Files
falah-mobile/src/app/api/wallet/top-up/create-checkout/route.ts
T

110 lines
3.4 KiB
TypeScript
Raw Normal View History

import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireAuth } from "@/lib/auth";
const TOP_UP_AMOUNTS = {
500: { usd: 0.99, bonus: 0, priceEnv: "POLAR_FLH_500" },
1000: { usd: 0.99, bonus: 0, priceEnv: "POLAR_FLH_1000" },
5000: { usd: 4.99, bonus: 500, priceEnv: "POLAR_FLH_5000" },
10000: { usd: 9.99, bonus: 2000, priceEnv: "POLAR_FLH_10000" },
50000: { usd: 49.99, bonus: 15000, priceEnv: "POLAR_FLH_50000" },
} as const;
export async function POST(req: NextRequest) {
const jwtPayload = await requireAuth(req);
if (!jwtPayload) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const body = await req.json();
const { amount } = body;
if (!amount || !(amount in TOP_UP_AMOUNTS)) {
return NextResponse.json(
{ error: "Invalid amount. Choose 500, 1000, 5000, 10000, or 50000 FLH." },
{ status: 400 }
);
}
const pricing = TOP_UP_AMOUNTS[amount as keyof typeof TOP_UP_AMOUNTS];
const totalFlh = amount + (pricing.bonus || 0);
// Mock mode: use when POLAR_ACCESS_TOKEN is not configured
if (!process.env.POLAR_ACCESS_TOKEN) {
await prisma.user.update({
where: { id: jwtPayload.userId },
data: { flhBalance: { increment: totalFlh } },
});
return NextResponse.json({
success: true,
url: "/wallet?topup=success",
mock: true,
amount,
bonus: pricing.bonus || 0,
amountUsd: pricing.usd,
});
}
// Production — Polar.sh checkout session
const productPriceId = process.env[pricing.priceEnv];
if (!productPriceId) {
return NextResponse.json(
{ error: `Polar price not configured for ${amount} FLH. Set ${pricing.priceEnv} env var.` },
{ status: 500 }
);
}
const origin = req.headers.get("origin") || req.headers.get("host") || "";
const baseUrl = origin.startsWith("http") ? origin : `https://${origin}`;
const polarResponse = await fetch("https://api.polar.sh/v1/checkouts/", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POLAR_ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
product_price_id: productPriceId,
success_url: `${baseUrl}/wallet?topup=success&amount=${amount}`,
customer_email: jwtPayload.email,
return_url: `${baseUrl}/wallet`,
metadata: {
type: "flh_purchase",
flh_amount: totalFlh,
user_id: jwtPayload.userId,
user_email: jwtPayload.email,
},
allow_trial: false,
}),
});
if (!polarResponse.ok) {
const errorBody = await polarResponse.text();
console.error("Polar API error:", polarResponse.status, errorBody);
return NextResponse.json(
{ error: `Checkout creation failed (HTTP ${polarResponse.status})` },
{ status: 502 }
);
}
const polarData = await polarResponse.json();
return NextResponse.json({
success: true,
url: polarData.url,
checkout_id: polarData.id,
amount,
amountUsd: pricing.usd,
bonus: pricing.bonus || 0,
});
} catch (error) {
console.error("Top-up checkout error:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Failed to create checkout" },
{ status: 500 }
);
}
}