Stripe
23 items · source
Backend Application & API
- Verify webhook handlers call
constructEventwith the signing secret and reject unsigned or mis-signed payloads. - Verify the webhook endpoint reads the raw body; a JSON body parser running first invalidates the signature.
- Verify the event timestamp is checked so an old captured payload cannot be replayed.
- Verify webhook handling is idempotent by event id — Stripe retries, and a duplicate must not fulfil an order twice.
- Verify the handler responds quickly and does the work asynchronously, rather than timing out and being retried.
- Verify a failed webhook is visible to you, not only in Stripe's dashboard.
- Verify each webhook endpoint's enabled events include every event type your handler has a case for — compare
stripe webhook_endpoints listwith the handler'sswitch; an event you handle but never subscribed to is code that never runs, and refunds are the usual one. - Verify the API version set on each webhook endpoint is the version your handler was written against — Stripe renders the payload in the endpoint's version, not your SDK's, and a field that moved between versions silently matches nothing while Stripe still receives a 200.
- Verify the handler checks
livemodeon every event and rejects one whose mode does not match the environment, so a production account that is quietly a sandbox, or a test event sent to production, is caught on the first delivery.
Business Logic & Race Conditions
- Verify the charge amount is computed server-side from a price or product id, never taken from the request body.
- Verify currency is server-side too; a client-supplied currency is a discount.
- Verify entitlement is granted from the webhook or a server-side retrieve, not from the browser returning to a success URL.
- Verify a success redirect cannot be visited directly to unlock the product.
- Verify idempotency keys are sent on charge and payment-intent creation so a retried request does not double-charge.
- Verify subscription state is read from Stripe or from a webhook-updated record, rather than assumed after checkout.
- Verify refunds, disputes, cancellations and failed renewals revoke access.
- Verify promotion codes and trials cannot be stacked or reused beyond intent.
Secrets Management & Cryptography
- Verify the secret key is server-side only, and that only the publishable key reaches the browser.
- Verify test and live keys cannot be confused — different environments, and an assertion at boot that the mode matches the environment.
- Verify restricted keys are used where a service needs only part of the API.
- Verify the webhook signing secret is stored as a secret and differs per endpoint and per environment.
Pre-Release Gates
- Verify card details never touch your server — Elements or Checkout, so PCI scope stays SAQ-A.
- Verify a real payment has been made and refunded end to end in production before launch.
# Stripe ## Backend Application & API * [ ] Verify webhook handlers call `constructEvent` with the signing secret and reject unsigned or mis-signed payloads. * [ ] Verify the webhook endpoint reads the **raw** body; a JSON body parser running first invalidates the signature. * [ ] Verify the event timestamp is checked so an old captured payload cannot be replayed. * [ ] Verify webhook handling is idempotent by event id — Stripe retries, and a duplicate must not fulfil an order twice. * [ ] Verify the handler responds quickly and does the work asynchronously, rather than timing out and being retried. * [ ] Verify a failed webhook is visible to you, not only in Stripe's dashboard. * [ ] Verify each webhook endpoint's enabled events include every event type your handler has a case for — compare `stripe webhook_endpoints list` with the handler's `switch`; an event you handle but never subscribed to is code that never runs, and refunds are the usual one. * [ ] Verify the API version set on each webhook endpoint is the version your handler was written against — Stripe renders the payload in the endpoint's version, not your SDK's, and a field that moved between versions silently matches nothing while Stripe still receives a 200. * [ ] Verify the handler checks `livemode` on every event and rejects one whose mode does not match the environment, so a production account that is quietly a sandbox, or a test event sent to production, is caught on the first delivery. ## Business Logic & Race Conditions * [ ] Verify the charge amount is computed server-side from a price or product id, never taken from the request body. * [ ] Verify currency is server-side too; a client-supplied currency is a discount. * [ ] Verify entitlement is granted from the webhook or a server-side retrieve, not from the browser returning to a success URL. * [ ] Verify a success redirect cannot be visited directly to unlock the product. * [ ] Verify idempotency keys are sent on charge and payment-intent creation so a retried request does not double-charge. * [ ] Verify subscription state is read from Stripe or from a webhook-updated record, rather than assumed after checkout. * [ ] Verify refunds, disputes, cancellations and failed renewals revoke access. * [ ] Verify promotion codes and trials cannot be stacked or reused beyond intent. ## Secrets Management & Cryptography * [ ] Verify the secret key is server-side only, and that only the publishable key reaches the browser. * [ ] Verify test and live keys cannot be confused — different environments, and an assertion at boot that the mode matches the environment. * [ ] Verify restricted keys are used where a service needs only part of the API. * [ ] Verify the webhook signing secret is stored as a secret and differs per endpoint and per environment. ## Pre-Release Gates * [ ] Verify card details never touch your server — Elements or Checkout, so PCI scope stays SAQ-A. * [ ] Verify a real payment has been made and refunded end to end in production before launch. 23 items · https://github.com/FarzamHabibi/pre-production-checklist · CC BY 4.0