Steps to creating a checkout

In this article, we'll you through the steps needed to create a checkout Frontastic componentsFrontastic components - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. based on the Frontastic starter componentsFrontastic starter components - Frontastic components that come with each Frontastic project that can be copied into your own project to use. Known in code as `boost theme`., add a checkout master page, and get the payments working. You'll need to integrate with a payment provider, set up basic commercetools data, and go through the PayPal integration guide (if you want to add it).

📘

Requirements for these steps

You're using commercetools and Adyen as the payment provider, plus you've already created a cart Frontastic componentsFrontastic components - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code..

Checkout Frontastic component

You can use the Frontastic starter componentsFrontastic starter components - Frontastic components that come with each Frontastic project that can be copied into your own project to use. Known in code as `boost theme`. package to create your checkout Frontastic componentsFrontastic components - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code.. If you prefer, you can create it on your own but please note that the steps in this tutorial will follow the assumption that you're using our version. If you haven't created a Frontastic componentsFrontastic components - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. before, see the Tastics article.

The version of the checkout Frontastic componentsFrontastic components - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. comes with the below features:

  • 3 checkout steps: Address, overview, and payment
  • Full commercetools integration: Shipping methods, taxes, zones, orders, and languages
  • Supported payment methods: PayPal, Credit card, Sofort, Paysafecard, GiroPay, and Klarna
  • Account creation isn't necessary
  • Logged in user's information is reused in the address tab

And the below features aren't supported:

  • No additional user login page
  1. Copy the schema.json file and the tastic.jsx file from your GitHub project repository.

We've put them below as well if you just want to copy the code from here:

{
    "tasticType": "frontastic/boost/checkout",
    "name": "Checkout",
    "icon": "menu",
    "category": "Checkout",
    "schema": [
        {
            "name": "Terms and agreements",
            "fields": [
                {
                    "label": "Policy text",
                    "field": "policy",
                    "type": "markdown"
                }
            ]
        }
    ]
}
import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'

import tastify from '@frontastic/catwalk/src/js/helper/tastify'
import app from '@frontastic/catwalk/src/js/app/app'
import Entity from '@frontastic/catwalk/src/js/app/entity'

import DefaultLoader from 'Molecules/Loaders/DefaultLoader/index'
import CheckoutPanels from 'Molecules/Layout/CheckoutPanels'

import EmptyState, { icons } from 'Organisms/EmptyState'
import { injectIntl, intlShape } from 'react-intl'

const CheckoutTastic = ({ intl, cart, context, data }) => {
    const [countries, setCountries] = useState([])

    useEffect(() => {
        app.getLoader('cart').getShippingMethods().then(response => {
            let c = []

            /* eslint-disable no-unused-expressions */
            response.shippingMethods?.forEach(method => {
                /* eslint-disable no-unused-expressions */
                method.rates?.forEach(rate => {
                    /* eslint-disable no-unused-expressions */
                    rate.locations?.forEach(location => {
                        if (!c.includes(location.country)) {
                            c.push(location.country)
                        }
                    })
                })
            })

            setCountries(c)
        })
    }, [context.locale])

    if (!cart || countries.length === 0) {
        return <DefaultLoader />
    }

    if (cart && cart.loaded && cart.data && cart.data.lineItems.length === 0) {
        const title = intl.formatMessage({ id: 'cart.emptyCart.text' })
        const actionLabel = intl.formatMessage({ id: 'checkout.backToShop' })

        return (
            <EmptyState
                icon={icons.EMOTION_SAD}
                iconColor='text-neutral-900'
                title={title}
                action={(e) => {
                    e.preventDefault()
                    app.getRouter().history.replace('/')
                }}
                actionLabel={actionLabel}
            />
        )
    }

    if (cart && cart.loaded && cart.data && cart.data.lineItems && cart.data.lineItems.length > 0) {
        const anyProductOutOfStock = cart.data.lineItems.some(product => product.variant.isOnStock === false)

        if (anyProductOutOfStock) {
            const title = intl.formatMessage({ id: 'checkout.outOfStock' })
            const actionLabel = intl.formatMessage({ id: 'checkout.backToCart' })

            return (
                <EmptyState
                    icon={icons.EMOTION_SAD}
                    iconColor='text-neutral-900'
                    title={title}
                    action={(e) => {
                        e.preventDefault()
                        app.getRouter().push('Frontastic.Frontend.Master.Checkout.cart')
                    }}
                    actionLabel={actionLabel}
                />
            )
        }
    }

    if (context.session.loggedIn && cart && cart.loaded && cart.data && (!cart.data.shippingAddress || !cart.data.shippingAddress.firstName)) {
        cart.data.email = context.account.email

        context.account.addresses?.forEach(address => {
            if (address.isDefaultBillingAddress) {
                cart.data.billingAddress = address
            }

            if (address.isDefaultShippingAddress) {
                cart.data.shippingAddress = address
            }
        })

        if (cart.data.billingAddress && !cart.data.shippingAddress) {
            cart.data.shippingAddress = cart.data.billingAddress
        } else if (cart.data.shippingAddress && !cart.data.billingAddress) {
            cart.data.billingAddress = cart.data.shippingAddress
        }
    }

    if (cart.loading) {
        if (!cart.data || !(countries.length > 0)) {
            return <DefaultLoader />
        } else {
            return (
                <CheckoutPanels
                    isLoading
                    app={app}
                    cart={cart}
                    data={cart.data}
                    countries={countries}
                    policy={data.policy}
                />
            )
        }
    }

    return (
        <CheckoutPanels
            app={app}
            cart={cart}
            data={cart.data}
            countries={countries}
            policy={data.policy}
        />
    )
}

