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

98 lines
3.3 KiB
TypeScript

import { type NextRequest, NextResponse } from "next/server"
import Stripe from "stripe"
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-12-18.acacia",
})
// Dynamic pricing configuration (in EUR cents)
const TICKET_PRICE_CENTS = 8000 // €80 early bird
// Public base URL (needed because request.nextUrl.origin returns internal Docker address)
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 paymentMethod = formData.get("paymentMethod") as string
const registrationDataStr = formData.get("registrationData") as string
const registrationData = registrationDataStr ? JSON.parse(registrationDataStr) : null
// Use price_data for dynamic pricing (no pre-created prices needed)
const lineItems: Stripe.Checkout.SessionCreateParams.LineItem[] = [
{
price_data: {
currency: "eur",
product_data: {
name: "CCG 2026 Ticket",
description: "Crypto Commons Gathering 2026 - August 16-22, Austria",
},
unit_amount: TICKET_PRICE_CENTS,
},
quantity: 1,
},
]
let paymentMethodTypes: Stripe.Checkout.SessionCreateParams.PaymentMethodType[] = ["card"]
if (paymentMethod === "sepa_debit") {
paymentMethodTypes = ["sepa_debit"]
} else if (paymentMethod === "crypto") {
paymentMethodTypes = ["customer_balance"]
}
const session = await stripe.checkout.sessions.create({
payment_method_types: paymentMethodTypes,
line_items: lineItems,
mode: "payment",
success_url: `${BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${BASE_URL}/register`,
metadata: registrationData
? {
name: registrationData.name,
contact: registrationData.contact,
contributions: registrationData.contributions.substring(0, 500),
expectations: registrationData.expectations.substring(0, 500),
howHeard: registrationData.howHeard || "",
dietary:
registrationData.dietary.join(", ") +
(registrationData.dietaryOther ? `, ${registrationData.dietaryOther}` : ""),
crewConsent: registrationData.crewConsent,
}
: {},
...(paymentMethod === "crypto" && {
payment_method_options: {
customer_balance: {
funding_type: "bank_transfer",
bank_transfer: {
type: "us_bank_account",
},
},
},
}),
allow_promotion_codes: true,
billing_address_collection: "required",
phone_number_collection: {
enabled: true,
},
})
// Use 303 redirect for POST requests (tells browser to follow with GET)
return new Response(null, {
status: 303,
headers: { Location: session.url! },
})
} catch (err) {
console.error("Error creating checkout session:", err)
return NextResponse.json({ error: "Error creating checkout session" }, { status: 500 })
}
}
export async function GET() {
return NextResponse.json(
{ message: "This is an API endpoint. Use POST to create a checkout session." },
{ status: 405 },
)
}