Subscription Management
Learn how to handle subscriptions, upgrades, downgrades, and cancellations in your application.
Creating Subscriptions
Create a subscription when a customer selects a plan:
// Create a subscriptionconst subscription = await stripe.subscriptions.create({customer: customerId,items: [{ price: priceId }],payment_behavior: "default_incomplete",payment_settings: {save_default_payment_method: "on_subscription",},expand: ["latest_invoice.payment_intent"],});// Return the client secret for payment confirmationconst clientSecret = subscription.latest_invoice.payment_intent.client_secret;
Managing Subscriptions
Handle common subscription operations:
// Update subscription (e.g., change plan)const updatedSubscription = await stripe.subscriptions.update(subscriptionId, {items: [{id: subscriptionItemId,price: newPriceId,},],proration_behavior: "always_invoice",});// Cancel subscriptionconst canceledSubscription = await stripe.subscriptions.update(subscriptionId, {cancel_at_period_end: true,});// Reactivate subscriptionconst reactivatedSubscription = await stripe.subscriptions.update(subscriptionId,{cancel_at_period_end: false,});// Add usage record (for metered billing)await stripe.subscriptionItems.createUsageRecord(subscriptionItemId, {quantity: 10,timestamp: "now",action: "increment",});
Handling Subscription Status
Track and respond to subscription status changes:
// Get subscription statusexport async function getSubscriptionStatus(subscriptionId: string) {const subscription = await stripe.subscriptions.retrieve(subscriptionId);return {status: subscription.status,cancelAtPeriodEnd: subscription.cancel_at_period_end,currentPeriodEnd: subscription.current_period_end,trialEnd: subscription.trial_end,};}// Check if subscription is activeexport function isSubscriptionActive(subscription: Stripe.Subscription) {return (subscription.status === "active" ||subscription.status === "trialing");}
Customer Portal
Let customers manage their subscriptions through the Stripe Customer Portal:
// Create a portal sessionexport async function createPortalSession(customerId: string) {const session = await stripe.billingPortal.sessions.create({customer: customerId,return_url: `${process.env.NEXT_PUBLIC_SITE_URL}/settings/billing`,});return session.url;}// Configure portal features in Stripe Dashboard:// - Subscription management// - Payment method updates// - Billing history// - Customer information updates
Best Practices
- Always handle webhooks for subscription status changes
- Implement proper error handling for failed payments
- Consider offering a trial period for new subscriptions
- Use metadata to store additional subscription information
- Sync subscription data with your database