Stripe & checkout

Flow

  • Client collects email + GitHub username, then POSTs to your checkout API.
  • Server creates a Stripe Checkout Session with metadata (persisted on the session).
  • User pays on Stripe-hosted checkout; success URL includes {CHECKOUT_SESSION_ID} so the app can poll until the order exists before showing success.
  • checkout.session.completed webhook creates/updates the order row (idempotent). GitHub invite and email run only after a successful insert.

Good practices

  • Use webhook signing secret per environment (test vs live whsec_ differ).
  • Verify the raw body for signature verification — do not parse JSON before verify.
  • Return 200 quickly after persisting the order; run email/GitHub side effects after insert, and use ON CONFLICT DO NOTHING (or equivalent) so Stripe retries do not duplicate work.
  • Store customer_email from session + metadata fallback so receipts always have an address.

Local testing

stripe listen --forward-to localhost:3000/api/webhooks/stripe

Use the CLI's whsec_ in .env.local while developing.

Price IDsUI price ($99) must match the Stripe Price amount, or customers see one number and pay another. Create a one-time price in Dashboard and set STRIPE_PRICE_ID.