Shop It Docs
Developer ResourcesPayment

Cart Checkout Payment Flow

Checkout initiation for all payment gateways, including COD pending collection flow.

Cart Checkout Payment Flow

Overview

Cart checkout is the primary payment path for active cart orders.

  • Endpoint: POST /api/orders/checkout
  • Mobile-composed endpoint: POST /api/mobile/orders/checkout
  • Supported gateways: stripe, esewa, fonepay, connect_ips, cod
  • Preferred/default gateway: stripe

Checkout initiation is synchronous. Payment finalization is asynchronous through payment events and order workers.

Checkout Request (Stripe Default)

{
  "gateway": "stripe",
  "returnUrl": "https://example.com/payment/return"
}

Payment-Init Response (200)

{
  "orderId": 101,
  "status": "payment_pending",
  "paymentId": 9001,
  "gatewayTransactionId": "cs_test_a1b2c3d4",
  "initiationType": "redirect",
  "redirectUrl": "https://checkout.stripe.com/c/pay/cs_test_a1b2c3d4",
  "gatewayPayload": {
    "sessionId": "cs_test_a1b2c3d4"
  }
}

Sequence

Queue Contract Stability

No queue name or job contract changes were introduced:

  • payment.completed still drives order.payment_success
  • payment.failed still drives order.payment_failed

Edge Cases

Edge CaseBehavior
Empty cartRejected before payment initiation
Duplicate idempotency keyExisting initiation result replayed
Stripe webhook replayIdempotent; terminal payments are not double-processed
Gateway failure/expiryPayment marked failed; order failure flow runs

COD Checkout (Cash on Delivery)

COD uses initiationType: "cod" — no redirect and no webhook. The order remains payment_pending, while paymentStatus becomes cod_pending after stock reservation succeeds.

This is enough for fulfillment to proceed, but not enough for warranty eligibility.

COD Request

{
  "gateway": "cod",
  "returnUrl": "https://example.com/orders/101/confirmation"
}

COD Response (200)

{
  "orderId": 101,
  "status": "payment_pending",
  "paymentId": 9001,
  "gatewayTransactionId": "cod_9001",
  "initiationType": "cod",
  "redirectUrl": "https://example.com/orders/101/confirmation",
  "gatewayPayload": {}
}

redirectUrl echoes the original returnUrl. No gateway redirect is performed. Frontend navigates to returnUrl directly.

The COD payment row remains pending at checkout. Admin cash collection later completes that same payment row and changes the order payment status to cod_collected. COD checkout does not emit payment.completed and does not use order.payment_success.

Warranty-related behavior follows the same state boundary: cod_pending is treated as unpaid for warranty, and cod_collected is the first COD state that allows warranty access.

COD restriction: Only available for physical orders. Digital-only or care-package-only carts return 400 ORDER_COD_PHYSICAL_ONLY.

COD-Specific Edge Cases

Edge CaseBehavior
Digital-only cart + COD400 ORDER_COD_PHYSICAL_ONLY
Care-package-only cart + COD400 ORDER_COD_PHYSICAL_ONLY
Mixed cart (physical + digital) + CODAllowed
Admin cash collection already recordedIdempotent 200 — returns existing codCashCollectedAt
  • apps/fumadocs/content/docs/developer/payment/browser-return-flow.mdx
  • apps/fumadocs/content/docs/developer/payment/stripe.mdx
  • apps/fumadocs/content/docs/developer/order/api.mdx