Skip to main content

Checkout Lifecycle

Checkout Creation

Upon creation, checkout is assigned to a channel that influences product stock, availability, and price. The channel can not be changed after the checkout is created. Learn more about Channels.

Checkout can be created from existing orders, which is helpful for re-order functionality.

Authentication in Checkout

BoxNCase allows you to manage both logged-in customers and guest users using the same API mutations. You do not need separate logic branches for different user states; instead, BoxNCase determines the checkout ownership based on the request's authentication context.

  • With Auth Header: If the checkout creation request includes a valid user token, the new checkout is automatically "Signed" (linked to that specific User ID).

  • Without Auth Header: The checkout is created as "Anonymous" (guest). It is identified solely by a unique token and is not linked to any user profile.

Attaching a Guest Checkout to a User

If a guest user logs in midway through their shopping experience, you can convert their anonymous checkout into a signed one using the checkoutCustomerAttach mutation. This ensures their items are preserved and linked to their account history.

Updating Checkout

  • Updating lines. Each line (product variant) should have at least a quantity of 1; if the line reaches a quantity of 0, it will be automatically removed. Optionally Price overwrites and Line Stacking can be controlled via API.

Completing Checkout

When checkout is finalized/completed, it is converted into an order.

The following are the requirements to finalize the checkout:

  1. The required addresses are valid, except when skipValidation is used.

  2. Delivery options and addresses are valid. Learn more.

  3. All selected products are in stock (while purchasing, another user could already buy the last available item). See Allocations and Reservations.

  4. The payments are processed unless the Channel setting of the checkout has allowUnpaidOrders setting enabled or checkout's total is 0. If you need to bypass this setting, you use orderCreateFromCheckout.

note

If case an order is overcharged, it will still be created. The overcharge must be handled manually.

Completing Anonymous Orders

When a guest checkout is completed, BoxNCase performs an automatic lookup using the provided email address.

  • If a user account with that email already exists, BoxNCase assigns the resulting order to that user automatically.

  • If the email does not exist at the time of purchase, BoxNCase still tracks the association. When a user later creates and confirms an account with that email, their previous guest orders are automatically attached to their new profile.

Checkout Expiration and Deletion

To avoid overloading the database, unfinished and unpaid checkouts are automatically deleted after a specified period from their last modification:

  • checkouts without lines after 6 hours,
  • anonymous checkouts (neither user nor email is set) with lines after 30 days,
  • user checkouts (either user or email is set) with lines after 90 days.

Releasing Funds for Abandoned Checkouts

Payments for items left in the cart by customers who did not complete the purchase will be refunded to the customer's account.

Abandoned checkout is the checkout that hasn't been changed in a specific period. The TTL is controlled by the environment variable: CHECKOUT_TTL_BEFORE_RELEASING_FUNDS, a default set to 6 hours.

For any transactionItem with processed funds (authorizedAmount or chargeAmount) assigned to abandoned checkout, BoxNCase will trigger the release action.

The release action is:

  • webhook with the event:TRANSACTION_CANCELATION_REQUESTED triggered when transactionItem contains authorized funds
  • webhook with the event: TRANSACTION_REFUND_REQUESTED triggered when transactionItem contains charged funds.

The release action is triggered only once. If a subscription for a release event is missing or the app fails to process the action, the release action needs to be handled manually.

To fetch paid checkouts, use the below query:

query checkouts($first: Int, $filter: CheckoutFilterInput) {
checkouts(first: $first, filter: $filter) {
totalCount
edges {
node {
id
totalBalance {
amount
}
}
}
}
}