CheckoutTastic.propTypes = {
    intl: intlShape.isRequired,
    cart: PropTypes.instanceOf(Entity),
    context: PropTypes.object.isRequired,
    data: PropTypes.object.isRequired,
}

export default tastify({ translate: true, connect: { cart: true, context: true } })(injectIntl(CheckoutTastic))

Be sure to check that the packages are imported into your project and the local dependencies are in the right place.

  1. Update your tastics.js file to include the new checkout Frontastic component, for example:
const CheckoutTastic = asyncComponent({ import: () => import('./checkout/tastic'), height: {} })

export default (() => {
    return {
        'frontastic/boost/checkout': CheckoutTastic,
          }
})()
  1. Upload your schema.json file to the Components section of the Frontastic studio:

You're now ready to create your checkout dynamic pagedynamic page - A type of page that creates the default layout of pages that use the same structure but with different data, for example, a Product Details Page, wishlist, cart, search, and so on. Previously known as `master page`..

Checkout dynamic page

Within the Dynamic pages area of the Frontastic studioFrontastic studio - The interface you use to manage, build, and edit all areas of your project and commerce sites. Previously known as `backstage`., you'll find the Checkout folder and it's here that you can create your checkout dynamic pagedynamic page - A type of page that creates the default layout of pages that use the same structure but with different data, for example, a Product Details Page, wishlist, cart, search, and so on. Previously known as `master page`..

  1. Open the Frontastic studio, select Dynamic pages, and select Checkout under the Checkout section:
  1. Select Default Page under the Dynamic page rules header, then click + New page version under the Page versions header, then input a name, and click Save
  1. Add a header, a footer, and a 1 layout element to your page, then add the Checkout component
  1. Input the terms and agreements text in the markdown editor
  1. Preview your page and Save it
  1. Click the more icon and select Make default

Now you have a checkout page to point to, let's get it added to your code.

Payments

Now we've got the basic checkout created, we need to create a way for our customers to make a payment.

We'll be using Adyen for our Payment Service Provider (PSP). Make sure you have your Adyen account details and make sure your risk management policy is set up. Then you can go through the steps below:

  1. In the API credentials section, select Create new web service user and input the information as below:
  1. Add your Adyen API configuration information in your project.yml in the config folder of your project repository, for example:
payment:
    adyen:
      apiKey: "ThisisourapiKeyforAdyen==-gkoNSuhoc77v0ZG0rVeS53otT9bqL1sbjaGm6s2DyCQ=-}f<gG4qM~q(F6#dK"
      merchantAccount: Frontastic
      clientKey: test_clientkey
      environment: test
      originKeys:
        "http://english-demo.frontastic.io": pub.v2.8015930790681055.aHR0cDovL2VuZ2xpc2gtZGVtby5mcm9udGFzdGljLmlvLmxvY2Fs.FfuaCwZXL65Fx_0vohp03RqPmHn85onb_KZc4yWRkXM
  1. Add the new CSP policy rules into the project.yml as well
