Checkout Flow
Learn how to customize the checkout process in Spree.
Overview
The Spree checkout process has been designed for maximum flexibility. It’s been redesigned several times now, each iteration has benefited from the feedback of real-world deployment experience. It is relatively simple to customize the checkout process to suit your needs. Secure transmission of customer information is possible via SSL and credit card information is never stored in the database.
The Checkout Flow DSL
Spree comes with a new checkout DSL that allows you succinctly define the different steps of your checkout. This new DSL allows you to customize just the checkout flow, while maintaining the unrelated admin states, such as “canceled” and “resumed”, that an order can transition to. Ultimately, it provides a shorter syntax compared with overriding the entire state machine for the Spree::Order
class.
The default checkout flow for Spree is defined like this, adequately demonstrating the abilities of this new system:
we can pass a block on each checkout step definition and work some logic to figure if the step is required dynamically. e.g. the confirm step might only be necessary for payment gateways that support payment profiles.
These conditional states present a situation where an order could transition from delivery to one of payment, confirm or complete. In the default checkout, we never want to transition from delivery to confirm, and therefore have removed it using the remove_transition
method of the Checkout DSL. The resulting transitions between states look like the image below:
These two helper methods are provided on Spree::Order
instances for your convenience:
checkout_steps
- returns a list of all the potential states of the checkout.has_step?
- Used to check if the current order fulfills the requirements for a specific state.
If you want a list of all the currently available states for the checkout, use the checkout_steps
method, which will return the steps in an array.
Default Checkout Steps
The Spree checkout process consists of the following steps. With the exception of the Registration step, each of these steps corresponds to a state of the Order object:
- Shipping Address and Contact Information
- Delivery Options Shipping Method
- Payment and Billing Information
- Confirmation (optional)
The following sections will provide a walk-through of checkout from a user’s perspective, and offer some information on how to configure the default behavior of the various steps.
Shipping Address and Contact Information
This step allows the customer to add shipping information and contact information. Customers have also option to sign in or create an account. For payment methods such as Stripe customers can use quick checkout option via payment wallets such as Apple Pay, Google Pay, etc and skip the rest of the checkout process.
The address fields include a select box for choosing state/province. If there are no states configured for a particular country, the select box will be replaced by a text field instead.
The list of countries that appear in the country select box can also be configured. Spree will list all countries by default, but you can configure exactly which countries you would like to appear. The list can be limited to a specific set of countries by setting the Store’s checkout zone.
Delivery Options
During this step, the user may choose a delivery method. Spree assumes the list of shipping methods to be dependent on the shipping address. If there are multiple shipments eg. different Stock Locations or Vendors, the user will be asked to select shipping method for each shipment.
Payment
This step is where the customer provides payment and billing information. Spree does not store any payment information in the database. For payment methods such as Stripe, we use Stripe JavaScript SDKs to render their payment form inside the checkout page, fully compliant with PCI DSS standards.
Besides Credit Card, Wallets and other 3rd party payment methods, Spree also supports Store Credit and Gift Cards (Spree 5.1+ only) which can be used to pay for the entire order or part of the order.
For more information about payments, please see the Payments guide.
Confirmation
This is the final opportunity for the customer to review their order before submitting it to be processed. Users have the opportunity to return to any step in the process using either the back button or by clicking on the appropriate step in the “progress breadcrumb.”
This step is disabled by default, but can be enabled by two ways:
-
globally for all orders by setting a preference in
config/initializers/spree.rb
: -
conditionally for specific orders by overriding the
confirmation_required?
method inSpree::Order
with a decorator, eg.app/models/spree/order_decorator.rb
file:
Adding Logic Before or After a Particular Step
The state_machines gem allows you to implement callbacks before or after transitioning to a particular step. These callbacks work similarly to Active Record Callbacks in that you can specify a method or block of code to be executed prior to or after a transition. If the method executed in a before_transition returns false, then the transition will not execute.
So, for example, if you wanted to verify that the user provides a valid zip code before transitioning to the delivery step, you would first implement a valid_zip_code?
method, and then tell the state machine to run this method before that transition, placing this code in a file called app/models/spree/order_decorator.rb
:
This callback would prevent transitioning to the delivery
step if valid_zip_code?
returns false.
Modifying the checkout flow
To add or remove steps to the checkout flow, you can use the insert_checkout_step and remove_checkout_step helpers respectively.
The insert_checkout_step
method takes a before
or after
option to determine where to insert the step:
The remove_checkout_step
will remove just one checkout step at a time:
What will happen here is that when a user goes to checkout, they will be asked to potentially fill in their payment details and then potentially confirm the order. This is the default behavior of the payment and the confirm steps within the checkout. If they are not required to provide payment or confirmation for this order then checking out this order will result in its immediate completion.
To completely re-define the flow of the checkout, use the checkout_flow
helper:
Was this page helpful?