[Service Name] — Stripe Checkout layer
A thin service that takes payments via Stripe Checkout and processes webhooks safely. Stateless except for what you choose to persist.
Source of truth
Stripe is the source of truth for payment state. Your DB stores a denormalized copy for fast reads. The webhook reconciles after every event.
Tech stack
Node 22 + TypeScript + Express or Hono (whatever your existing stack uses). Stripe SDK (stripe npm package, pinned to a specific API version). Postgres for the local mirror. JWT or session auth on the create-checkout endpoint.
Deploy
Anywhere a Node server runs. Webhook endpoint must be reachable from the public internet. For local dev use stripe listen --forward-to localhost:3000/webhooks/stripe.
File map
src/routes/checkout.tsPOST/api/checkout-> creates a Checkout Session, returns the URLsrc/routes/billing-portal.tsPOST/api/billing-portal-> Customer portal URL for subscription managementsrc/routes/webhook.tsPOST/webhooks/stripe-> verifies signature, dispatches by event typesrc/lib/stripe.tsSDK init, API version pinsrc/lib/db.tsPostgres writes for customers, subscriptions, orderssrc/events/one handler per Stripe event type (checkout.session.completed, customer.subscription.updated, etc)db/schema.sqlstripe_customers,subscriptions,orderstables
.env keys
STRIPE_SECRET_KEYsk_live_...orsk_test_...STRIPE_WEBHOOK_SECRETwhsec_...STRIPE_PRICE_IDS_TIER1,STRIPE_PRICE_IDS_TIER2your product price IDsSTRIPE_PORTAL_RETURN_URLwhere users land after the portalDATABASE_URL
Hard rules
- Webhook signature is verified BEFORE parsing the body. Use the raw body, not
JSON.parse(). - Webhook handlers must be idempotent. Same event twice = same result. Store the Stripe event ID, refuse duplicates.
- Webhook responds 200 within 2 seconds; do the slow work in a background queue if needed.
- Never store full card numbers, CVCs, or full names on cards. Stripe holds these.
- API version is PINNED in
stripe.ts(apiVersion: '2025-06-30.basil'or whatever your locked version is). Test before bumping. - Test mode keys for dev, live mode for prod. Use Stripe's CLI
stripe listento forward events to localhost.
Recent significant changes
- 2026-04-26: Scaffolded. Locked: Stripe Checkout (hosted) over custom Elements UI, webhooks over polling, Postgres mirror over Stripe-as-source-only.
Next session: start here
- Create Stripe account, get test keys.
- Create products + prices in Stripe Dashboard, save IDs.
stripe listen --forward-to localhost:3000/webhooks/stripeand copy thewhsec_into.env.- Implement create-checkout endpoint, test with a real test card (
4242 4242 4242 4242). - Verify a successful webhook updates your DB before going live.
- Activate live mode keys. Test one real payment for $1.