Rebasely Beta: data may be purged

examples/storefront Public

Markdown · 38 lines · 2.3 KiB · at 80dbc76

---id: payment-webhooktype: conceptowner: justincomponent: paymentsdescribes:  - workers/payments/src/webhook.tsreviewed: 2026-10-15---# The payment webhookAn order is paid when Stripe says so, never when the browser says so. Stripe sends events to `/stripe/webhook` on the `storefront-payments` Worker ([[payments]]), which turns them into order changes.## What it does1. Verifies the `stripe-signature` header against `STRIPE_WEBHOOK_SECRET` with Web Crypto. A bad or missing signature gets a 400 and changes nothing.2. For `payment_intent.succeeded`, calls `OrdersService.markPaid(order, intent)` on storefront-api. The order id comes from the intent's metadata, which checkout set ([[checkout]]).3. For `payment_intent.canceled`, calls `OrdersService.cancel(order)`, which puts the stock back.4. Answers 200 to everything else, including events for intents without an `order_id`, so Stripe stops retrying them.The payments Worker has no database binding. It reaches orders only through the service binding `ORDERS` ([[0006-one-writer-for-the-database]]). Until October 15 this code was a Worker of its own, `storefront-stripe-webhook`; it moved into the payments Worker unchanged ([[0010-payments-worker]]).## Retries and repeatsStripe delivers each event at least once and retries anything that does not get a 2xx. Both calls are safe to repeat:- `markPaid` only moves an order from `pending_payment` to `paid`, and only when the intent id matches the one stored at checkout.- `cancel` puts stock back in the same batch that cancels the order, and only while the order is pending.If OrdersService throws, the webhook answers 500 and Stripe tries again later.## A payment for a cancelled orderIf an order was cancelled and its payment still succeeds, `markPaid` leaves the order cancelled and the Worker logs `payment for a cancelled order, refund it` as an error. Expiry cancels the intent before the order ([[checkout]]), so this needs an order cancelled some other way; the log line is there to search for if it happens.## Local testing`stripe listen --forward-to localhost:8788/stripe/webhook` prints a webhook secret for `workers/payments/.dev.vars` and forwards test-mode events. Run the Worker with `npx wrangler dev -c workers/payments/wrangler.jsonc --port 8788` next to storefront-api.