Files
gridpilot.gg/apps/website/app/api/payments/route.ts
2025-12-10 12:38:55 +01:00

141 lines
3.6 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
// Alpha: In-memory payment storage (mock payment gateway)
const payments: Map<string, {
id: string;
type: 'sponsorship' | 'membership_fee';
amount: number;
platformFee: number;
netAmount: number;
payerId: string;
payerType: 'sponsor' | 'driver';
leagueId: string;
seasonId?: string;
status: 'pending' | 'completed' | 'failed' | 'refunded';
createdAt: Date;
completedAt?: Date;
}> = new Map();
const PLATFORM_FEE_RATE = 0.10;
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const leagueId = searchParams.get('leagueId');
const payerId = searchParams.get('payerId');
const type = searchParams.get('type');
let results = Array.from(payments.values());
if (leagueId) {
results = results.filter(p => p.leagueId === leagueId);
}
if (payerId) {
results = results.filter(p => p.payerId === payerId);
}
if (type) {
results = results.filter(p => p.type === type);
}
return NextResponse.json({ payments: results });
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { type, amount, payerId, payerType, leagueId, seasonId } = body;
if (!type || !amount || !payerId || !payerType || !leagueId) {
return NextResponse.json(
{ error: 'Missing required fields: type, amount, payerId, payerType, leagueId' },
{ status: 400 }
);
}
if (!['sponsorship', 'membership_fee'].includes(type)) {
return NextResponse.json(
{ error: 'Type must be "sponsorship" or "membership_fee"' },
{ status: 400 }
);
}
if (!['sponsor', 'driver'].includes(payerType)) {
return NextResponse.json(
{ error: 'PayerType must be "sponsor" or "driver"' },
{ status: 400 }
);
}
const platformFee = amount * PLATFORM_FEE_RATE;
const netAmount = amount - platformFee;
const id = `payment-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const payment = {
id,
type,
amount,
platformFee,
netAmount,
payerId,
payerType,
leagueId,
seasonId: seasonId || undefined,
status: 'pending' as const,
createdAt: new Date(),
};
payments.set(id, payment);
return NextResponse.json({ payment }, { status: 201 });
} catch (err) {
console.error('Payment creation failed:', err);
return NextResponse.json(
{ error: 'Failed to create payment' },
{ status: 500 }
);
}
}
// Complete a payment (mock payment gateway callback)
export async function PATCH(request: NextRequest) {
try {
const body = await request.json();
const { paymentId, status } = body;
if (!paymentId || !status) {
return NextResponse.json(
{ error: 'Missing required fields: paymentId, status' },
{ status: 400 }
);
}
if (!['completed', 'failed', 'refunded'].includes(status)) {
return NextResponse.json(
{ error: 'Status must be "completed", "failed", or "refunded"' },
{ status: 400 }
);
}
const payment = payments.get(paymentId);
if (!payment) {
return NextResponse.json(
{ error: 'Payment not found' },
{ status: 404 }
);
}
payment.status = status;
if (status === 'completed') {
payment.completedAt = new Date();
}
payments.set(paymentId, payment);
return NextResponse.json({ payment });
} catch (err) {
console.error('Payment update failed:', err);
return NextResponse.json(
{ error: 'Failed to update payment' },
{ status: 500 }
);
}
}