Read the server-owned choices
Do not infer payment choices from a connected provider or a location setting. Load the current cart’scollection-options first:
unavailableReasonCode; never override it in the browser.
Pay online with Stripe
CUSTOMER_ACTION_REQUIRED, initialize Stripe.js with its
connectedAccountId and confirm its clientSecret. The server captures and
settles the already-persisted order. No provider-selected confirmation endpoint exists.
Confirm a Stripe session with Stripe Elements
storefront.checkout.getOrderSubmissionOutcome(locationId, cartId, attemptId). Treat only PAID as paid, keep PROCESSING retryable, and surface ACTION_REQUIRED without creating another order.
Pay at the store
Offer this choice only when the server returns an availablePAY_AT_STORE
option and identifies SQUARE, CLOVER, or TOAST as its settlement adapter.
Submit the same order-first contract without a saved payment method:
status: "ACCEPTED" and remains unpaid
until the selected POS reports native tender evidence. Tell the customer that
payment is due at the store and keep order state separate from payment state.
Poll the same attemptId; never submit a replacement order and never render a
POS card form, saved card, gift-card entry, or provider-hosted checkout.
When counter-verification is unresolved, show Verifying payment — do not
charge again. In outcome.verification.state, PENDING and WARNING
continue reconciliation, while ACTION_REQUIRED needs staff review. Only the
top-level PAID outcome proves collection. The POS provider owns the original
in-person tender and its refund path. A provider order cancellation is not
refund evidence.
Checkout Flow
See the complete checkout state machine.
Order Tracking
Poll the order result and load protected receipts.
