88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { activateProPlan } from "@/lib/billing";
|
|
import { PRO_PRICE_CENTS } from "@/lib/credits";
|
|
import { prisma } from "@/lib/db";
|
|
import { getSessionUser } from "@/lib/session";
|
|
import {
|
|
checkoutTaxAndReferenceOptions,
|
|
ensureStripeCustomer,
|
|
priceDataTaxFields,
|
|
productDataWithTaxCode,
|
|
} from "@/lib/stripe-checkout";
|
|
import { getStripe, isBillingDevMock, isStripeConfigured } from "@/lib/stripe";
|
|
|
|
/** Start Pro subscription Checkout (€5/mo) or mock-upgrade in development. */
|
|
export async function POST(req: NextRequest) {
|
|
const user = await getSessionUser();
|
|
if (!user) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
if (user.plan === "PREMIUM") {
|
|
return NextResponse.json({ error: "Already on Pro." }, { status: 400 });
|
|
}
|
|
|
|
const dbUser = await prisma.user.findUniqueOrThrow({
|
|
where: { id: user.id },
|
|
select: { email: true, stripeCustomerId: true },
|
|
});
|
|
|
|
if (isBillingDevMock()) {
|
|
await activateProPlan(user.id, {
|
|
stripeCustomerId: dbUser.stripeCustomerId,
|
|
stripeSubscriptionId: `dev_sub_${Date.now()}`,
|
|
cardLast4: "4242",
|
|
});
|
|
return NextResponse.json({ mocked: true, plan: "PREMIUM" });
|
|
}
|
|
|
|
if (!isStripeConfigured()) {
|
|
return NextResponse.json(
|
|
{ error: "Payments are not configured yet. Set STRIPE_SECRET_KEY." },
|
|
{ status: 503 },
|
|
);
|
|
}
|
|
|
|
const origin = process.env.NEXTAUTH_URL || req.nextUrl.origin;
|
|
const stripe = getStripe();
|
|
const customerId = await ensureStripeCustomer(user.id, dbUser.email);
|
|
const priceId = process.env.STRIPE_PRO_PRICE_ID;
|
|
|
|
const session = await stripe.checkout.sessions.create({
|
|
mode: "subscription",
|
|
customer: customerId,
|
|
line_items: priceId
|
|
? [{ price: priceId, quantity: 1 }]
|
|
: [
|
|
{
|
|
quantity: 1,
|
|
price_data: {
|
|
currency: "eur",
|
|
unit_amount: PRO_PRICE_CENTS,
|
|
recurring: { interval: "month" },
|
|
...priceDataTaxFields(),
|
|
product_data: productDataWithTaxCode(
|
|
"Songs2VID Pro",
|
|
"50 video credits / month · 1080p · API access · Includes Custom Branding, Watermark Positioning, and Bulk Image Matching",
|
|
),
|
|
},
|
|
},
|
|
],
|
|
metadata: {
|
|
type: "pro_subscription",
|
|
userId: user.id,
|
|
},
|
|
subscription_data: {
|
|
metadata: {
|
|
type: "pro_subscription",
|
|
userId: user.id,
|
|
},
|
|
},
|
|
...checkoutTaxAndReferenceOptions(user.id),
|
|
success_url: `${origin}/dashboard/settings?upgrade=success`,
|
|
cancel_url: `${origin}/dashboard/settings?upgrade=cancelled`,
|
|
});
|
|
|
|
return NextResponse.json({ url: session.url, sessionId: session.id });
|
|
}
|