Test Payments Before Launch

Test a payment flow end to end with Stripe test cards and the Stripe CLI, then go live without leaving test keys behind.

This guide covers testing a Stripe payment flow before launch, and the checklist for switching from test mode to live.

Quick Answer

Use Stripe's test card numbers and the Stripe CLI to exercise success, decline, and 3D Secure paths in test mode; verify refunds work; then switch to live keys and a live webhook endpoint with its own signing secret, and confirm nothing still points at test mode.

1. Test Cards

Stripe's test mode accepts fixed card numbers that simulate specific outcomes, with any future expiry date and any CVC:

  • 4242 4242 4242 4242 succeeds.
  • 4000 0000 0000 0002 is declined.
  • 4000 0025 0000 3155 requires 3D Secure/SCA authentication, useful for testing that flow explicitly rather than assuming it works.

2. Exercise the Full Flow

Walk through: a successful purchase, a declined card, a card requiring 3DS, and a refund initiated from your admin/backend. Confirm your app's UI handles each outcome (not just the happy path) and that fulfilment/refund logic actually fires from the webhook, not just the client.

3. Test Webhooks Locally

stripe listen --forward-to localhost:4000/webhooks/stripe

This prints a webhook signing secret starting with whsec_; use it as STRIPE_WEBHOOK_SECRET in your local environment while testing, it's different from your production endpoint's secret.

4. Going Live

  1. Switch STRIPE_SECRET_KEY and the app's publishable key from test (sk_test_ / pk_test_) to live (sk_live_ / pk_live_).
  2. Register a separate webhook endpoint in the Stripe dashboard pointed at your production URL; it gets its own whsec_ secret, distinct from your test/local one.
  3. Update STRIPE_WEBHOOK_SECRET on your production server to match the live endpoint's secret, not the test one.
  4. Re-run at least one real, small live transaction to confirm the full path end to end.

Common Issues

Live payment succeeds but nothing happens in your app the live webhook endpoint was never registered, or the production STRIPE_WEBHOOK_SECRET still holds the test/local value.

"No such payment_intent" errors after going live mixing a test-mode secret key with a live-mode client secret (or vice versa); test and live are entirely separate object spaces in Stripe.

3D Secure never triggers in testing the specific test card for it wasn't used; a plain success card doesn't exercise that path.

Verification Checklist

  • success, decline, and 3DS test cards all produce the expected app behavior;
  • a refund correctly reverses the order in your system;
  • the production webhook endpoint is registered separately from any test/local one;
  • live keys and the live webhook secret are both in place before launch;
  • a real, minimal live transaction has been run successfully.

Next Steps