import Stripe from 'stripe';
import express from 'express';
// ============================================
// Configuration
// ============================================
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16', // Update to latest
});
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!;
// ============================================
// Services
// ============================================
export const stripeService = {
// Create Checkout Session
async createCheckoutSession(priceId: string, customerId?: string) {
const session = await stripe.checkout.sessions.create({
mode: 'subscription', // or 'payment'
payment_method_types: ['card'],
line_items: [
{
price: priceId,
quantity: 1,
},
],
customer: customerId,
success_url: `${process.env.DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.DOMAIN}/cancel`,
});
return session;
},
// Create Customer Portal Session
async createPortalSession(customerId: string) {
const session = await stripe.billingPortal.sessions.create({
customer: customerId,
return_url: `${process.env.DOMAIN}/account`,
});
return session;
},
// Get Customer Subscription
async getSubscription(customerId: string) {
const subscriptions = await stripe.subscriptions.list({
customer: customerId,
status: 'active',
limit: 1,
});
return subscriptions.data[0] || null;
}
};
// ============================================
// Webhook Handler
// ============================================
export const webhookHandler = async (req: express.Request, res: express.Response) => {
const sig = req.headers['stripe-signature'];
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
req.body, // Must be raw buffer
sig!,
endpointSecret
);
} catch (err: any) {
console.error(`Webhook Error: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
try {
switch (event.type) {
case 'checkout.session.completed': {
const session = event.data.object as Stripe.Checkout.Session;
// Provision access, update database, send email
console.log('Payment successful for session:', session.id);
break;
}
case 'customer.subscription.updated': {
const subscription = event.data.object as Stripe.Subscription;
// Update subscription status in DB
console.log('Subscription updated:', subscription.id);
break;
}
case 'customer.subscription.deleted': {
const subscription = event.data.object as Stripe.Subscription;
// Revoke access
console.log('Subscription canceled:', subscription.id);
break;
}
default:
console.log(`Unhandled event type ${event.type}`);
}
} catch (error) {
console.error('Error processing webhook:', error);
return res.status(500).send('Error processing webhook');
}
res.json({ received: true });
};