The ScandiPWA checkout page enables users to provide the necessary information to complete an order, similar to Magento 2.
When the checkout page needs to be loaded, ScandiPWA renders the Checkout component.
The Checkout component defines three default steps to complete an order. The first step is shipping, which handles the customer's address and delivery options. The second step is billing, which is divided into handling billing address and payment method options and completing the transaction. The final step is called “details”, which displays the transaction result.
Understanding these steps is essential for customizing the checkout process. For example, adding a custom payment method, which often involves extending the savePaymentMethodAndPlaceOrder function of the Checkout container. Which sometimes may need to redirect the user to a third-party site and then properly handle the return.

The main responsibility of the Checkout component, which renders the checkout page, is to display a summary of the order and handle the various steps of the checkout process:
<aside> ✅ You can check the "Network" tab in your browser's developer tools to see the GraphQL responses. This can help you to understand!
</aside>
<aside> ℹ️ If guest checkout is allowed and the user is not authenticated, this step includes an email field to save in the cart, and later the user can register an account. This feature can be disabled in the admin.
</aside>
In this step, ScandiPWA renders the CheckoutShipping component. This component is responsible for rendering the shipping address form, delivery options, and a button to proceed to billing.
renderContent function return from the CheckoutShipping component.
The renderAddressBook function essentially displays the CheckoutAddressBook component, which distinguishes between signed-in users and guest users.
The renderDelivery function will display the CheckoutDeliveryOptions component, which shows the available delivery options for the user to select.
The renderActions renders the “Proceed to billing” button.
Note that when the user clicks on this button, the onShippingSuccess function of the CheckoutShipping container is called.
ScandiPWA sends a GraphQL mutation to update the shipping methods and costs when the user updates the shipping address.
What happens when the user clicks to proceed to billing?
After the user has selected the shipping method and clicked to proceed:

If the user is not authenticated and guest checkout is allowed, make a GraphQL mutation to set the guest email on the cart.
Send a GraphQL mutation to save the provided address in the cart as both shipping and billing addresses.
This mutation also returns the payment methods that will be used in the billing step.
saveAddressInformation mutation returnProceeds to the next step and renders the CheckoutBilling component in place of the CheckoutShipping component.
In this step, The Checkout component renders CheckoutBilling.
CheckoutBilling componentIn the CheckoutBilling component render method:
The renderAddresses function is basically responsible for allowing the user to select the billing address.
By default, the billing address is set to be the same as the shipping address. However, the user can uncheck this option and view their registered addresses if they are logged in. Alternatively, if the user has no registered address or is a guest user, they can fill out a form to add a new one.
The renderPayments function basically renders the CheckoutPayments component if payment methods are available. It is responsible for enabling the user to select the payment method.
<aside>
✅ Note that in the previous step, the saveAddressInformation mutation returned the available payment methods.
</aside>
The CheckoutPayments will render a heading, the payments options, and the selected payment:
renderContent function return from the CheckoutPayments component
renderHeading function by default only renders ‘Payment method’ in a h2.
The renderPayments function will call the renderPayment function for each payment method. This will define what will be rendered for each payment method option.
renderPayment function from CheckoutPayments componentBy default, the CheckoutPayment component is rendered for every payment method option. However, when working with payment integrations, it is common to extend this functionality to render a different component for different types of payment methods.
The renderSelectedPayment function utilizes the paymentRenderMap to check if there is anything associated with the selected payment method. If there is, it renders it.
paymentRenderMap: Record<string, () => ReactElement> = {
[PaymentMethods.PURCHASE_ORDER]: this.renderPurchaseOrderPayment.bind(this),
};
In this case, if the selected method is PURCHASE_ORDER the renderSelectedPayment will render the renderPurchaseOrderPayment function.
A common feature is to extend the paymentRenderMap object to include a button to replace the default complete order button.
The renderTAC - renders terms and conditions if accepted.
The renderActions - will basically render the button to complete the order.
Note that when the user clicks the complete order button, the onBillingSuccess function of the CheckoutBilling container is called.
The renderPopup - renders the popup message from the terms and conditions if any.
What happens when the user clicks to complete the order?
When the user clicks the "Complete Order" button, the onBillingSuccess function of the CheckoutBilling container is called to process the address and payment method form and save this information using the savePaymentInformation function from the Checkout container.

Process the billing address and payment method information on the form. This is done in the onBillingSuccess function of the CheckoutBilling container.
Check if the user is authenticated. If the user is not authenticated, it will either save the email of the user as a guest by calling the setGuestEmailOnCart mutation or create a user depending on the component configuration.
Save the billing address information. This is done by sending the GraphQL mutation setBillingAddressOnCart defined in the getSetBillingAddressOnCart function of the Checkout.query.
Save the payment information. This is done by sending the GraphQL mutation setPaymentMethodOnCart defined in the getSetPaymentMethodOnCartMutation function of the Checkout.query.
proceeds to complete the transaction.
<aside> ⚠️ Note that in reality, this process is done all at once. However, for educational purposes, the order placement will be handled separately in the next section.
</aside>
In this step, ScandiPWA creates an order using the placeOrder mutation. For this to be possible, ScandiPWA must have already:
<aside> ✅ Note that all of this is done during the shipping and billing steps.
</aside>

When ScandiPWA needs to complete a transaction, it:
Sends a placeOrder mutation to convert the cart into an order and returns the order ID.
Remove cart information and payment totals from localStorage. This is important to avoid conflicts with the cart that will be created.
Create an empty cart. This is important for enabling the user to make another purchase.
mapDispatchToPropsNote that if the user is signed in, it will call the resetCart prop defined in the mapDispatchToProps. For guest users, it will call the resetGuestCart prop. Both of these are responsible for calling the createEmptyCart mutation.
Display order information.
<aside> ✅ The ScandiPWA marketplace offers a variety of extensions to integrate payment methods easily!
</aside>
By default, ScandiPWA only enables payment methods that do not require any additional steps after sending the placeOrder mutation.
But you may want to add a payment method that requires additional behavior before or after placing the order. One example is adding a credit card payment that needs to redirect the user to a third-party site to complete the payment.

An example of this is the Mollie payment integration, which extends ScandiPWA checkout to:
Redirect the user to a third-party site to complete the payment after placing the order. This is usually done by extending the savePaymentMethodAndPlaceOrder function of the Checkout.container.js.
Process the customer return from the third-party site. This is usually done by extending the __construct and componentDidMount functions of the Checkout container.
To implement a payment method is necessary to understand how the payment process work and adjust ScandiPWA components to follow the same pattern.
<aside> ✅ A good starting point is to study the payment integration for Magento, particularly the frontend layout.
</aside>