Files
calvana/pledge-now-pay-later/src/app/api/gocardless/create-flow/route.ts

136 lines
4.0 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server"
import prisma from "@/lib/prisma"
import { createRedirectFlow } from "@/lib/gocardless"
import { generateReference } from "@/lib/reference"
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { amountPence, donorName, donorEmail, donorPhone, giftAid, eventId, qrSourceId } = body
if (!prisma) {
return NextResponse.json({ error: "Database not configured" }, { status: 503 })
}
// Get event + org
const event = await prisma.event.findUnique({
where: { id: eventId },
include: { organization: true },
})
if (!event) {
return NextResponse.json({ error: "Event not found" }, { status: 404 })
}
const org = event.organization
// Generate reference
let reference = ""
let attempts = 0
while (attempts < 10) {
reference = generateReference(org.refPrefix || "PNPL", amountPence)
const exists = await prisma.pledge.findUnique({ where: { reference } })
if (!exists) break
attempts++
}
// Create pledge in DB
const pledge = await prisma.pledge.create({
data: {
reference,
amountPence,
currency: "GBP",
rail: "gocardless",
status: "new",
donorName: donorName || null,
donorEmail: donorEmail || null,
donorPhone: donorPhone || null,
giftAid: giftAid || false,
eventId,
qrSourceId: qrSourceId || null,
organizationId: org.id,
},
})
// Create reminder schedule
const { calculateReminderSchedule } = await import("@/lib/reminders")
const schedule = calculateReminderSchedule(new Date())
await prisma.reminder.createMany({
data: schedule.map((s) => ({
pledgeId: pledge.id,
step: s.step,
channel: s.channel,
scheduledAt: s.scheduledAt,
status: "pending",
payload: { templateKey: s.templateKey, subject: s.subject },
})),
})
// Track analytics
await prisma.analyticsEvent.create({
data: {
eventType: "pledge_completed",
pledgeId: pledge.id,
eventId,
qrSourceId: qrSourceId || null,
metadata: { amountPence, rail: "gocardless" },
},
})
// Try real GoCardless flow
// GoCardless live mode requires HTTPS redirect URLs
const baseUrl = process.env.BASE_URL || "http://localhost:3000"
const isHttps = baseUrl.startsWith("https://")
const redirectUrl = `${baseUrl}/api/gocardless/callback?pledge_id=${pledge.id}`
if (!isHttps && process.env.GOCARDLESS_ENVIRONMENT === "live") {
// Can't use GC live with HTTP — return simulated mode
// Set BASE_URL to your HTTPS domain to enable live GoCardless
console.warn("GoCardless live mode requires HTTPS BASE_URL. Falling back to simulated.")
return NextResponse.json({
mode: "simulated",
pledgeId: pledge.id,
reference,
id: pledge.id,
})
}
const flow = await createRedirectFlow({
description: `${event.name}${reference}`,
reference,
pledgeId: pledge.id,
successRedirectUrl: redirectUrl,
})
if (flow) {
// Save the redirect flow ID for completion
await prisma.paymentInstruction.create({
data: {
pledgeId: pledge.id,
bankReference: reference,
bankDetails: {},
gcMandateUrl: flow.redirectUrl,
},
})
return NextResponse.json({
mode: "live",
pledgeId: pledge.id,
reference,
redirectUrl: flow.redirectUrl,
redirectFlowId: flow.redirectFlowId,
})
}
// Fallback: no GoCardless configured — return pledge for simulated flow
return NextResponse.json({
mode: "simulated",
pledgeId: pledge.id,
reference,
id: pledge.id,
})
} catch (error) {
console.error("GoCardless create flow error:", error)
return NextResponse.json({ error: "Internal error" }, { status: 500 })
}
}