← 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 });
  }
}