Separate checkout from entitlement
A successful redirect means the customer returned from checkout, not necessarily that payment is settled. Store provider IDs and update access from verified webhook events.
- Create a server-side checkout session with the selected product and amount.
- Redirect the browser to the provider's hosted checkout.
- Return to a neutral success or cancel page.
- Verify webhook signatures and process events idempotently.
- Update the local order or subscription status and show it in the app.
Subscription states
This comes down to a handful of concrete details. Work through the list below and flag the ones you have not covered yet.
- Trialing or pending: access rules are explicit.
- Active: entitlement is available.
- Past due: show a billing action without deleting data.
- Canceled: retain the history and end access at the correct time.
- Refunded or disputed: follow a defined business rule.
Test before launch
Use provider test mode to cover successful payment, cancellation, duplicate webhooks, failed renewal, refund and a customer returning to an old success URL.
Pre-launch payment checklist
Use the list below as a working checklist. Each item is something you can verify or action directly on your own site.
- Live mode keys are set and test mode keys are removed from production.
- Prices and product IDs used by the backend match what is live in the provider dashboard.
- Tax, currency and invoice settings match the business's actual requirements.
- A customer can reach a working support contact if a charge looks wrong.
- Failed renewal emails and dunning behaviour are configured, not left on defaults.
Common failure examples
Here are the key things to get right. None of them are complicated on their own, but skipping one tends to undermine the rest.
- A customer pays but the webhook fails silently, so access never activates. Fix: alert on webhook failures, not just log them.
- A cancelled subscription still shows as active because the frontend caches the old status. Fix: refetch entitlement after any billing-related redirect.
- A duplicate webhook creates two orders for one payment. Fix: key processing off the provider's event ID, not the timestamp.