✨ Strapi MCP is now Generally Available - let your agents manage your Strapi content ✨

App6 min read

E-commerce website with Nuxt.js, GraphQL, Strapi and Stripe (6/7)

March 29, 2022Updated on May 22, 2026

This tutorial is part of the « E-commerce website with Strapi, Nuxt.js, GraphQL and Stripe

Note: The source code is available on Github.

Introduction

You must be starving by now... I am sure you want to be able to order!

Deliveroo - Checkout page

Goals

Let’s create a new checkout page, and store orders in our database.

Step 1 - Create a new Orders collection type

To store the orders in our database, we will create a new content type.

Strapi - Content-Type Builder

  1. Go to Plugins Content-Type Builder in the main navigation.

  2. Click on Create new collection type.

  3. Type Order for the Display name, and click Continue.

  4. Click the Text field.

  5. Type address in the Name field.

  6. Click on Add another field.

  7. Choose the JSON field.

  8. Type dishes under the Name field, then click Finish.

  9. Click on Add another field.

  10. Choose the Number field, Number format: decimal (ex: 2.22).

  11. Type amount under the Name field, then click Finish.

  12. Click on Add another field.

  13. Choose the Relation field, create a many-to-one relation, user has many orders as below, then click Finish. User has many Orders - Relation field

  14. Finally, click Save and wait for Strapi to restart.

Now that we have created new fields for the orders collection type. We will take care of the permissions, same process as usual.

Step 2 - Set Roles & Permissions

We need to make sure that authenticated users can create new orders:

Strapi - Roles

  1. Click on General > Settings at the bottom of the main navigation.
  2. Under Users & Permissions plugin, choose Roles.
  3. Click the Authenticated role.
  4. Scroll down under Permissions.
  5. In the Permissions tab, find Order and click on it.
  6. Click the checkbox next to create.
  7. Finally, click Save.

In the next section, we will setup Stripe.js to get user's address and debit card information.

Step 3 - Setup Stripe.js

You are going to create a checkout page that will display your cart thanks to the Cart component and the Stripe form.

Deliveroo - Checkout page

Add Stripe to your frontend app, run:

    yarn add vue-stripe-elements-plus

In the nuxt.config.js file, add the Stripe script in the head object:

    module.exports = {
      // Global page headers: https://go.nuxtjs.dev/config-head
      head: {
        // ...other properties
        script: [{ src: 'https://js.stripe.com/v3/' }],
      },
    }

You can use Stripe.js’ APIs to tokenize customer information, collect sensitive payment details using customizable Stripe Elements, and accept payments with browser payment APIs like Apple Pay and the Payment Request API.

Step 4 - Creating a new checkout page

Create a new pages/checkout.vue, open the file with your text editor, and copy/paste the following code.

    // pages/checkout.vue
    <template>
      <div class="uk-container uk-container-xsmall">
        <h1 class="uk-heading-small">Checkout</h1>
        <div v-if="success" class="uk-alert-success" uk-alert>
          <a class="uk-alert-close" uk-close></a>
          <p>{{ success.message }}</p>
        </div>
        <div v-if="err" class="uk-alert-danger" uk-alert>
          <a class="uk-alert-close" uk-close></a>
          <p>{{ err.message }}</p>
        </div>
        <Cart :checkout="false" />
        <div class="uk-margin">
          <label class="uk-form-label">
            Address
            <input v-model="address" class="uk-input" type="email" />
          </label>
        </div>
        <div class="uk-margin-top">
          <StripeElements v-slot="{ elements }" ref="elms" :stripe-key="stripeKey">
            <StripeElement ref="card" type="card" :elements="elements" />
          </StripeElements>
          <button
            class="uk-button uk-button-secondary uk-margin-top uk-width-1-1"
            @click="pay"
          >
            Pay
          </button>
        </div>
      </div>
    </template>
    <script>
    import { StripeElements, StripeElement } from 'vue-stripe-elements-plus'
    import { mapGetters, mapMutations } from 'vuex'
    export default {
      components: {
        StripeElements,
        StripeElement,
      },
      data() {
        return {
          success: null,
          err: null,
          address: '',
          stripeKey: process.env.stripePublishable,
        }
      },
      computed: {
        ...mapGetters({
          username: 'auth/username',
          token: 'auth/token',
        }),
      },
      methods: {
        async pay() {
          // ref in template
          const groupComponent = this.$refs.elms
          const cardComponent = this.$refs.card
          // Get stripe element
          const cardElement = cardComponent.stripeElement
          const address = this.address
          const username = this.username
          let token = this.token
          this.$http.setToken(token, 'Bearer')
          try {
            // Access instance methods, e.g. createToken()
            token = await groupComponent.instance.createToken(cardElement)
          } catch (err) {
            this.err = err.response?.data?.error
          }
          try {
            await this.$http.$post('orders', {
              data: {
                address,
                amount: this.$store.getters['cart/price'],
                user: username,
                dishes: this.$store.getters['cart/items'],
                token,
              },
            })
            // this.emptyCart()
            this.success = {
              message: 'Payment completed successfuly',
            }
          } catch (err) {
            this.err = err.response?.data?.error
          }
        },
        ...mapMutations({
          emptyCart: 'cart/emptyList',
        }),
      },
    }
    </script>

