import Stripe from 'stripe'; import { config } from '../config'; import { query } from '../db'; const stripe = new Stripe(config.stripe.secretKey, { apiVersion: '2024-06-20' }); // Annual plans are 20% off (pay 10 months, get 12) export const PLAN_PRICES: Record = { free: { monthly: 0, annual: 0, label: 'Free' }, solo: { monthly: 9.99, annual: 95.90, label: 'Solo' }, host: { monthly: 29.99, annual: 287.90, label: 'Host' }, agency: { monthly: 79.99, annual: 767.90, label: 'Agency' }, }; export async function getOrCreateStripeCustomer(data: { customerId: string; email: string; name: string; stripeCustomerId?: string | null; }): Promise { if (data.stripeCustomerId) return data.stripeCustomerId; const stripeCustomer = await stripe.customers.create({ email: data.email, name: data.name, metadata: { nixpanel_customer_id: data.customerId }, }); await query( 'UPDATE customers SET stripe_customer_id = ? WHERE id = ?', [stripeCustomer.id, data.customerId] ); return stripeCustomer.id; } export async function createCheckoutSession(data: { stripeCustomerId: string; priceId: string; planKey: string; interval: 'monthly' | 'annual'; serverIp: string; customerId: string; successUrl: string; cancelUrl: string; }): Promise { const session = await stripe.checkout.sessions.create({ customer: data.stripeCustomerId, mode: 'subscription', line_items: [{ price: data.priceId, quantity: 1 }], success_url: data.successUrl, cancel_url: data.cancelUrl, metadata: { nixpanel_customer_id: data.customerId, plan_key: data.planKey, billing_interval: data.interval, server_ip: data.serverIp, }, subscription_data: { metadata: { nixpanel_customer_id: data.customerId, plan_key: data.planKey, server_ip: data.serverIp, }, }, }); return session.url!; } export async function createBillingPortalSession( stripeCustomerId: string, returnUrl: string ): Promise { const session = await stripe.billingPortal.sessions.create({ customer: stripeCustomerId, return_url: returnUrl, }); return session.url; } export async function cancelSubscription(stripeSubscriptionId: string): Promise { await stripe.subscriptions.update(stripeSubscriptionId, { cancel_at_period_end: true, }); await query( 'UPDATE subscriptions SET cancel_at_period_end = 1 WHERE stripe_subscription_id = ?', [stripeSubscriptionId] ); } export async function changeSubscriptionPlan(data: { stripeSubscriptionId: string; newPriceId: string; }): Promise { const sub = await stripe.subscriptions.retrieve(data.stripeSubscriptionId); await stripe.subscriptions.update(data.stripeSubscriptionId, { items: [{ id: sub.items.data[0].id, price: data.newPriceId }], proration_behavior: 'create_prorations', }); } export async function constructWebhookEvent( payload: Buffer, signature: string ): Promise { return stripe.webhooks.constructEvent(payload, signature, config.stripe.webhookSecret); } export { stripe };