Stripe webhook test plan for Next.js
Before a Next.js app exposes Stripe checkout traffic, the webhook route needs evidence that exact raw bodies are verified, duplicate events are safe, and access changes happen once.
Start with the raw-body gate
In a Next.js App Router route, read await request.text() before parsing JSON. Signature verification must use the exact string Stripe signed; a parsed and reserialized object is not release evidence.
- Valid signed payload returns 2xx.
- Mutated body returns 400 before side effects.
- Wrong Stripe-Signature header returns 400 before side effects.
Lock the Stripe contract fields
Keep fake, committed fixtures for checkout.session.completed, invoice.paid, customer.subscription.deleted, and charge.refunded. The tests should assert the fields your handler trusts before creating users, granting access, sending email, or delivering a download.
Session ID, customer ID, customer email, payment status, currency, amount, product or price ID, and internal account mapping.
Invoice ID, subscription ID, period dates, paid status, customer mapping, and renewal extension decision.
Subscription ID, cancellation timing, access end date, and whether the account remains active until period end.
Charge or payment intent ID, refund amount, rollback action, support note, and replay-safe revocation state.
Prove idempotency and duplicate replay
Stripe retries events. Store a provider-scoped idempotency key before fulfillment, then replay the same signed fixture three times. The route can return success for duplicates, but side effects should run exactly once.
Keep checkout smoke separate
Fixture tests prove handler behavior. A controlled checkout smoke test proves deployed Stripe configuration, live webhook delivery, environment variables, and success redirects. Keep both pieces in the release notes before a public buy link goes live.
FAQ
What should a Stripe webhook test plan include for Next.js?
Raw-body signature verification, signed checkout.session.completed and invoice.paid fixtures, invalid signature rejection, idempotency storage, duplicate replay, entitlement decisions, checkout smoke evidence, and CI gates.
Can Stripe webhook tests run without a live Stripe account?
Yes. Route tests can use fake fixtures and fake signing secrets. A separate live checkout smoke test is still required before production traffic.
Use the free sample before wiring production checkout
The free sample shows the shape of fixtures, handlers, signature tests, contract checks, duplicate replay tests, and CI workflow. The Pro Kit preview shows the full CN¥69 paid package structure without exposing the private archive.