import { NextResponse } from 'next/server' import { z } from 'zod' import { stripe } from '@/lib/stripe-server' import { prisma } from '@/lib/db' import { verifyToken } from '@/lib/auth' export const runtime = 'nodejs' const checkoutSchema = z.object({ priceId: z.string(), interval: z.enum(['month', 'year']), locale: z.string().default('en') }) export async function POST(request: Request) { try { // Verify authentication const authHeader = request.headers.get('authorization') if (!authHeader?.startsWith('Bearer ')) { return NextResponse.json( { success: false, error: 'Authentication required' }, { status: 401 } ) } const token = authHeader.substring(7) let payload try { payload = await verifyToken(token) } catch (error) { return NextResponse.json( { success: false, error: 'Invalid or expired token' }, { status: 401 } ) } const userId = payload.userId // Get user const user = await prisma.user.findUnique({ where: { id: userId }, select: { email: true, name: true, stripeCustomerId: true, subscriptionTier: true, stripeSubscriptionId: true } }) if (!user) { return NextResponse.json( { success: false, error: 'User not found' }, { status: 404 } ) } // Check if already has active premium subscription if (user.subscriptionTier === 'premium' && user.stripeSubscriptionId) { // Check if subscription is actually active in Stripe try { const subscription = await stripe.subscriptions.retrieve(user.stripeSubscriptionId) if (subscription.status === 'active' || subscription.status === 'trialing') { return NextResponse.json( { success: false, error: 'Already subscribed to Premium', code: 'ALREADY_SUBSCRIBED' }, { status: 400 } ) } } catch (error) { console.log('Subscription not found in Stripe, allowing new subscription') } } const body = await request.json() const { priceId, interval, locale } = checkoutSchema.parse(body) // Validate price ID if (!priceId || priceId === 'price_xxxxxxxxxxxxx') { return NextResponse.json( { success: false, error: 'Invalid price ID. Please configure Stripe price IDs in environment variables.' }, { status: 400 } ) } // Create or retrieve Stripe customer let customerId = user.stripeCustomerId if (!customerId) { const customer = await stripe.customers.create({ email: user.email, name: user.name || undefined, metadata: { userId, source: 'subscription' } }) customerId = customer.id await prisma.user.update({ where: { id: userId }, data: { stripeCustomerId: customerId } }) } // Create checkout session const session = await stripe.checkout.sessions.create({ customer: customerId, mode: 'subscription', payment_method_types: ['card'], line_items: [ { price: priceId, quantity: 1 } ], success_url: `${process.env.NEXTAUTH_URL}/${locale}/subscription/success?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${process.env.NEXTAUTH_URL}/${locale}/subscription`, metadata: { userId, interval }, subscription_data: { metadata: { userId } }, allow_promotion_codes: true, billing_address_collection: 'auto' }) console.log('✅ Stripe checkout session created:', { sessionId: session.id, userId, priceId, interval }) return NextResponse.json({ success: true, sessionId: session.id, url: session.url }) } catch (error) { console.error('Subscription checkout error:', error) if (error instanceof z.ZodError) { return NextResponse.json( { success: false, error: 'Invalid request format', details: error.errors }, { status: 400 } ) } return NextResponse.json( { success: false, error: 'Failed to create checkout session' }, { status: 500 } ) } }