import { NextRequest, NextResponse } from 'next/server'; import { auth } from '@/auth'; import { stripe } from '@/lib/stripe'; import { resolvePriceId } from '@/lib/billing/stripe-prices'; import { prisma } from '@/lib/prisma'; import { z } from 'zod'; const bodySchema = z.object({ tier: z.enum(['PRO', 'BUSINESS']), interval: z.enum(['month', 'year']), }); export async function POST(req: NextRequest) { const session = await auth(); if (!session?.user?.id || !session.user.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const parsed = bodySchema.safeParse(await req.json()); if (!parsed.success) { return NextResponse.json({ error: 'Invalid request body' }, { status: 400 }); } const { tier, interval } = parsed.data; const userId = session.user.id; const userEmail = session.user.email; try { const priceId = resolvePriceId(tier, interval); const subscription = await prisma.subscription.findUnique({ where: { userId } }); let customerId = subscription?.stripeCustomerId ?? undefined; if (!customerId) { const customer = await stripe.customers.create({ email: userEmail, metadata: { userId }, }); customerId = customer.id; } const origin = req.headers.get('origin') ?? process.env.NEXTAUTH_URL ?? 'http://localhost:3000'; const sessionParams = { customer: customerId, mode: 'subscription' as const, line_items: [{ price: priceId, quantity: 1 }], ui_mode: 'embedded', return_url: `${origin}/settings/billing?session_id={CHECKOUT_SESSION_ID}`, metadata: { userId, tier }, subscription_data: { metadata: { userId, tier } }, customer_update: { address: 'auto' }, }; const checkoutSession = await stripe.checkout.sessions.create(sessionParams as any); if (checkoutSession.client_secret) { return NextResponse.json({ clientSecret: checkoutSession.client_secret, sessionId: checkoutSession.id, }); } return NextResponse.json({ url: checkoutSession.url }); } catch (error) { console.error('[billing/create-checkout]', error); return NextResponse.json({ error: 'Failed to create checkout session' }, { status: 500 }); } }