# Checkout app (https://prood.com/docs/apps/checkout)

`apps/checkout` is the **hosted payment application**. After the storefront places an order, the customer is redirected here to complete payment via Stripe, Easypay, or Ifthenpay.

**Port:** 3004 · **Framework:** Next.js 16 · **Database:** None (Upstash Redis for sessions)

## Architecture [#architecture]

```mermaid
sequenceDiagram
  participant SF as Storefront
  participant CHK as Checkout app
  participant REDIS as Upstash Redis
  participant PP as Payment provider
  participant API as Commerce API

  SF->>CHK: POST /api/sessions
  CHK->>CHK: Create CheckoutSession
  CHK->>REDIS: Save snapshot
  CHK-->>SF: checkoutUrl

  Note over CHK: Customer visits /c/{id}
  CHK->>REDIS: loadSession()
  CHK->>PP: Rebuild provider with tenant credentials
  CHK->>PP: submitPayment()
  PP->>API: Webhook forwarded
  API->>API: Update order status
```

## Key dependencies [#key-dependencies]

| Package | Role |
| --- | --- |
| `@prood/checkout-host` | Session create/load/persist, webhook forwarding |
| `@prood/checkout` | CheckoutSession state machine (used internally) |
| `@prood/types` | Error response helpers |
| `@prood/ui` | Button, skeleton, toast components |
| `@stripe/react-stripe-js` | Stripe Payment Element |

## Routes [#routes]

| Route | Purpose |
| --- | --- |
| `/pay` | Landing / entry page |
| `/pay/c/[id]` | Payment UI |
| `/pay/confirm/[id]` | Post-3DS / async confirmation |

The app is built with `basePath: "/pay"`, so every route, asset and API call lives under `/pay`: `https://prood.com/pay` in production, `http://localhost:3004/pay` locally. The routes below are written relative to it.

See [Sessions](/docs/apps/checkout/sessions) for API route details.

## Configuration [#configuration]

| Variable | Required | Purpose |
| --- | --- | --- |
| `KV_REST_API_URL` | Yes | Redis REST endpoint |
| `KV_REST_API_TOKEN` | Yes | Redis REST token |
| `CHECKOUT_API_SECRET` | Yes | Protects session creation API |
| `CHECKOUT_URL` | Yes | Public checkout base URL including its path, `https://prood.com/pay` |
| `COMMERCE_API_URL` | Yes | Webhook forwarding target |

## Security [#security]

- Session creation requires `x-checkout-secret` header — only trusted callers (storefront) can create sessions
- Webhook routes are org-scoped: `/pay/api/webhooks/{provider}/{orgId}`
- Payment provider credentials loaded per tenant from encrypted integration config
- No direct database access — all order updates go through the Commerce API

## Related pages [#related-pages]

<Cards>
  <Card title="Sessions" href="/docs/apps/checkout/sessions" description="Session API routes and Redis persistence." />
  <Card title="Payments" href="/docs/apps/checkout/payments" description="Stripe, Easypay, and Ifthenpay UI." />
  <Card title="Webhooks" href="/docs/apps/checkout/webhooks" description="Webhook routing and forwarding." />
  <Card title="Checkout flow" href="/docs/architecture/checkout-flow" description="State machine architecture." />
</Cards>
