> Documentation index: [Saleor](/llms.txt) · [This section](/developer/llms.txt)
> Source: https://docs.saleor.io/developer/checkout/cookbook

# Checkout cookbook

<a id="free-orders"></a>

## 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`.

<a id="example-of-checkout-flows"></a>

## Example of checkout flows

<a id="creating-order-before-processing-payment-using-custom-app"></a>

### Creating order before processing payment (using custom app)

The advantage of this flow that prices, discount and stock are frozen before payment is created.

```mermaid
sequenceDiagram
    Customer->>+Custom App: Finalize an order
    Custom App ->>+ Saleor: Create order from checkout
    Saleor -->>- Custom App: Unpaid order
    Custom App-->>-Customer: Order
    Customer ->>+ Custom App: Process payment
    Custom App ->>+ Payment provider: Process payment for order
    Payment provider -->>- Custom App: Payment with proper status
    Custom App ->>+ Saleor: Create transaction for order
    Saleor -->>- Custom App: Transaction created and <br>attached to order
    Custom App -->>- Customer: Order paid
```

<a id="processing-payment-before-creating-an-order-using-custom-app"></a>

### Processing payment before creating an order (using custom app)

In this flow payment is made in Checkout, before Order is created - this way stocks are not reserved until a payment is made.

```mermaid
sequenceDiagram
    Customer ->>+ Custom App: Process payment
    Custom App ->>+ Payment provider: Process payment for checkout
    Payment provider -->>- Custom App: Payment with proper status
    Custom App ->>+ Saleor: Create transaction for checkout
    Saleor -->>- Custom App: Transaction created and <br>attached to checkout
    Custom App -->>- Customer: Payment paid
    Customer->>+Custom App: Convert checkout into an order
    Custom App ->>+ Saleor: Create order from checkout
    Saleor ->> Saleor: Attach checkout's transactions to order
    Saleor -->>- Custom App: Paid order
    Custom App-->>-Customer: Order
```

<a id="processing-payment-before-creating-an-order-using-saleor-transaction-api"></a>

### Processing payment before creating an order (using Saleor Transaction API)

Similar to previous flow, but instead of communicating with a custom app directly, Saleor Transaction API is used, payment app can be easily swapped for another.

Learn more about this integration in [Transactions Overview](/developer/payments/overview.md).

```mermaid
sequenceDiagram
    Customer ->>+ Saleor: Request to make<br> transaction for Checkout
    Saleor ->>+ Payment app: Sync webhook
    Payment app ->>+ Payment provider: Process payment for checkout
    Payment provider -->>- Payment app: Payment with proper status
    Payment app ->>- Saleor: Return result
    Saleor -->> Saleor: Transaction created and <br>attached to checkout
    Saleor -->>- Customer: Transaction paid
    Customer->>+Saleor: Convert checkout into an order<br>(checkoutComplete mutation)
    Saleor ->> Saleor: Attach checkout's transactions to order
    Saleor-->>-Customer: Order
```

<a id="creating-order-from-checkout-without-payments"></a>

### Creating order from checkout without Payments

Creating unpaid orders is possible for channels that have [`allowUnpaidOrders`](/api-reference/miscellaneous/objects/order-settings.md#allow-unpaid-orders) setting enabled. If you wish to bypass this setting, you can use [`orderCreateFromCheckout`](/api-reference/orders/mutations/order-create-from-checkout.md).

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`](/api-reference/orders/mutations/order-create-from-checkout.md).

**Mutation**

```graphql
mutation orderCreateFromCheckout($id: ID!, $removeCheckout: Boolean) {
  orderCreateFromCheckout(id: $id, removeCheckout: $removeCheckout) {
    order {
      id
    }
  }
}
```

**Variables**

```json
{
  "id": "Q2hlY2tvdXQ6YTcxYjRjZDQtNzI1NS00ZjAyLWEzOTEtMDQxYWQ0MmNjZWNk",
  "removeCheckout": true
}
```

**Result**

```json
{
  "data": {
    "orderFromCheckoutCreate": {
      "order": {
        "id": "T3JkZXI6MjI="
      }
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 0,
      "maximumAvailable": 50000
    }
  }
}
```

<a id="partialsplit-payments"></a>

## 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.

<a id="possible-approach"></a>

#### 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`](/api-reference/payments/mutations/transaction-initialize.md) 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](/developer/extending/webhooks/synchronous-events/transaction.md#response-4).

Remaining amount:

-   Checkout passes the remaining `amount` to the [`transactionInitialize`](/api-reference/payments/mutations/transaction-initialize.md) 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](/developer/extending/webhooks/synchronous-events/transaction.md#response-4).

2.  **Process transactions:**

-   Calling [`transactionProcess`](/api-reference/payments/mutations/transaction-process.md) 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.

<a id="product-personalization"></a>

## 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`](/api-reference/checkout/objects/checkout-line.md#metafields) fields to the [`CheckoutLine`](/api-reference/checkout/objects/checkout-line.md) object.

With the following mutations:

-   [`checkoutLinesAdd`](/api-reference/checkout/mutations/checkout-lines-add.md)
-   [`checkoutLinesUpdate`](/api-reference/checkout/mutations/checkout-lines-update.md)

The [`metafields`](/api-reference/orders/objects/order-line.md#metafields) will be copied to the [`OrderLine`](/api-reference/orders/objects/order-line.md) 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`](/developer/extending/webhooks/overview.md) events such as `ORDER_CREATED` to process the fields
-   [Custom pricing](#custom-product-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.

<a id="custom-product-pricing"></a>

## Custom product pricing

To set prices on checkout lines dynamically you can use the [`checkoutLinesUpdate`](/api-reference/checkout/inputs/checkout-line-update-input.md#price) mutation. See example [repository](https://github.com/saleor/saleor-app-checkout-prices) for creating custom pricing middleware.

<a id="using-phone-number-instead-as-identity"></a>

## 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.

<a id="automatic-checkout-completion"></a>

## Automatic checkout completion

The checkout can be automatically completed once full payment is received when using Payment Apps.

For more details, read [here](/developer/payments/transactions.md#automatic-checkout-completion).

<a id="order-approvals-and-quotes"></a>

## 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](/developer/channels/configuration.md#allow-unpaid-orders) should enable [`allowUnpaidOrders`](/api-reference/orders/inputs/order-settings-input.md#allow-unpaid-orders) to create orders without payments, (settings can be set via [API](/api-reference/channels/mutations/channel-update.md) or _Dashboard -> Order -> Order settings cogwheel_).

To require manual approval of orders in the dashboard, set the [`automaticallyConfirmAllNewOrders`](/api-reference/orders/inputs/order-settings-input.md#automatically-confirm-all-new-orders) to `false` (can be set via the dashboard _Configuration -> Channel_).

To arrange communication between flow between admin see Order related [`webhooks`](/api-reference/webhooks/enums/webhook-sample-event-type-enum.md).

<a id="subscriptions"></a>

## 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](/developer/extending/apps/quickstart.md) to create a dedicated UI in the Saleor dashboard to talk to your subscription service.
