Problem
You need to integrate Stripe webhooks into your application to reliably process payment events. When a customer completes a payment, Stripe sends a webhook event to your server. You must handle these events to update order status, provision access, and send confirmation emails.
Requirements
- Webhook Endpoint: Create a POST endpoint (
/api/webhooks/stripe) that receives Stripe webhook events.
- Signature Verification: Verify the
Stripe-Signature header to ensure the event is genuinely from Stripe and has not been tampered with.
- Event Handling: Handle these event types:
-
checkout.session.completed — Mark order as paid, provision access
-
payment_intent.payment_failed — Mark order as failed, notify customer
-
customer.subscription.updated — Update subscription status
-
customer.subscription.deleted — Handle cancellation
- Idempotency: Handle duplicate webhook deliveries gracefully (Stripe may retry).
- Error Handling: Return appropriate HTTP status codes. Return 200 to acknowledge receipt, even if processing will happen asynchronously.
Constraints
- Stripe expects a response within 20 seconds or it will retry.
- Stripe retries failed deliveries (non-2xx responses) for up to 72 hours with exponential backoff.
- The raw request body must be preserved for signature verification (do not parse JSON before verifying).
- The same event may be delivered multiple times.
- Events may arrive out of order (e.g.,
payment_failed before checkout.session.completed).
What to Design
- The webhook endpoint implementation with signature verification
- The idempotency strategy (how to detect and handle duplicate events)
- How to handle events that require long processing (beyond 20 seconds)
- Error handling and retry-friendly response behavior
- Testing strategy for webhook handlers