Checkout cookbook
Free orders
You might have a use case where you want to allow customers to complete a checkout without needing to pay. This can be useful for scenarios like:
- Free samples
- Free digital downloads
To allow for this, you can create a checkout with a total price of 0
. This can be achieved by adding a free item to the checkout or by applying a discount code that reduces the total price to 0
.
Example of checkout flows
Creating order before processing payment
The advantage of this flow that prices, discount and stock are frozen before payment is created.
Processing payment before creating an order
Creating order from checkout without Payments
Creating unpaid orders is possible for channels that have allowUnpaidOrders
setting enabled.
If you wish to bypass this setting, you can use orderCreateFromCheckout
.
The operation requires the HANDLE_CHECKOUTS
permission and can be called only by the App. Calling checkoutPaymentCreate
and checkoutComplete
is not necessary.
The created order can be marked as paid by staff customer/app with the MANAGE_ORDERS
permission.
To create an order from checkout we can pass id of the checkout to orderCreateFromCheckout
.
- GraphQL
- Result
mutation {
orderCreateFromCheckout(
id: "Q2hlY2tvdXQ6YTcxYjRjZDQtNzI1NS00ZjAyLWEzOTEtMDQxYWQ0MmNjZWNk"
removeCheckout: true
) {
order {
id
}
}
}
{
"data": {
"orderFromCheckoutCreate": {
"order": {
"id": "T3JkZXI6MjI="
}
}
},
"extensions": {
"cost": {
"requestedQueryCost": 0,
"maximumAvailable": 50000
}
}
}
Partial/Split payments
Common use cases of splitting payments on a single order are:
- Charging only for part of the order and another part after the fulfillment.
- Orders are split into fulfillment's paid separately to each vendor.
- Paying part with gift card, and the rest with credit card.
- Authorize part of the basket as a pre-order payment (without charging) and change it immediately before fulfillment.
Possible Approach
Prepare two transactions, one that is only authorized and one that is charged immediately.
- Initialize transactions:
For the authorized-only transaction:
- Checkout passes
amount
to thetransactionInitialize
mutation, and desired action such asAUTHORIZE
. - In the
TRANSACTION_INITIALIZE_SESSION
webhook the payment app validates the split (e.g. if it is allowed) and includesAUTHORIZE
in allowed actions.
Remaining amount:
- Checkout passes the remaining
amount
to thetransactionInitialize
mutation and desired action such asCHARGE
. - In the
TRANSACTION_INITIALIZE_SESSION
webhook, the payment app validates the split (e.g., if it is allowed) and includesCHARGE
in allowed actions.
- Process transactions:
- Calling
transactionProcess
withaction
set toAUTHORIZE
for the first transaction andCHARGE
for the second transaction.
While it is possible to call transactionInitialize
and transactionProcess
directly from the storefront (client-side), it is recommended that these operations be executed from the backend (server-side), which would be more resilient and maintainable.
Product personalization
Common use cases of product personalization are:
- Customized products (e.g., engraved jewelry, custom t-shirts)
- Packaging preferences
- Product configuration such as PC components, furniture, cars, etc.
- Delivery preferences for each item
The personalization can be achieved by adding additional metadfields
fields to the CheckoutLine
object.
With the following mutations:
The metdafields
will be copied to the OrderLine
after checkout completion.
Additional steps might be required to process such fields in the fulfillment process, such as:
- Pass the fields to the ERP system
- Listen to
webhook
events such asORDER_CREATED
to process the fields - Custom pricing
-
- Metadata can be added without permissions via front-end API; thus, it might require extra validation steps on the server or write metadata lines with server permissions to
privateMetadata
instead.
- Metadata can be added without permissions via front-end API; thus, it might require extra validation steps on the server or write metadata lines with server permissions to
Custom product pricing
To set prices on checkout lines dynamically you can use the checkoutLinesUpdate
mutation.
See example repository for creating custom pricing middleware.
Using phone number instead as identity
You can use a phone number instead of an email address to identify customers. While Saleor always requires email to create orders, you can use the email
field as a phone number or other semantic meaning. For example: 123456789@noreply.yourcompany.com
. Make sure always to use domain names you own, to avoid leaking user data.
Order approvals and quotes
Example order approval flow:
- Customer places an order without payment
- Admin reviews the order and provides a final price in the form of a discount
- Customer pays the final price
- The order is shipped
Channel setting should enable allowUnpaidOrders
to create orders without payments, (settings can be set via API or Dashboard -> Order -> Order settings cogwheel).
To require manual approval of orders in the dashboard, set the automaticallyConfirmAllNewOrders
to false
(can be set via the dashboard Configuration -> Channel).
To arrange communication between flow between admin see Order related webhooks
.
Subscriptions
Common use cases of subscriptions are:
- Create a subscription for a product that gets fulfilled periodically.
- Create membership subscriptions that do not require fulfillment.
A subscription service can be implemented as a standalone service that communicates with Saleor to write orders, update payments, and fulfill orders. If admins need to manage subscriptions, you can use custom app to create a dedicated UI in the Saleor dashboard to talk to your subscription service.