Skip to main content

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.

mutation {
orderCreateFromCheckout(
id: "Q2hlY2tvdXQ6YTcxYjRjZDQtNzI1NS00ZjAyLWEzOTEtMDQxYWQ0MmNjZWNk"
removeCheckout: true
) {
order {
id
}
}
}

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.

  1. Initialize transactions:

For the authorized-only transaction:

  • Checkout passes amount to the transactionInitialize mutation, and desired action such as AUTHORIZE.
  • In the TRANSACTION_INITIALIZE_SESSION webhook the payment app validates the split (e.g. if it is allowed) and includes AUTHORIZE in allowed actions.

Remaining amount:

  • Checkout passes the remaining amount to the transactionInitialize mutation and desired action such as CHARGE.
  • In the TRANSACTION_INITIALIZE_SESSION webhook, the payment app validates the split (e.g., if it is allowed) and includes CHARGE in allowed actions.
  1. Process transactions:
  • Calling transactionProcess with action set to AUTHORIZE for the first transaction and CHARGE for the second transaction.
note

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 as ORDER_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.

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:

  1. Customer places an order without payment
  2. Admin reviews the order and provides a final price in the form of a discount
  3. Customer pays the final price
  4. 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.