Billing Provider Editions
Choose one provider edition, map its catalog, verify signed events, and run the durable billing worker before accepting live payments.
On this page
Provider setup matrix
Use the row that matches the branch you received. A buyer checkout should contain one row's provider code and credentials, not all five rows' SDKs.
| Provider | Provider environment | Catalog key | Required provider values | Models | Webhook |
|---|---|---|---|---|---|
| Stripe | Test mode or live mode | stripePriceId | STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, BILLING_PORTAL_CONFIGURATION_ID | All five | /api/webhooks/stripe/billing |
| Lemon Squeezy | Store/test or live | lemonsqueezyVariantId | LEMONSQUEEZY_API_KEY, LEMONSQUEEZY_STORE_ID, LEMONSQUEEZY_WEBHOOK_SECRET | All five | /api/webhooks/lemonsqueezy |
| Dodo Payments | test_mode or live_mode | dodoProductId | DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_WEBHOOK_KEY, DODO_PAYMENTS_ENVIRONMENT | All five | /api/webhooks/dodo |
| Polar | sandbox or production | polarProductId | POLAR_ACCESS_TOKEN, POLAR_WEBHOOK_SECRET, POLAR_SERVER | All five | /api/webhooks/polar |
| Creem | test_mode or live_mode | creemProductId | CREEM_API_KEY, CREEM_WEBHOOK_SECRET, CREEM_ENVIRONMENT | Recurring, one-time, credits | /api/webhooks/creem |
Provider launch sequence
- 1
Create provider resources in test mode
Create products, recurring prices or variants, one-time offers, meters, and portal settings in the provider's test or sandbox environment. Keep the provider mode aligned with the environment and catalog IDs.
- One resource for each selected plan or offer
- One catalog mapping for every enabled billing model
- No production credentials in local development
- 2
Set the runtime controls
The active provider edition supplies provider identity. Set model selection and catalog configuration explicitly; keep production locks enabled when deployment configuration must be authoritative.
textBILLING_ENABLED_MODELS=licensed_recurring,prepaid_credits BILLING_PRESET=hybrid BILLING_MODELS_LOCKED=true BILLING_CATALOG_JSON=<validated-catalog-json> BILLING_WEBHOOK_BATCH_SIZE=20 BILLING_WEBHOOK_CONCURRENCY=5 - 3
Register the application webhook
Configure the provider dashboard with the matching HTTPS endpoint and signing secret. The route verifies the unmodified request body and stores a durable verified event before projection.
- Stripe: /api/webhooks/stripe/billing
- Lemon Squeezy: /api/webhooks/lemonsqueezy
- Dodo: /api/webhooks/dodo
- Polar: /api/webhooks/polar
- Creem: /api/webhooks/creem
- 4
Deploy the optional Supabase Edge ingress
The shared billing-webhooks Edge Function can verify and enqueue provider events close to Supabase. It does not replace the Next.js billing projection worker. Keep one public destination active for each provider event while testing the rollout.
textpnpm dlx supabase secrets set --env-file supabase/.env.edge pnpm dlx supabase functions deploy billing-webhooks --no-verify-jwt - 5
Schedule the billing worker
Run GET /api/cron/billing-webhooks every 1–5 minutes with Authorization: Bearer <CRON_SECRET>. The worker claims verified events, retries transient failures, and moves exhausted events to dead letter. Schedule each job once through Supabase Cron, the hosting provider, or one external scheduler.
- Keep BILLING_WEBHOOK_BATCH_SIZE bounded
- Keep concurrency below the batch size
- Alert on queue age, failed attempts, and dead letters
- Never log raw provider payloads or secrets
Implementation reference3 areas
These Product code locations explain how the documented behavior is implemented. Expand them when you are ready to customize or maintain this area.
Edition lock and adapter composition
Distribution metadata and the selected adapter composition keep provider-specific dependencies out of the buyer's runtime boundary.
src/config/product-distribution.tssrc/features/billing/server/providers/runtime/selected.tssrc/features/billing/server/providers/runtime/adapter-contract.ts
Provider implementation boundaries
Each provider owns its checkout, pricing, portal, usage, refund, and webhook normalization behavior behind app-owned billing contracts.
src/features/billing/server/providers/stripe/checkout.tssrc/features/billing/server/providers/lemonsqueezy/checkout.tssrc/features/billing/server/providers/dodo/checkout.tssrc/features/billing/server/providers/polar/checkout.tssrc/features/billing/server/providers/creem/checkout.ts
Durable event projection
The selected ingress and worker separate signature verification from provider projection, allowing retries and duplicate delivery to be handled safely.
src/app/api/cron/billing-webhooks/route.tssrc/features/billing/server/webhooks/cron.tssrc/features/billing/server/webhooks/worker.tssupabase/functions/billing-webhooks/handler.ts
Reference paths are relative to the delivered product checkout.
Ready for live billing when
- The selected branch and provider mode match the credentials and catalog IDs.
- Every enabled billing model has a provider resource and a validated catalog entry.
- A signed test webhook creates exactly one durable event and one local projection.
- A replayed or duplicate webhook does not create a second order, entitlement, credit grant, or notification.
- Portal, cancellation, refund, usage, and credit behavior has been tested where supported.
- The billing worker is scheduled once, monitored, and has an owner for dead-letter recovery.