ManagedQA PartnersSee plans

Stack · Stripe

Release testing for Stripe integrations

Payments and plan state arrive as signed webhook events that can be duplicated and can arrive out of order. The checklist sends the events the docs warn about and checks the account state afterwards.

Termswebhook (a message a provider such as Stripe sends to your server when something happens, like a payment) · publishable and secret keys (the publishable key may sit in the browser because row-level security limits it; the secret key bypasses those rules and must stay on the server) · critical flow (a path a user takes that costs money or trust if it breaks: sign-up, checkout, invite, export) · verdict (a one-word release result (pass, pass with findings, fail) with the findings and the checklist version behind it) · CI (the pipeline that builds and tests every change before it can be merged or deployed) · client bundle (the JavaScript your app sends to the browser or ships inside the mobile app; anyone can read it)

What Stripe changes in a codebase

Payments and subscriptions arrive as signed webhook events. Entitlements are only as correct as the handler that verifies, deduplicates and orders those events.

A webhook handler is the most-copied code in a payments integration and the least tested. Every release that touches it runs PY-01 through PY-05 in the provider's sandbox, with unsigned, altered, duplicated and reversed events.

Defaults, from the docs verified 2026-09-21

Verified defaults for Stripe
Default, from the docsWhy it matters for release testingSource
"Without verification, an attacker could send fake webhook events to your endpoint to trigger actions like fulfilling orders, granting account access, or modifying records." Stripe requires the raw request body for the check.PY-01 sends unsigned and altered events; a framework that parses the body first fails the check silently.docs
verified 2026-09-21
"Webhook endpoints might occasionally receive the same event more than once"; log processed event ids. Stripe "doesn't guarantee the delivery of events in the order that they're generated."PY-02 replays an event id and reverses a related pair.docs
verified 2026-09-21
Official libraries "have a default tolerance of 5 minutes between the timestamp and the current time"; a tolerance of 0 disables the recency check.A copied handler that sets tolerance to 0 to make a test pass has removed replay protection; PY-01 includes a stale-timestamp event.docs
verified 2026-09-21
Only publishable keys (pk_) are safe to expose; secret (sk_) and restricted (rk_) keys are not. Sandbox keys start with sk_test_ and live keys with sk_live_. "Don't put keys in source code or configuration files checked into version control."SC-01 and SC-02 scan for sk_ and rk_ prefixes; SC-04 checks that production is not running on sk_test_.docs
verified 2026-09-21
Restricted keys tagged for autonomous agents are "automatically subject to approval rules, which require a designated reviewer to approve sensitive actions" such as payouts and refunds.If an agent holds a Stripe key, this is the setting that keeps DR-03 true for money.docs
verified 2026-09-21

Each row was read on the linked page on the date shown. Docs change; the date tells you how current the row is. Stripe documentation.

Failure patterns most associated

How the checklist adapts

  • PY-01 sends unsigned, altered, wrongly signed and stale-timestamp events; the raw-body requirement is the usual reason a copied handler fails.
  • PY-02 replays an event id and reverses a related pair, then checks the final state.
  • PY-03 and PY-04 edit the client-side plan flag and the checkout amount.
  • SC-01, SC-02 and SC-04 scan for sk_ and rk_ prefixes and confirm production is not on sk_test_.

Release checklist, five of the published items

v1.0 · verified on 2026-09-21
PY-01

Webhook signatures are verified against the raw body

automated Send an unsigned event, an event with an altered body, and an event signed with the wrong secret to the webhook endpoint.

Pass when

All three are rejected with a 4xx status and no state change.

critical
starter, growth, scale
PY-02

Duplicate and out-of-order events are handled once

automated Deliver the same event id twice and deliver invoice.paid before customer.subscription.created.

Pass when

Exactly one state change per event id; the out-of-order pair ends in the correct final state.

high
starter, growth, scale
PY-05

Cancellation, downgrade and refund paths update entitlements

manual Trigger cancel, downgrade, failed renewal and refund events in the payment provider's test mode and check the account state.

Pass when

Each event leaves the account with the entitlement the written rules specify, within one webhook delivery.

high
starter, growth, scale
SC-01

No secret keys in client bundles

automated Scan the built client assets (JS, source maps, HTML) for known key prefixes and for every value present in the server environment file.

Pass when

Zero matches for key prefixes (sk_, service_role, AKIA, whsec_, private keys) and zero server-only env values found in client assets.

critical
starter, growth, scale
SC-02

No secrets in repository history

tool Run a secret scanner (gitleaks or equivalent) over the full git history, not only the working tree.

Pass when

Scanner reports zero unrevoked findings; any historical finding has a rotation record.

critical
starter, growth, scale

Read the full checklist

Which plan fits

Starter $2,900/mo

Starter covers all five payment items on a web app. Growth adds the API surface if the integration is behind one.

For 3-8 engineers, weekly releases, web. Limits, cadence and what is not included.

Questions

Stripe webhook testing checklist
Unsigned event rejected; altered body rejected; wrong secret rejected; stale timestamp rejected; same event id delivered twice changes state once; invoice.paid before subscription.created ends in the right state; cancel, downgrade, failed renewal and refund each leave the written entitlement. Items PY-01, PY-02, PY-05.
How to test Stripe webhooks before going live?
Use the Stripe CLI to forward events to a staging endpoint, then send the negative cases by hand: unsigned, altered, replayed, reversed. Confirm the handler reads the raw body, logs processed event ids and returns 2xx quickly. Then switch keys and run the same set against the live endpoint with test events.
Payment webhook signature verification test
Send the same payload three ways: without a Stripe-Signature header, with a header from a different secret, and with a valid header but an edited body. All three must return 4xx with no state change. A handler that parses JSON before verifying will fail this test.