Payments

Payments use one active billing provider, local catalog configuration, checkout services, portal access, webhook projection, and provider-specific troubleshooting.

On this page

Billing module

Provider selection, catalog, checkout, webhooks, and billing rules.

Read Billing module

Customer billing

Customer history, portal access, ledgers, exports, refunds, and disputes.

Read Customer billing

Troubleshooting

Provider setup, webhook secrets, customer projection, and empty history checks.

Read Troubleshooting

Provider model

AreaHow the app handles it
StripeSupports checkout, portal, subscriptions, one-time purchases, usage, base-plus-usage, credits, invoices, refunds, disputes, and exports.
Lemon SqueezySupports checkout, subscriptions, one-time purchases, usage-oriented catalog setup, app-local prepaid-credit grants, portal-style customer flows, and provider webhooks.
One-time purchasesUse licensed_one_time catalog entries and provider price ids.
Customer portalUse the active provider and current signed-in billing customer record.
WebhooksVerify signature, claim event row, dispatch by event type, project local billing state, and mark event status.

Recipe: switch payment provider

Move between Stripe and Lemon Squeezy without leaving catalog, setup, checkout, and webhook behavior inconsistent.

Implementation locations

Inspect

  • src/features/billing/server/runtime/provider.ts
  • src/features/billing/server/catalog/configuration.ts
  • src/features/billing/server/runtime/readiness.ts
  • src/features/billing/server/providers/stripe/checkout.ts
  • src/features/billing/server/providers/lemonsqueezy/checkout.ts

Edit

  • BILLING_PROVIDER
  • BILLING_CATALOG_JSON
  • BILLING_ENABLED_MODELS
  • src/features/billing/server/catalog/configuration.ts

Steps

  • Select the active provider and decide whether settings may override env.
  • Replace catalog product and price ids with provider-compatible values.
  • Configure the matching webhook endpoint and secret.
  • Open /billing/setup and resolve every readiness failure.
  • Run a provider test checkout and confirm local billing projection updates.

Verify

  • pnpm run test:features
  • pnpm run quality
  • Open /billing/setup and run provider test mode.

Common mistakes

  • Do not reuse Stripe Price IDs for Lemon Squeezy credit offers; map a same-mode Lemon Squeezy variant and keep credits in the app-local ledger.
  • Do not reuse webhook secrets from a different endpoint.
  • Do not assume provider events arrive in order.