Payments
Set up Stripe, Polar, or Dodo Payments via Better Auth plugins to handle one-time and subscription payments.
Setup
Stripe
- Sign up at Stripe and create an account.
- Create a Product in the Stripe Dashboard.
- Add pricing plans (e.g. Monthly $10, Yearly $60).
- Copy the Price IDs (they look like
price_xxx).
- Copy your Secret Key and Webhook Secret from the Stripe Dashboard (Developers > API Keys and Webhooks).
- Set the following environment variables:
.env
STRIPE_SECRET_KEY="your-stripe-secret-key" STRIPE_WEBHOOK_SECRET="your-stripe-webhook-secret" - Update pricing plans in your config:
shared/config.ts
pricing: { paymentProvider: enums.paymentProvider.stripe, // Set paymentProvider Stripe successUrlPath: '/payment-success', // Redirect after successful payment failedUrlPath: '/payment-failed', // Redirect after failed payment plans: { pro: { enable: true, // Is show Pro Plan key: 'pro', monthly: { key: 'pro-monthly', priceId: 'price_monthly', // Set Stripe Price ID for monthly subscription mode: 'subscription', // Payment is subscription }, yearly: { key: 'pro-yearly', priceId: 'price_yearly', // Set Stripe Price ID for yearly subscription mode: 'subscription', // Payment is subscription }, }, lifetime: { enable: true, // Is show Lifetime Plan key: 'lifetime', priceId: 'price_lifetime', // Set Stripe Price ID for one-time payment promoCodeId: '', // Optional - Set Stripe Promo ID for any promo/coupon to discount mode: 'payment', // Payment is one-time }, }, }, - Set up a webhook:
- Local: Use Stripe CLICopy the Webhook Secret intoTerminal
stripe listen --forward-to localhost:3000/api/auth/stripe/webhook.env. - Production: Add a webhook endpoint in Stripe Dashboard pointing to:
Select events like
https://your-site.com/api/auth/stripe/webhookcheckout.session.completed,customer.subscription.created,customer.subscription.updated, andcustomer.subscription.deleted.
- Local: Use Stripe CLI
Polar
- Sign up at Polar and create an account.
- Create a Product in the Polar Dashboard.
- Add pricing plans (e.g. Monthly $10, Yearly $60).
- Copy the Product IDs (found in the product details/API settings).
- Generate a Personal Access Token (or Organization Token) and configure a Webhook in the Polar Dashboard (Settings > Developers).
- Set the following environment variables:
.env
POLAR_ACCESS_TOKEN="your-polar-access-token" POLAR_WEBHOOK_SECRET="your-polar-webhook-secret" - Update pricing plans in your config:
shared/config.ts
pricing: { paymentProvider: enums.paymentProvider.polar, // Set paymentProvider Polar successUrlPath: '/payment-success', // Redirect after successful payment failedUrlPath: '/payment-failed', // Redirect after failed payment plans: { pro: { enable: true, // Is show Pro Plan key: 'pro', monthly: { key: 'pro-monthly', priceId: 'price_monthly', // Set Polar Product ID for monthly subscription mode: 'subscription', // Payment is subscription }, yearly: { key: 'pro-yearly', priceId: 'price_yearly', // Set Polar Product ID for yearly subscription mode: 'subscription', // Payment is subscription }, }, lifetime: { enable: true, // Is show Lifetime Plan key: 'lifetime', priceId: 'price_lifetime', // Set Polar Product ID for one-time payment mode: 'payment', // Payment is one-time }, }, }, - Set up a webhook:
- Local: Use a tunneling service (like ngrok) or Polar's CLI if available to forward events to your local environment. Copy the Webhook Secret into
.env. - Production: Add a webhook endpoint in Polar Dashboard pointing to:
Select at least the following events like
https://your-site.com/api/auth/polar/webhooksorder.created,subscription.created,subscription.updated,subscription.canceled.
- Local: Use a tunneling service (like ngrok) or Polar's CLI if available to forward events to your local environment. Copy the Webhook Secret into
Dodo Payments
- Sign up at Dodo Payments and create an account.
- Create a Product and its associated pricing plans in the Dodo Payments Dashboard.
- Copy the Product IDs (they typically start with
pdt_) for each unique plan/interval.
- Copy the Product IDs (they typically start with
- Copy your API Key and Webhook Secret from the Dodo Payments Dashboard (Developer > API Keys and Webhooks).
- Set the following environment variables:
.env
DODO_PAYMENTS_API_KEY="your-dodo-api-key" DODO_PAYMENTS_WEBHOOK_SECRET="your-dodo-webhook-secret" - Update pricing plans in your config:
shared/config.ts
pricing: { paymentProvider: enums.paymentProvider.dodo, // Set paymentProvider Dodo successUrlPath: '/payment-success', // Redirect after successful payment failedUrlPath: '/payment-failed', // Redirect after failed payment plans: { pro: { enable: true, // Is show Pro Plan key: 'pro', monthly: { key: 'pro-monthly', priceId: 'price_monthly', // Set Dodo Product ID for monthly subscription mode: 'subscription', // Payment is subscription }, yearly: { key: 'pro-yearly', priceId: 'price_yearly', // Set Dodo Product ID for yearly subscription mode: 'subscription', // Payment is subscription }, }, lifetime: { enable: true, // Is show Lifetime Plan key: 'lifetime', priceId: 'price_lifetime', // Set Dodo Product ID for one-time payment mode: 'payment', // Payment is one-time }, }, }, - Set up a webhook:
- Local: Use a tunneling service (like ngrok) to expose your local development server.
Copy the resulting URL and add /api/payment/dodo/webhook to it for the Dodo Webhook configuration.terminal
# Example using ngrok to tunnel to your app's port ngrok http 3000 - Production: Add a webhook endpoint in Dodo Payments Dashboard pointing to:
Select at lease the following events like
https://your-site.com/api/payment/dodo/webhookpayment.succeeded,payment.failed,subscription.active,subscription.updated,subscription.renewed,subscription.cancelled,subscription.on_hold, andsubscription.failed.
- Local: Use a tunneling service (like ngrok) to expose your local development server.
Usage
- Handle Webhooks: Plugin automatically updates subscription status on payment events.
- Verify Payments: Check transactions and subscriptions in the plugin dashboard.
- Initiate Checkout: Use the
paymentCheckoutfunction to start a payment.Users are redirected to payment's checkout page, then back toconst { payment } = useAuth(); payment.paymentCheckout(appConfig.pricing.plans.lifetime.key, locale.value);successUrlPathorfailedUrlPath - Customer Portal: Let users manage subscriptions, invoices, and payment methods:
const { payment } = useAuth(); payment.toCustomerPortal();