examples/storefront Public
---id: paymentstype: conceptowner: justincomponent: paymentsdescribes: - workers/payments/src/index.ts - workers/payments/src/stripe.ts - src/payments.tsreviewed: 2026-10-15---# The payments Worker`storefront-payments` (`workers/payments`) is the only Worker that talks to Stripe or holds its keys. It has two faces.## PaymentsService, for storefront-apistorefront-api reaches it through the `PAYMENTS` service binding, entrypoint `PaymentsService`. The binding is typed as the `Payments` interface in `src/payments.ts`, the same interface tests implement with `FakePayments`:| Call | Used by | What it does || --- | --- | --- || `createIntent({ order_id, amount_cents, currency, email })` | checkout | creates a PaymentIntent with idempotency key `order-<id>` and returns its id and client secret || `cancelIntent(intent_id)` | expiry | cancels the intent; false if it already succeeded or is processing |Service binding calls do not leave Cloudflare, and the entrypoint is not reachable from the internet. The Stripe adapter itself is `workers/payments/src/stripe.ts`.## The webhook, for StripeIts fetch handler serves `POST /stripe/webhook` and nothing else ([[payment-webhook]]). It settles orders through storefront-api's `OrdersService` over the `ORDERS` binding, because only storefront-api writes to D1 ([[0006-one-writer-for-the-database]]).So the two Workers bind each other: storefront-api calls payments to charge, payments calls storefront-api to record the result. Deploy order matters only when an interface changes: add a method on the side being called first.## Secrets`STRIPE_SECRET_KEY` and `STRIPE_WEBHOOK_SECRET`, set with `npx wrangler secret put -c workers/payments/wrangler.jsonc`. Rotating the secret key means redeploying nothing else. Why the keys moved here is in [[0010-payments-worker]].