Don’t forget to create a  `stripePublishable` property inside `env` object in your `nuxt.config.js` file:

    export default {
      env: {
        stripePublishable: process.env.STRIPE_PUBLISHABLE || '##PUBLISHABLE##'
      }
    }

Don't forget to replace ##PUBLISHABLE## by your public Stripe API key.

In this page, you display a form to get user's address and debit card information. You use the Stripe Elements system. When the form is submitted, you get a token from Stripe. Then, you create the order in your Strapi API.

You are now able to let users submit their order. Bon appétit! 🇫🇷

Step 5 - Setup Stripe API

Create a Stripe account, and navigate to API Keys.

If you have already used Stripe, you may know that the credit card information does not go through your backend server. Instead, the information is directly sent to the Stripe API. Then, your frontend receives a token. The id of the token must be sent to your backend which will create the Stripe charge.

Open the backend terminal, and install the stripe package:

    // Ctrl + C
    yarn add stripe

The Stripe Node library provides convenient access to the Stripe API from applications written in server-side JavaScript.

In order to integrate the Stripe logic, you need to update the create charge endpoint in your Strapi API.

    // src/api/order/controllers/order.js
    'use strict';
    const stripe = require('stripe')(process.env.STRIPE_KEY);
    /**
     *  order controller
     */
    const { createCoreController } = require('@strapi/strapi').factories;
    
    module.exports = createCoreController('api::order.order', ({ strapi }) =>  ({
      async create(ctx) {
        const {
          amount,
          address,
          dishes,
          token,
        } = ctx.request.body.data;
        try {
          // Charge the customer
          await stripe.charges.create({
            amount: amount,
            currency: 'eur',
            description: `Order ${new Date()} by ${ctx.state.user.id}`,
            source: token,
          });
    
          // Create the order
         const entity = await strapi.service('api::order.order').create({ amount, address, dishes, user: ctx.state.user.id }).
         const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
         return this.transformResponse(sanitizedEntity);
        } catch (err) {
          // return 500 error
          ctx.response.status = 500;
          return { error: { message: 'There was a problem creating the charge'}};
        }
      }
    }));

Create a .env file in the backend directory, then copy/pase the following code:

STRIPE_KEY=##Secret##

Don't forget to replace ##Secret## by your Stripe API Key.

Restart the Strapi backend with npm run develop.

Note: In a real-world example, the amount should be checked on the backend side and the list of dishes related to the command should be stored in a more specific Content Type called orderDetail.

Conclusion

In this section, we have created a new checkout page, which let user submit a form with their address and debit card information and used Stripe API to check the amount. 🚀 In the next (and last) section, you will learn how to deploy your Strapi & Nuxt.js applications.

Pierre BurgyChief Executive Officer

Pierre created Strapi with Aurélien and Jim back in 2015. He's a strong believer in open-source, remote and people-first organizations. You can also find him regularly windsurfing or mountain-biking!

App·26 min read

Build a To-Do App with Strapi GraphQL Plugin and Flutter

In this tutorial, we will set up a GraphQL endpoint in a Strapi backend along with Flutter, a powerful opensource UI...

·August 30, 2023
App·16 min read

How to build a To-do App using Next.js and Strapi

How to build a Todo App using Next.js and Strapi Updated July 2023 In this article, we will learn how to use , and to...

·August 29, 2023
How to setup Amazon S3 Upload Provider Plugin for your Strapi App
AppBeginner·14 min read

How to Set up Amazon S3 Upload Provider Plugin for Your Strapi App

Learn how to set up the Amazon S3 Upload Provider Plugin for your Strapi App to work with an Amazon S3 storage bucket.

·July 3, 2023