Billing Overview
Learn how to manage subscriptions and billing in your application.
Note: This is mock/placeholder content for demonstration purposes.
The billing system supports subscription-based pricing with multiple tiers and payment providers.
Supported Providers
Stripe
Industry-standard payment processing with comprehensive features:
- Credit card payments
- Subscription management
- Invoice generation
- Tax calculation
- Customer portal
Paddle
Merchant of record solution that handles:
- Global tax compliance
- Payment processing
- Subscription billing
- Revenue recovery
Subscription Tiers
Define your subscription tiers in the billing configuration:
export const plans = [
{
id: 'free',
name: 'Free',
price: 0,
features: ['Feature 1', 'Feature 2'],
},
{
id: 'pro',
name: 'Professional',
price: 29,
interval: 'month',
features: ['All Free features', 'Feature 3', 'Feature 4'],
},
{
id: 'enterprise',
name: 'Enterprise',
price: 99,
interval: 'month',
features: ['All Pro features', 'Feature 5', 'Priority support'],
},
];
Subscription Lifecycle
- Customer selects plan - User chooses subscription tier
- Payment processed - Provider handles payment collection
- Webhook received - Your app receives confirmation
- Subscription activated - User gains access to features
- Recurring billing - Automatic renewal each period
- Cancellation - User can cancel anytime
Managing Subscriptions
Creating a Subscription
import { createCheckoutSession } from '~/lib/billing/checkout';
const session = await createCheckoutSession({
accountId: user.accountId,
planId: 'pro',
returnUrl: '/dashboard',
});
// Redirect user to payment page
redirect(session.url);
Checking Subscription Status
import { getSubscription } from '~/lib/billing/subscription';
const subscription = await getSubscription(accountId);
if (subscription.status === 'active') {
// User has active subscription
}
Canceling a Subscription
import { cancelSubscription } from '~/lib/billing/subscription';
await cancelSubscription(subscriptionId);
Webhook Handling
Webhooks notify your application of billing events:
export async function POST(request: Request) {
const signature = request.headers.get('stripe-signature');
const payload = await request.text();
const event = stripe.webhooks.constructEvent(
payload,
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
switch (event.type) {
case 'customer.subscription.created':
await handleSubscriptionCreated(event.data.object);
break;
case 'customer.subscription.updated':
await handleSubscriptionUpdated(event.data.object);
break;
case 'customer.subscription.deleted':
await handleSubscriptionCanceled(event.data.object);
break;
}
return new Response('OK');
}
Testing
Use test mode credentials for development:
- Test card: 4242 4242 4242 4242
- Any future expiry date
- Any CVC
All test transactions will appear in your provider's test dashboard.