Checkout Step 5: Complete Cart

Complete the cart and place the order.

On this page

In this guide, you'll learn how to complete the cart and place the order. This is step 5 of checkout — keep the order in Checkout Overview.

On Next.js, call sdk.store.cart.complete from a server action, then removeCartId() and redirect to /{countryCode}/order/{id}/confirmed.

Warning: Don't use the validate hook of completeCartWorkflow to mutate the cart's line items, shipping methods, or totals. The workflow retrieves the cart once before any hook runs and builds the order from that snapshot. If you mutate the cart in a hook, the created order and the authorized payment amount won't reflect the change.

If you need to change the cart before completing it, run a separate step or workflow before completeCartWorkflow, then refresh the cart's payment collection so that the payment session amount matches the new total.

How to Complete Cart in Storefront Checkout

Once you finish any required actions with the third-party payment provider, you can complete the cart and place the order.

To complete the cart, send a request to the Complete Cart API route. For example:

Tip: Learn how to install and configure the JS SDK in the Getting started guide.

ts

tsCopy
sdk.store.cart.complete("us", cart.id)
.then((data) => {
if (data.type === "cart" && data.cart) {
// an error occurred
console.error(data.error)
} else if (data.type === "order" && data.order) {
// TODO redirect to order success page
alert("Order placed.")
console.log(data.order)
// unset cart ID (removeCartId() on Next.js)
}
})

In the response of the request, the type field determines whether the cart completion was successful:

  • If the type is cart, it means the cart completion failed. The error response field holds the error details.
  • If the type is order, it means the cart was completed and the order was placed successfully.

When the cart completion is successful, unset the cart ID (removeCartId() on Next.js, which clears _aiminaabee_cart_id). The cart is no longer usable.

Tip: Check type === "order" to confirm cart completion. Don't assume the payment was charged based on calling the complete cart endpoint alone.


Payment Failure Handling

When cart completion fails after the payment was authorized or captured, the completeCartWorkflow automatically reverts the payment so the customer isn't charged for an incomplete order:

  • An authorized payment that wasn't yet captured is canceled.
  • A captured payment is refunded, unless a later or concurrent completion attempt already placed an order for the same cart. In that case, the refund is skipped so that the successful order keeps its payment.

Because the payment is reverted before the response is returned, a storefront doesn't need to issue a refund itself when completion fails. The type: "cart" response signals that completion failed and the payment was rolled back.


Order's Locale after Cart Completion

Prerequisites

  • Translation Module Configured

When you complete the cart, items in the order will be in the locale that was set for the cart. This ensures that the customer sees the order details in their preferred language.

If no locale was set for the cart, then the order's items will be in the original product content.


React Example with Default System Payment Provider

For example, to complete the cart when the default system payment provider is used:

Tip: This example uses the useCart hook defined in the Cart React Context guide.

tsx

tsxCopy
"use client" // include with Next.js 13+
import { useState } from "react"
import { useCart } from "@/providers/cart"
import { sdk } from "@/lib/sdk"
export default function SystemDefaultPayment() {
const { cart, refreshCart } = useCart()
const [loading, setLoading] = useState(false)
const handlePayment = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.preventDefault()
if (!cart) {
return
}
setLoading(true)
// TODO perform any custom payment handling logic
// complete the cart
sdk.store.cart.complete("us", cart.id)
.then((data) => {
if (data.type === "cart" && data.cart) {
// an error occurred
console.error(data.error)
} else if (data.type === "order" && data.order) {
// TODO redirect to order success page
alert("Order placed.")
console.log(data.order)
refreshCart()
}
})
.finally(() => setLoading(false))
}
return (
<button
onClick={handlePayment}
disabled={loading}
>
Place Order
</button>
)
}

In the example above, you create a handlePayment function in the payment component. In this function, you:

  • Optionally perform any required actions with the third-party payment provider. For example, authorize the payment. For the default system payment provider, no actions are required.
  • Send a request to the Complete Cart API route once all actions with the third-party payment provider are performed.
  • In the received response of the request, if the type is cart, it means that the cart completion failed. The error is set in the error response field.
  • If the type is order, it means the card was completed and the order was placed successfully. You can access the order in the order response field.
  • When the order is placed, unset the cart ID (on Next.js, removeCartId()). Redirect the customer to an order success page. The redirection logic depends on the storefront framework you're using.

React Example with Third-Party Payment Provider

Refer to the Stripe guide for an example on integrating a third-party provider and implementing card completion.