Files
Lageplan/src/app/api/donate/webhook/route.ts

71 lines
2.3 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getStripe, getStripeConfig } from '@/lib/stripe'
import { prisma } from '@/lib/db'
export const dynamic = 'force-dynamic'
export async function POST(req: NextRequest) {
try {
const stripe = await getStripe()
const config = await getStripeConfig()
if (!stripe || !config) {
return NextResponse.json({ error: 'Stripe not configured' }, { status: 503 })
}
const body = await req.text()
const sig = req.headers.get('stripe-signature')
if (!sig) {
return NextResponse.json({ error: 'Missing signature' }, { status: 400 })
}
let event
try {
if (config.webhookSecret) {
event = stripe.webhooks.constructEvent(body, sig, config.webhookSecret)
} else {
// No webhook secret configured — parse event directly (not recommended for production)
event = JSON.parse(body)
}
} catch (err) {
console.error('Webhook signature verification failed:', err)
return NextResponse.json({ error: 'Invalid signature' }, { status: 400 })
}
if (event.type === 'checkout.session.completed') {
const session = event.data.object
const metadata = session.metadata || {}
if (metadata.type === 'donation') {
// Store donation record
try {
await (prisma as any).systemSetting.create({
data: {
key: `donation_${Date.now()}`,
value: JSON.stringify({
amount: (session.amount_total || 0) / 100,
currency: session.currency,
donor: metadata.donor_name || 'Anonym',
message: metadata.donor_message || '',
paymentId: session.payment_intent,
date: new Date().toISOString(),
}),
isSecret: false,
category: 'donations',
},
})
} catch (e) {
console.error('Failed to store donation record:', e)
}
console.log(`[Donation] CHF ${(session.amount_total || 0) / 100} from ${metadata.donor_name || 'Anonym'}`)
}
}
return NextResponse.json({ received: true })
} catch (error) {
console.error('Webhook error:', error)
return NextResponse.json({ error: 'Webhook processing failed' }, { status: 500 })
}
}