← back to Trademarks Copyright
src/app/api/drops/checkout/route.ts
50 lines
import { NextRequest, NextResponse } from "next/server";
import { query } from "@/lib/db";
import { createCheckoutSession, stripeEnabled, TIERS, type TierId } from "@/lib/stripe";
export async function POST(req: NextRequest) {
const body = await req.json().catch(() => ({}));
if (!body || typeof body !== "object" || Array.isArray(body)) {
return NextResponse.json({ error: "json object body required" }, { status: 400 });
}
const email = String(body.email || "").trim().toLowerCase();
const tier = String(body.tier || "standard") as TierId;
if (!TIERS[tier]) return NextResponse.json({ error: "invalid tier" }, { status: 400 });
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
return NextResponse.json({ error: "valid email required" }, { status: 400 });
}
const { rows } = await query<{ id: number; token: string }>(
`SELECT id, token FROM subscribers WHERE email = $1`, [email]
);
if (!rows.length) return NextResponse.json({ error: "sign up for the trial first" }, { status: 404 });
const sub = rows[0];
const origin = req.nextUrl.origin;
if (!stripeEnabled()) {
// Dev fallback — mark the subscriber as "comp" immediately so we can test end-to-end.
await query(`UPDATE subscribers SET tier = $1 WHERE id = $2`, [tier, sub.id]);
return NextResponse.json({
ok: true,
mock: true,
message: `Stripe not configured — subscriber set to tier=${tier} directly for testing.`,
next: `${origin}/drops/view/${sub.token}`,
});
}
try {
const session = await createCheckoutSession({
email,
tier,
successUrl: `${origin}/drops/view/${sub.token}?upgraded=${tier}`,
cancelUrl: `${origin}/drops?cancelled=1`,
subscriberToken: sub.token,
});
return NextResponse.json({ ok: true, url: session.url });
} catch (e) {
return NextResponse.json({ error: (e as Error).message }, { status: 500 });
}
}