policy:
    connect-src:
    - https://checkoutshopper-live.adyen.com
    - https://checkoutshopper-test.adyen.com
    - https://www.paypal.com
    - https://www.sandbox.paypal.com
    - https://pay.google.com
    default-src:
    - https://checkoutshopper-live.adyen.com
    - https://checkoutshopper-test.adyen.com
    - https://www.paypal.com
    - https://www.sandbox.paypal.com
    - https://pay.google.com
    frame-src:
    - https://checkoutshopper-live.adyen.com
    - https://checkoutshopper-test.adyen.com
    - https://pal-test.adyen.com
    - https://www.paypal.com
    - https://www.sandbox.paypal.com
    - https://pay.google.com
    style-src:
    - https://checkoutshopper-live.adyen.com
    - https://checkoutshopper-test.adyen.com
    - https://www.paypal.com
    - https://www.sandbox.paypal.com
    - https://pay.google.com
    - http://fonts.googleapis.com
    script-src:
    - https://checkoutshopper-live.adyen.com
    - https://checkoutshopper-test.adyen.com
    - https://www.paypal.com
    - https://www.sandbox.paypal.com
    - https://pay.google.com
  1. Add the Adyen JS and CSS files in layout.html.twig in the templates folder your GitHub project repository
<link rel="stylesheet"
     href="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.21.1/adyen.css"
     integrity="sha384-KM3xJKzswGJ0xqiPCOHrWUtn0i0LHqEngauvYxSfy0eRtqcImL7ArxjV2HVgeRJ/"
     crossorigin="anonymous">

<script src="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.21.1/adyen.js"
     integrity="sha384-qgB03MgLihAbvkTmWIkmZxFUxyAqJ4Ozk1My6beIRqit6+8e5HFg8ysln5y5FSw0"
     crossorigin="anonymous"></script>

commercetools set up

We also need to make sure that our commercetools account has all the basic data we need to use for our checkout.

  1. Open your commercetools project, go to Project settings, then input the currencies, languages, countries you need

🚧

The languages in commercetools need to be exactly the same languages that are in your project.yml.

languages:
  - de_DE
  - en_GB
defaultLanguage: en_GB
  1. Add the zones you need your shop to be active in
  1. Add any taxes that you need to
  1. Add the shipping methods you'll be using

Now you have all the systems set up, and they can communicate together to display the right data to your users.

Checkout success

The last step is to make a checkout success Frontastic componentFrontastic component - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. and dynamic pagedynamic page - A type of page that creates the default layout of pages that use the same structure but with different data, for example, a Product Details Page, wishlist, cart, search, and so on. Previously known as `master page`.. That way your customers will know that their payment has been successful.

  1. Create a checkout success Frontastic component, you can use the below code:
{
    "tasticType": "frontastic/boost/checkout-success",
    "name": "Checkout success",
    "icon": "menu",
    "category": "Checkout",
    "schema": []
}
import React from 'react'
import PropTypes from 'prop-types'

import tastify from '@frontastic/catwalk/src/js/helper/tastify'
import app from '@frontastic/catwalk/src/js/app/app'
import Entity from '@frontastic/catwalk/src/js/app/entity'

import CheckoutSuccess from '../../patterns/molecules/CheckoutSuccess'
import CheckoutError from '../../patterns/molecules/CheckoutError'

const CheckoutSuccessTastic = ({ order }) => {
    if (order.isComplete()) {
        return (
            <CheckoutSuccess
                id={order.data.orderId}
                email={order.data.email}
                onClick={() => {
                    return app.getRouter().history.replace('/')
                }}
            />
        )
    } else if (order.loaded && order.error) {
        return (
            <CheckoutError
                onClick={() => {
                    app.getRouter().replace('Frontastic.Frontend.Master.Checkout.checkout')
                }}
            />
        )
    } else {
        app.getRouter().history.replace('/')
        return null
    }
}

CheckoutSuccessTastic.defaultProps = {}

CheckoutSuccessTastic.propTypes = {
    order: PropTypes.instanceOf(Entity).isRequired,
}

export default tastify({ translate: true, connect: { order: true } })(CheckoutSuccessTastic)
  1. Add it to your tastics.js file, for example:
...
const CheckoutSuccessTastic = asyncComponent({ import: () => import('./checkout-success/tastic'), height: {} })
...
        'frontastic/boost/checkout-success': CheckoutSuccessTastic,
...
  1. Upload the schema.json to the Frontastic studio
  1. Go to Dynamic pages and select Checkout finished
  1. Click + New page version, input a name, and click Save
  1. Add a header, a footer, and a 1 layout element to your page, then add the Checkout success Frontastic component
  1. Preview and Save your page

  2. Click the more icon and select Make default

You'll now have a working checkout and success page for your customers!


Did this page help you?