import { NextRequest, NextResponse } from 'next/server' import { stripe } from '@/lib/stripe-server' import { prisma } from '@/lib/db' import Stripe from 'stripe' export async function POST(req: NextRequest) { const body = await req.text() const signature = req.headers.get('stripe-signature') if (!signature) { console.error('No stripe signature found') return NextResponse.json({ error: 'No signature' }, { status: 400 }) } let event: Stripe.Event try { // Verify webhook signature event = stripe.webhooks.constructEvent( body, signature, process.env.STRIPE_WEBHOOK_SECRET! ) } catch (err) { console.error('Webhook signature verification failed:', err) return NextResponse.json( { error: 'Webhook signature verification failed' }, { status: 400 } ) } // Handle the event try { switch (event.type) { case 'checkout.session.completed': { const session = event.data.object as Stripe.Checkout.Session // Update donation status to COMPLETED await prisma.donation.update({ where: { stripeSessionId: session.id }, data: { status: 'COMPLETED', stripePaymentId: session.payment_intent as string, metadata: { paymentStatus: session.payment_status, customerEmail: session.customer_email, }, }, }) console.log(`Donation completed for session: ${session.id}`) break } case 'checkout.session.expired': { const session = event.data.object as Stripe.Checkout.Session // Update donation status to CANCELLED await prisma.donation.update({ where: { stripeSessionId: session.id }, data: { status: 'CANCELLED', }, }) console.log(`Donation cancelled for session: ${session.id}`) break } case 'payment_intent.payment_failed': { const paymentIntent = event.data.object as Stripe.PaymentIntent // Update donation status to FAILED const donation = await prisma.donation.findFirst({ where: { stripePaymentId: paymentIntent.id }, }) if (donation) { await prisma.donation.update({ where: { id: donation.id }, data: { status: 'FAILED', metadata: { error: paymentIntent.last_payment_error?.message, }, }, }) } console.log(`Payment failed for intent: ${paymentIntent.id}`) break } case 'charge.refunded': { const charge = event.data.object as Stripe.Charge // Update donation status to REFUNDED const donation = await prisma.donation.findFirst({ where: { stripePaymentId: charge.payment_intent as string }, }) if (donation) { await prisma.donation.update({ where: { id: donation.id }, data: { status: 'REFUNDED', metadata: { refundReason: charge.refunds?.data[0]?.reason, }, }, }) } console.log(`Donation refunded for charge: ${charge.id}`) break } default: console.log(`Unhandled event type: ${event.type}`) } return NextResponse.json({ received: true }) } catch (error) { console.error('Error processing webhook:', error) return NextResponse.json( { error: 'Webhook processing failed' }, { status: 500 } ) } }