66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { type NextRequest, NextResponse } from "next/server";
|
|
import { auth } from "@/app/(auth)/auth";
|
|
import {
|
|
createStripeBillingPortalSession,
|
|
findStripeCustomerIdByEmail,
|
|
StripeRequestError,
|
|
} from "@/lib/billing/stripe";
|
|
|
|
function getBaseUrl(request: NextRequest) {
|
|
return (
|
|
process.env.AUTH_URL ??
|
|
`${request.nextUrl.protocol}//${request.headers.get("host") ?? request.nextUrl.host}`
|
|
);
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const session = await auth();
|
|
|
|
if (!session?.user?.id || !session.user.email) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
if (session.user.type === "guest") {
|
|
return NextResponse.json({ error: "Guest user cannot manage subscription" }, { status: 403 });
|
|
}
|
|
|
|
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
|
|
|
|
if (!stripeSecretKey) {
|
|
return NextResponse.json({ error: "Stripe is not configured" }, { status: 503 });
|
|
}
|
|
|
|
const customerId = await findStripeCustomerIdByEmail({
|
|
secretKey: stripeSecretKey,
|
|
email: session.user.email,
|
|
});
|
|
|
|
if (!customerId) {
|
|
return NextResponse.json({ error: "No Stripe subscription account found" }, { status: 404 });
|
|
}
|
|
|
|
const returnUrl = process.env.STRIPE_BILLING_RETURN_URL
|
|
? process.env.STRIPE_BILLING_RETURN_URL
|
|
: new URL("/billing", getBaseUrl(request)).toString();
|
|
|
|
const portalSession = await createStripeBillingPortalSession({
|
|
secretKey: stripeSecretKey,
|
|
customerId,
|
|
returnUrl,
|
|
});
|
|
|
|
return NextResponse.json({
|
|
id: portalSession.id,
|
|
url: portalSession.url,
|
|
});
|
|
} catch (error) {
|
|
if (error instanceof StripeRequestError) {
|
|
return NextResponse.json({ error: error.message }, { status: error.status });
|
|
}
|
|
|
|
console.error("[Billing Portal API] Error:", error);
|
|
return NextResponse.json({ error: "Failed to create billing portal session" }, { status: 500 });
|
|
}
|
|
}
|