Audience: Developers, Finance Admins
Outcomes: Cards are enabled; webhooks verified; receipts flow into orders
Configure environment
STRIPE_SECRET_KEY=sk_live_xxx STRIPE_WEBHOOK_SECRET=whsec_xxx
Option A — Payment Intent (server‑controlled)
curl -X POST $API_BASE/api/payments/intents -b cookies.txt \ -H 'Content-Type: application/json' \ -d '{"orderId":"ord_123","amount":150000,"currency":"USD"}'
Use this when you want maximum control over the flow.
Option B — Hosted Checkout (fast)
curl -X POST $API_BASE/api/payments/stripe/checkout-session -b cookies.txt \ -H 'Content-Type: application/json' \ -d '{ "orderId":"ord_123", "amount":150000, "currency":"USD", "successUrl":"https://app.example.com/success", "cancelUrl":"https://app.example.com/cancel" }' # → returns { "url": "https://checkout.stripe.com/c/..." }
Webhook (Express)
app.post('/api/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => { try { const event = stripe.webhooks.constructEvent( req.body, req.header('Stripe-Signature'), process.env.STRIPE_WEBHOOK_SECRET! ); handleStripeEvent(event); // mark order DepositPaid, refunds, etc. res.json({ received: true }); } catch (err) { res.status(400).send('Signature verification failed'); } });
3DS/SCA
Handled by Intents/Checkout. Ensure your UI shows the challenge modal when required.
Local testing
stripe listen --forward-to localhost:3000/api/webhooks/stripe
Idempotency & metadata
Send a stable
reference
with your requests.Attach
orderId
in provider metadata for easy reconciliation.