MuseMVP Docs
Billing

Billing Configuration

Choose a gateway, connect your products, and complete your first sandbox checkout.

Connect one gateway first. Your goal is a complete sandbox purchase: a signed-in user checks out, the webhook arrives, and the app shows the correct plan.

Before You Start

Have a working app and a gateway account with sandbox/test access. Prepare the plans you want to sell, their amounts, currency, and billing intervals. For webhooks, use a publicly reachable HTTPS test deployment or a provider-supported forwarding tool.

Keep live credentials and real charges out of this first test. You can keep config.payments.enableBilling=false until configuration is ready.

1. Choose One Gateway

GatewaySetup guideMain credential
CreemCreemCREEM_API_KEY
StripeStripeSTRIPE_SECRET_KEY
Dodo PaymentsDodoDODO_PAYMENTS_API_KEY
WaffoWaffoWAFFO_MERCHANT_ID and WAFFO_PRIVATE_KEY

Choose based on merchant eligibility, markets, payment methods, and business needs. Availability depends on the provider and your account; you do not need all four accounts.

2. Connect Your Plans

In packages/config/src/index.ts, keep your stable app plan IDs in payments.productCatalog. In your selected app:

  • src/config/saas/pricing-desc.ts: plan titles, descriptions, features.
  • src/config/saas/pricing-desc-usage.ts: amounts, currency, recurring intervals, and purchasable items.

Create matching products/prices in the gateway dashboard. Follow its guide for the exact ID to copy. Map each configured plan to that gateway's environment variables. For example, a Stripe setup in the app .env.local uses:

BILLING_DEFAULT_GATEWAY="muse_stripe"
STRIPE_SECRET_KEY="YOUR_TEST_SECRET_KEY"
STRIPE_WEBHOOK_SECRET="YOUR_TEST_WEBHOOK_SECRET"
STRIPE_PRODUCT_ID_PRO_MONTHLY="YOUR_MONTHLY_PRICE_ID"
STRIPE_PRODUCT_ID_PRO_YEARLY="YOUR_YEARLY_PRICE_ID"
STRIPE_PRODUCT_ID_LIFETIME="YOUR_ONE_TIME_PRICE_ID"

Keep provider price, currency, and interval aligned with the app. originalAmount only displays a comparison price; it does not change the gateway price. Follow Environment Variables for local and production credentials.

3. Register the Webhook

Use your test origin plus the gateway path:

GatewayPath
Creem/api/muse-billing/notify/muse_creem
Stripe/api/muse-billing/notify/muse_stripe
Dodo/api/muse-billing/notify/muse_dodo
Waffo/api/muse-billing/notify/muse_waffo

Copy the provider's signing secret where applicable and enable the events listed in its guide. Waffo uses its SDK signature verifier and WAFFO_ENVIRONMENT=test, without a separate webhook-secret variable. A browser success redirect alone does not establish paid access; the server processes webhook state.

4. Complete a Sandbox Purchase

Enable payments.enableBilling, restart/redeploy with your test settings, and sign in as a development user. Open /pricing, choose a configured plan, and complete checkout with the provider's sandbox method. Wait for the webhook, then inspect the user's plan and account billing page.

Check Your Result

  • Pricing shows the intended plan and the provider checkout uses the expected amount, currency, and interval.
  • The provider reports successful webhook delivery.
  • The app shows the correct plan/access window for the purchasing user after refresh.
  • Subscription management works through the gateway portal when using a subscription plan.
  • A failed or canceled checkout does not grant paid access.

Common Problems

ProblemFix
Gateway is missing or checkout failsCheck the selected gateway's credentials and product mappings; restart after local changes
Product/price not foundCheck the exact ID type and sandbox/live environment in the gateway guide
Webhook never arrivesUse a public HTTPS endpoint or forwarding tool; check the provider delivery log and URL
Signature is rejectedMatch the endpoint's signing secret; for Waffo check signature header and environment
Checkout succeeds but the plan stays unchangedInspect webhook delivery, server errors, and contract matching rather than only the return URL

Before switching to live mode, create live products, replace test credentials and webhook configuration, and complete the Release Checklist. Do not use development seed accounts in production.

On this page