import Stripe from 'stripe'; import { NextResponse } from 'next/server'; import { Timestamp } from 'firebase/firestore'; import { createCreditTransaction, createPurchase, getUser, updateUserCredits, } from '@/lib/firestore'; const stripeSecretKey = process.env.STRIPE_SECRET_KEY; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; const stripe = stripeSecretKey ? new Stripe(stripeSecretKey, { apiVersion: '2024-06-20' }) : null; export async function POST(request: Request) { if (!stripe || !webhookSecret) { return NextResponse.json({ error: 'Stripe webhook not configured.' }, { status: 500 }); } const signature = request.headers.get('stripe-signature'); if (!signature) { return NextResponse.json({ error: 'Missing Stripe signature.' }, { status: 400 }); } const payload = await request.text(); let event: Stripe.Event; try { event = stripe.webhooks.constructEvent(payload, signature, webhookSecret); } catch (error) { console.error('Stripe webhook signature error:', error); return NextResponse.json({ error: 'Invalid signature.' }, { status: 400 }); } if (event.type === 'checkout.session.completed') { const session = event.data.object as Stripe.Checkout.Session; const metadata = session.metadata ?? {}; const userId = metadata.userId; const credits = Number(metadata.credits); const amount = Number(metadata.amount); if (!userId || !Number.isFinite(credits) || credits <= 0) { return NextResponse.json({ error: 'Invalid checkout metadata.' }, { status: 400 }); } const user = await getUser(userId); if (!user) { return NextResponse.json({ error: 'User not found.' }, { status: 404 }); } const newBalance = user.creditBalance + credits; await updateUserCredits(userId, newBalance); await createCreditTransaction({ userId, amount: credits, type: 'purchase', balanceAfter: newBalance, createdAt: Timestamp.now(), }); await createPurchase({ userId, credits, amount: Number.isFinite(amount) ? amount : credits, currency: session.currency ?? 'eur', stripeSessionId: session.id, createdAt: Timestamp.now(), }); } return NextResponse.json({ received: true }); }