import { NextRequest, NextResponse } from "next/server"; import { headers } from "next/headers"; import Stripe from "stripe"; import { getStripe, getStripeWebhookSecret } from "@/src/lib/stripe"; import { prisma } from "@/src/lib/prisma"; export const dynamic = "force-dynamic"; export async function POST(request: NextRequest) { const payload = await request.text(); const headerPayload = await headers(); const signature = headerPayload.get("stripe-signature") || ""; // Determine which Stripe account this webhook belongs to // Stripe sends the account ID in the Stripe-Account header for Connect const accountId = headerPayload.get("stripe-account") || ""; let houseId: string; if (process.env.STRIPE_ACCOUNT_HERDWEWEG && accountId === process.env.STRIPE_ACCOUNT_HERDWEWEG) { houseId = "herdweg"; } else if (process.env.STRIPE_ACCOUNT_SCHOENAICHER && accountId === process.env.STRIPE_ACCOUNT_SCHOENAICHER) { houseId = "schoenaicher"; } else { // If no account header, try to infer from event metadata (not available in signature verification) // For now, we'll try both secrets. In production, use separate webhook endpoints or account headers. return NextResponse.json( { error: "Could not determine Stripe account" }, { status: 400 } ); } try { const stripe = getStripe(houseId); const webhookSecret = getStripeWebhookSecret(houseId); const event = stripe.webhooks.constructEvent(payload, signature, webhookSecret); // Deduplicate events const existingEvent = await prisma.stripeEvent.findUnique({ where: { eventId: event.id }, }); if (existingEvent) { return NextResponse.json({ received: true }); } await prisma.stripeEvent.create({ data: { eventId: event.id, accountId, type: event.type, payload: JSON.stringify(event), }, }); if (event.type === "checkout.session.completed") { const session = event.data.object as Stripe.Checkout.Session; const bookingReference = session.metadata?.bookingReference; if (bookingReference) { await prisma.booking.update({ where: { bookingReference }, data: { status: "deposit_paid", stripePaymentIntentId: session.payment_intent as string, }, }); // TODO: Trigger n8n workflow to create booking in Beds24 console.log(`Deposit paid for booking ${bookingReference}`); } } return NextResponse.json({ received: true }); } catch (error) { console.error("Stripe webhook error:", error); return NextResponse.json( { error: "Webhook verification failed" }, { status: 400 } ); } }