crypto-commons-gather.ing-w.../app/api/create-checkout-session/route.ts

96 lines
3.6 KiB
TypeScript

import { type NextRequest, NextResponse } from "next/server"
import createMollieClient from "@mollie/api-client"
// Lazy initialization to avoid build-time errors
let mollieClient: ReturnType<typeof createMollieClient> | null = null
function getMollie() {
if (!mollieClient) {
mollieClient = createMollieClient({ apiKey: process.env.MOLLIE_API_KEY! })
}
return mollieClient
}
// Dynamic pricing configuration (in EUR)
const TICKET_PRICE = 80 // €80 early bird
// Accommodation prices per person for 7 nights
const ACCOMMODATION_PRICES: Record<string, { label: string; price: number }> = {
"ch-multi": { label: "Bed in shared room (Commons Hub)", price: 279.30 },
"ch-double": { label: "Bed in double room (Commons Hub)", price: 356.30 },
"hh-single": { label: "Single room (Herrnhof)", price: 665 },
"hh-double-separate": { label: "Double room, separate beds (Herrnhof)", price: 420 },
"hh-double-shared": { label: "Double room, shared double bed (Herrnhof)", price: 350 },
"hh-triple": { label: "Triple room (Herrnhof)", price: 350 },
"hh-daybed": { label: "Daybed or extra bed in living room (Herrnhof)", price: 280 },
}
// Public base URL
const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "https://cryptocommonsgather.ing"
export async function POST(request: NextRequest) {
try {
const formData = await request.formData()
const registrationDataStr = formData.get("registrationData") as string
const includeAccommodation = formData.get("includeAccommodation") === "true"
const accommodationType = (formData.get("accommodationType") as string) || "ch-multi"
const registrationData = registrationDataStr ? JSON.parse(registrationDataStr) : null
// Calculate total
let total = TICKET_PRICE
const descriptionParts = ["CCG 2026 Ticket (€80)"]
if (includeAccommodation) {
const accom = ACCOMMODATION_PRICES[accommodationType]
if (accom) {
total += accom.price
descriptionParts.push(`${accom.label} (€${accom.price.toFixed(2)})`)
}
}
// Build metadata for webhook
const metadata: Record<string, string> = {}
if (registrationData) {
metadata.name = registrationData.name || ""
metadata.email = registrationData.email || ""
metadata.contact = registrationData.contact || ""
metadata.contributions = (registrationData.contributions || "").substring(0, 500)
metadata.expectations = (registrationData.expectations || "").substring(0, 500)
metadata.howHeard = registrationData.howHeard || ""
metadata.dietary =
(registrationData.dietary || []).join(", ") +
(registrationData.dietaryOther ? `, ${registrationData.dietaryOther}` : "")
metadata.crewConsent = registrationData.crewConsent || ""
metadata.accommodation = includeAccommodation ? accommodationType : "none"
}
const payment = await getMollie().payments.create({
amount: {
value: total.toFixed(2),
currency: "EUR",
},
description: `CCG 2026 Registration — ${descriptionParts.join(" + ")}`,
redirectUrl: `${BASE_URL}/success`,
webhookUrl: `${BASE_URL}/api/webhook`,
metadata,
})
// Redirect to Mollie checkout
return new Response(null, {
status: 303,
headers: { Location: payment.getCheckoutUrl()! },
})
} catch (err) {
console.error("Error creating Mollie payment:", err)
return NextResponse.json({ error: "Error creating payment" }, { status: 500 })
}
}
export async function GET() {
return NextResponse.json(
{ message: "This is an API endpoint. Use POST to create a checkout session." },
{ status: 405 },
)
}