crypto-commons-gather.ing-w.../app/api/webhook/route.ts

72 lines
2.2 KiB
TypeScript

import { type NextRequest, NextResponse } from "next/server"
import Stripe from "stripe"
// Lazy initialization to avoid build-time errors when env vars aren't set
let stripeInstance: Stripe | null = null
function getStripe(): Stripe {
if (!stripeInstance) {
if (!process.env.STRIPE_SECRET_KEY) {
throw new Error("STRIPE_SECRET_KEY is not configured")
}
stripeInstance = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: "2024-12-18.acacia",
})
}
return stripeInstance
}
function getWebhookSecret(): string {
if (!process.env.STRIPE_WEBHOOK_SECRET) {
throw new Error("STRIPE_WEBHOOK_SECRET is not configured")
}
return process.env.STRIPE_WEBHOOK_SECRET
}
export async function POST(request: NextRequest) {
try {
const body = await request.text()
const signature = request.headers.get("stripe-signature")!
let event: Stripe.Event
try {
event = getStripe().webhooks.constructEvent(body, signature, getWebhookSecret())
} catch (err) {
console.error("[v0] Webhook signature verification failed:", err)
return NextResponse.json({ error: "Invalid signature" }, { status: 400 })
}
// Handle the event
switch (event.type) {
case "checkout.session.completed": {
const session = event.data.object as Stripe.Checkout.Session
console.log("[v0] Payment successful:", session.id)
// Here you would:
// 1. Store the registration in your database
// 2. Send confirmation email
// 3. Add to attendee list
break
}
case "payment_intent.succeeded": {
const paymentIntent = event.data.object as Stripe.PaymentIntent
console.log("[v0] PaymentIntent successful:", paymentIntent.id)
break
}
case "payment_intent.payment_failed": {
const paymentIntent = event.data.object as Stripe.PaymentIntent
console.error("[v0] Payment failed:", paymentIntent.id)
break
}
default:
console.log("[v0] Unhandled event type:", event.type)
}
return NextResponse.json({ received: true })
} catch (err) {
console.error("[v0] Webhook error:", err)
return NextResponse.json({ error: "Webhook error" }, { status: 500 })
}
}