Rebasely Beta: data may be purged

examples/storefront Public

Markdown · 1.8 KiB · at 80dbc76

id: payments
type: concept
owner: justin
component: payments
describes:
  - workers/payments/src/index.ts
  - workers/payments/src/stripe.ts
  - src/payments.ts
reviewed: 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-api

storefront-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 Stripe

Its 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]].