The Better Auth Stripe plugin provides a simple, zero-configuration payment system using external Stripe checkout pages only. This is separate from the Custom Boilerplate's advanced checkout system.
External checkout only: Better Auth uses Stripe-hosted external checkout pages. For embedded forms, guest checkout, or installments, use the Custom Boilerplate System.
Perfect for: Simple SaaS subscriptions where users create accounts before purchasing and you prefer zero configuration over advanced features.
The Stripe plugin is configured in src/lib/better-auth/auth.ts and provides automatic integration:
// From src/lib/better-auth/auth.ts
import { stripe } from '@better-auth/stripe'
import { stripeClient } from '@/lib/stripe/stripe-client'
import { onStripeEvent } from '@/lib/stripe/stripe-events'
plugins: [
// ... other plugins
stripe({
stripeClient,
stripeWebhookSecret: env.STRIPE_WEBHOOK_SECRET,
createCustomerOnSignUp: true,
subscription: {
enabled: true,
plans: () => getActivePlansForBetterAuthService(),
authorizeReference: createAuthorizeReference(),
// Subscription lifecycle hooks...
},
onEvent: onStripeEvent,
}),
]Better Auth Stripe Checkout Interface:
Automatic Customer Creation
// From src/lib/better-auth/auth.ts
stripe({
createCustomerOnSignUp: true, // Automatically create Stripe customer
stripeClient,
stripeWebhookSecret: env.STRIPE_WEBHOOK_SECRET,
})What happens automatically:
Seamless integration: Users don't need to know about Stripe customers - it's all handled automatically during registration.
The plugin provides hooks for all subscription events with automatic notification integration:
// From src/lib/better-auth/auth.ts
onSubscriptionComplete: async ({ subscription }) => {
if (!subscription.stripeCustomerId) {
return
}
const user = await getUserByStripeCustomerIdDao(
subscription.stripeCustomerId as string
)
if (user) {
await createTypedNotificationService({
userId: user.id,
type: NotificationTypeConst.subscription_created,
metadata: { subscription },
})
}
}What happens:
// From src/lib/better-auth/auth.ts
onSubscriptionUpdate: async ({ subscription }) => {
if (!subscription.stripeCustomerId) {
return
}
const user = await getUserByStripeCustomerIdDao(
subscription.stripeCustomerId as string
)
if (user) {
await createTypedNotificationService({
userId: user.id,
type: NotificationTypeConst.subscription_updated,
metadata: { subscription },
})
}
}Triggers on:
// From src/lib/better-auth/auth.ts
onSubscriptionCancel: async ({ subscription }) => {
if (!subscription.stripeCustomerId) {
return
}
const user = await getUserByStripeCustomerIdDao(
subscription.stripeCustomerId as string
)
if (user) {
await createTypedNotificationService({
userId: user.id,
type: NotificationTypeConst.subscription_canceled,
metadata: { subscription },
})
}
}Cancellation handling:
// From src/lib/better-auth/auth.ts
onSubscriptionDeleted: async ({ subscription }) => {
if (!subscription.stripeCustomerId) {
return
}
const user = await getUserByStripeCustomerIdDao(
subscription.stripeCustomerId as string
)
if (user) {
await createTypedNotificationService({
userId: user.id,
type: NotificationTypeConst.subscription_deleted,
metadata: { subscription },
})
}
}The plugin automatically manages subscription data with your database:
// From src/db/repositories/user-repository.ts
getUserByStripeCustomerIdDao(stripeCustomerId: string)Maintains:
// From src/services/facades/subscription-service-facade.ts
getActivePlansForBetterAuthService()Provides:
The plugin delegates custom events to your handler:
// From src/lib/stripe/stripe-events.ts
export const onStripeEvent = async (event: Stripe.Event) => {
// Custom business logic for Stripe events
// Handle events not covered by the plugin
console.log(`Processing Stripe event: ${event.type}`)
// Add your custom event handling here
switch (event.type) {
case 'invoice.payment_failed':
// Handle failed payments
break
case 'customer.subscription.trial_will_end':
// Send trial ending notifications
break
// Add more custom events...
}
}Automatic Verification
// Plugin automatically verifies webhook signatures
stripe({
stripeWebhookSecret: env.STRIPE_WEBHOOK_SECRET,
})Security measures:
Automatic customer creation, webhook processing, and database synchronization
Webhooks automatically update subscription status and user access
Automatic email notifications for all subscription lifecycle events
Webhook verification, authorization checks, and secure data handling
Check your application logs for successful plugin initialization:
[Better Auth] Stripe plugin loaded successfully
[Better Auth] Webhook endpoint: /api/auth/stripe/webhook
Better Auth Stripe integration complete! Your authentication system now seamlessly manages Stripe customers and subscriptions with zero additional configuration.