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
amountto thetransactionInitializemutation, and desired action such asAUTHORIZE. - In the
TRANSACTION_INITIALIZE_SESSIONwebhook the payment app validates the split (e.g. if it is allowed) and includesAUTHORIZEin allowed actions.
Remaining amount:
- Checkout passes the remaining
amountto thetransactionInitializemutation and desired action such asCHARGE. - In the
TRANSACTION_INITIALIZE_SESSIONwebhook, the payment app validates the split (e.g., if it is allowed) and includesCHARGEin allowed actions.
- Process transactions:
- Calling
transactionProcesswithactionset toAUTHORIZEfor the first transaction andCHARGEfor 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
webhookevents such asORDER_CREATEDto 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
privateMetadatainstead.
- 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.