If you use a hosted payment page like Stripe Checkout, the safest architecture is:
- Create an internal order before redirecting.
- Redirect the user to the hosted checkout URL.
- Use webhooks as the source of truth for fulfillment.
- Let the frontend poll order status after return.
This avoids race conditions and ensures users still get entitlements even if they close the tab before the success page loads.
Why This Pattern Works
Hosted checkout redirects are excellent for UX and compliance, but redirects are not guaranteed delivery signals.
A webhook is the reliable signal. The redirect page is only a user-facing state page.
End-to-End Sequence

High-Level Components
Frontend App
- Shows plans or packs.
- Calls backend to create checkout session.
- Redirects user to hosted checkout.
- On return page, checks order status and polls while pending.
Backend API
- Authenticates user.
- Creates internal order (
pending) before payment. - Creates hosted checkout session.
- Verifies webhook signature and fulfills idempotently.
- Exposes order status endpoint.
Database
- Plans or packs catalog.
orderstable/collection.processed_webhook_eventsfor idempotency.- User entitlement/credits balance.
API Shape
POST /checkout-session
Request:
{ "planId": "pro_monthly" }
Response:
{ "orderId": "...", "checkoutUrl": "..." }
POST /order-status
Request:
{ "orderId": "..." }
or
{ "sessionId": "..." }
Response:
{ "orderId": "...", "status": "pending|paid|failed|canceled" }
POST /payment-webhook
Stripe calls this endpoint. The backend verifies signature and fulfills idempotently.
Production Checklist
- Verify webhook signatures with raw request body.
- Store processed webhook event IDs (idempotency).
- Create internal order before checkout session creation.
- Enforce order ownership checks on status API.
- Keep plan pricing authoritative on backend/DB (never trust client amount).
- Make fulfillment webhook-driven, not redirect-driven.
- Add retry-safe entitlement logic (grant once).
Final Takeaway
Treat the hosted checkout redirect as UX, and the webhook as truth.
That single decision makes your billing flow robust, auditable, and far less fragile in real-world conditions.