ShipNext
Payment Integration

Stripe

Configure the default Stripe payment provider for subscriptions, Checkout, Customer Portal, and Price IDs.

ShipNext's default payment provider is Stripe. The provider is selected in config/website.ts:

const paymentConfig = {
  provider: "stripe",
  planChange: {
    chargeStrategy: "flat_difference",
  },
  testingEnabled: false,
};

Provider code lives in src/integrations/payment/stripe/; business code talks to it through getPaymentProvider().

Configuration locations

ItemLocationDescription
Provider selectionconfig/website.tspayment.provider = "stripe"
Plans and entitlementssrc/modules/billing/config/plan.tsFree, starter, pro, Price IDs, credits
Checkout APIapp/api/payment/checkout/route.tsCreates Stripe Checkout Sessions
Billing Portalapp/api/payment/portal/route.tsOpens Stripe Customer Portal
Webhookapp/api/payment/webhook/route.tsSyncs subscriptions, orders, and entitlements

Environment variables

NEXT_PUBLIC_STARTER_MONTHLY_PRICE_ID=''
NEXT_PUBLIC_STARTER_YEARLY_PRICE_ID=''
NEXT_PUBLIC_PRO_MONTHLY_PRICE_ID=''
NEXT_PUBLIC_PRO_YEARLY_PRICE_ID=''
STRIPE_SECRET_KEY=''
STRIPE_WEBHOOK_SECRET=''

Public Price IDs are read by plan.ts and used by pricing and Checkout. STRIPE_SECRET_KEY is server-only. Use sk_test_... for testing and sk_live_... in production.

Stripe Dashboard setup

  1. Create Products and Prices for starter and pro, monthly and yearly.
  2. Keep displayed amounts in plan.ts aligned with Stripe Price amounts.
  3. Put Price IDs in the matching NEXT_PUBLIC_*_PRICE_ID variables.
  4. Enable Customer Portal and configure subscription, payment method, and invoice options.
  5. Configure the webhook endpoint:
https://<your-domain>/api/payment/webhook

For local testing:

stripe listen --forward-to localhost:3000/api/payment/webhook

Copy the CLI whsec_... value into STRIPE_WEBHOOK_SECRET.

Current boundaries

  • Checkout success and cancel URLs use NEXT_PUBLIC_APP_URL and redirect to /dashboard/settings/billing.
  • PAYMENT_TESTING_ENABLED references older test paths and an unimplemented /api/payment/test; do not treat it as production-ready without fixing that test flow.
  • websiteConfig.payment.testingEnabled exists, but runtime behavior mostly depends on PAYMENT_TESTING_ENABLED.

Checklist

  • NEXT_PUBLIC_APP_URL matches the current environment.
  • Every enabled paid price has a real Stripe Price ID.
  • Pricing CTA opens Checkout for logged-in users.
  • Webhook syncs subscriptions and entitlements after payment.
  • Production disables or removes payment test mode.

See Payment webhooks for event processing details.

On this page