Checkout Flow
Once the customer has added the desired products to the active order, it's time to check out.
This guide assumes that you are using the default OrderProcess, so if you have defined a custom process, some of these steps may be slightly different.
In this guide, we will assume that an ActiveOrder
fragment has been defined, as detailed in the
Managing the Active Order guide, but for the purposes of
checking out the fragment should also include customer
shippingAddress
and billingAddress
fields.
Add a customer
Every order must be associated with a customer. If the customer is not logged in, then the setCustomerForOrder
mutation must be called. This will create a new Customer record if the provided email address does not already exist in the database.
If the customer is already logged in, then this step is skipped.
- Mutation
- Variables
mutation SetCustomerForOrder($input: CreateCustomerInput!) {
setCustomerForOrder(input: $input) {
...ActiveOrder
...on ErrorResult {
errorCode
message
}
}
}
{
"input": {
"title": "Mr.",
"firstName": "Bob",
"lastName": "Dobalina",
"phoneNumber": "1234556",
"emailAddress": "b.dobalina@email.com",
}
}
Set the shipping address
The setOrderShippingAddress
mutation must be called to set the shipping address for the order.
- Mutation
- Variables
mutation SetOrderShippingAddress($input: CreateAddressInput!) {
setOrderShippingAddress(input: $input) {
...ActiveOrder
...on ErrorResult {
errorCode
message
}
}
}
{
"input": {
"fullName": "John Doe",
"company": "ABC Inc.",
"streetLine1": "123 Main St",
"streetLine2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "10001",
"countryCode": "US",
"phoneNumber": "123-456-7890",
"defaultShippingAddress": true,
"defaultBillingAddress": false
}
}
If the customer is logged in, you can check their existing addresses and pre-populate an address form if an existing address is found.
- Query
- Result
query GetCustomerAddresses {
activeCustomer {
id
addresses {
id
fullName
company
streetLine1
streetLine2
city
province
postalCode
country {
code
name
}
phoneNumber
defaultShippingAddress
defaultBillingAddress
}
}
}
{
"data": {
"activeCustomer": {
"id": "123456",
"addresses": [
{
"id": "123",
"fullName": "John Doe",
"company": "",
"streetLine1": "123 Main St",
"streetLine2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "10001",
"country": {
"code": "US",
"name": "United States"
},
"phoneNumber": "123-456-7890",
"defaultShippingAddress": true,
"defaultBillingAddress": false
},
{
"id": "124",
"fullName": "John Doe",
"company": "",
"streetLine1": "456 Elm St",
"streetLine2": "",
"city": "Los Angeles",
"province": "CA",
"postalCode": "90001",
"country": {
"code": "US",
"name": "United States"
},
"phoneNumber": "987-654-3210",
"defaultShippingAddress": false,
"defaultBillingAddress": true
}
]
}
}
}
Set the shipping method
Now that we know the shipping address, we can check which shipping methods are available with the eligibleShippingMethods
query.
- Query
- Result
query GetShippingMethods {
eligibleShippingMethods {
id
price
description
}
}
{
"data": {
"eligibleShippingMethods": [
{
"id": "1",
"price": 545,
"description": "Standard Shipping"
},
{
"id": "2",
"price": 1250,
"description": "Expedited Shipping"
},
{
"id": "3",
"price": 1695,
"description": "Overnight Shipping"
}
]
}
}
The results can then be displayed to the customer so they can choose the desired shipping method. If there is only a single result, then it can be automatically selected.
The desired shipping method's id is the passed to the setOrderShippingMethod
mutation.
mutation SetShippingMethod($id: [ID!]!) {
setOrderShippingMethod(shippingMethodId: $id) {
...ActiveOrder
...on ErrorResult {
errorCode
message
}
}
}
Add payment
The eligiblePaymentMethods
query can be used to get a list of available payment methods.
This list can then be displayed to the customer, so they can choose the desired payment method.
- Query
- Result
query GetPaymentMethods {
eligiblePaymentMethods {
id
name
code
isEligible
}
}
{
"data": {
"eligiblePaymentMethods": [
{
"id": "1",
"name": "Stripe",
"code": "stripe",
"isEligible": true
},
{
"id": "2",
"name": "Apple Pay",
"code": "apple-pay",
"isEligible": true
}
{
"id": "3",
"name": "Pay on delivery",
"code": "pay-on-delivery",
"isEligible": false
}
]
}
}
Next, we need to transition the order to the ArrangingPayment
state. This state ensures that no other changes can be made to the order
while the payment is being arranged. The transitionOrderToState
mutation is used to transition the order to the ArrangingPayment
state.
- Query
- Variables
mutation TransitionToState($state: String!) {
transitionOrderToState(state: $state) {
...ActiveOrder
...on OrderStateTransitionError {
errorCode
message
transitionError
fromState
toState
}
}
}
{
"state": "ArrangingPayment"
}
At this point, your storefront will use an integration with the payment provider to collect the customer's payment details, and then the exact sequence of API calls will depend on the payment integration.
The addPaymentToOrder
mutation is the general-purpose mutation for adding a payment to an order.
It accepts a method
argument which must corresponde to the code
of the selected payment method, and a metadata
argument which is a JSON object containing any additional information required by that particular integration.
For example, the demo data populated in a new Vendure installation includes a "Standard Payment" method, which uses the dummyPaymentHandler
to simulate a payment provider. Here's how you would add a payment using this method:
- Mutation
- Variables
mutation AddPaymentToOrder($input: PaymentInput!) {
addPaymentToOrder(input: $input) {
...ActiveOrder
...on ErrorResult {
errorCode
message
}
}
}
{
"method": "standard-payment",
"metadata": {
"shouldDecline": false,
"shouldError": false,
"shouldErrorOnSettle": false,
}
}
Other payment integrations have specific setup instructions you must follow:
Stripe
Our StripePlugin docs
describe how to set up your checkout to use Stripe.
Braintree
Our BraintreePlugin
docs describe how to set up your checkout to use Braintree.
Mollie
Our MolliePlugin
docs describe how to set up your checkout to use Mollie.
Other payment providers
For more information on how to integrate with a payment provider, see the Payment guide.
Display confirmation
Once the checkout has completed, the order will no longer be considered "active" (see the OrderPlacedStrategy
) and so the activeOrder
query will return null
. Instead, the orderByCode
query can be used to retrieve the order by its code to display a confirmation page.
- Query
- Variables
query GetOrderByCode($code: String!) {
orderByCode(code: $code) {
...Order
}
}
{
"code": "PJGY46GCB1EDU9YH"
}
By default Vendure will only allow access to the order by code for the first 2 hours after the order is placed if the customer is not logged in.
This is to prevent a malicious user from guessing order codes and viewing other customers' orders. This can be configured via the OrderByCodeAccessStrategy
.