You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
3.3 KiB
124 lines
3.3 KiB
|
7 months ago
|
import { NextRequest, NextResponse } from "next/server";
|
||
|
|
import { stripe } from "@/lib/stripe";
|
||
|
|
import { formatAmountForStripe } from "@/lib/stripe";
|
||
|
|
import { getPool } from "@/lib/database";
|
||
|
|
|
||
|
|
// Define pricing tiers
|
||
|
|
const PRICING_TIERS = {
|
||
|
|
basic: {
|
||
|
|
name: "Basic",
|
||
|
|
amount: 9.99,
|
||
|
|
storageLimit: 5,
|
||
|
|
},
|
||
|
|
standard: {
|
||
|
|
name: "Standard",
|
||
|
|
amount: 19.99,
|
||
|
|
storageLimit: 20,
|
||
|
|
},
|
||
|
|
premium: {
|
||
|
|
name: "Premium",
|
||
|
|
amount: 39.99,
|
||
|
|
storageLimit: 100,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
export async function POST(request: NextRequest) {
|
||
|
|
try {
|
||
|
|
// Check if Stripe is configured
|
||
|
|
if (!process.env.STRIPE_SECRET_KEY) {
|
||
|
|
console.error("Stripe secret key is not configured");
|
||
|
|
return NextResponse.json(
|
||
|
|
{
|
||
|
|
error:
|
||
|
|
"Stripe is not configured. Please add STRIPE_SECRET_KEY to your environment variables.",
|
||
|
|
},
|
||
|
|
{ status: 500 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const { tier, userId } = await request.json();
|
||
|
|
|
||
|
|
// Validate tier
|
||
|
|
const selectedTier = PRICING_TIERS[tier as keyof typeof PRICING_TIERS];
|
||
|
|
if (!selectedTier) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: "Invalid tier selected" },
|
||
|
|
{ status: 400 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate user
|
||
|
|
if (!userId) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: "User ID is required" },
|
||
|
|
{ status: 400 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if user already has an active subscription
|
||
|
|
const pool = getPool();
|
||
|
|
const client = await pool.connect();
|
||
|
|
|
||
|
|
try {
|
||
|
|
const existingSub = await client.query(
|
||
|
|
`SELECT id, status FROM subscriptions WHERE user_id = $1 AND status = 'ACTIVE'`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
|
||
|
|
if (existingSub.rows.length > 0) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{
|
||
|
|
error:
|
||
|
|
"You already have an active subscription. Please cancel your current subscription before purchasing a new one.",
|
||
|
|
},
|
||
|
|
{ status: 400 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
} catch (dbError) {
|
||
|
|
console.error("Database error checking existing subscription:", dbError);
|
||
|
|
// Continue with payment creation even if check fails
|
||
|
|
} finally {
|
||
|
|
client.release();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the base URL
|
||
|
|
const origin = request.headers.get("origin") || "http://localhost:3000";
|
||
|
|
|
||
|
|
// Create checkout session
|
||
|
|
const session = await stripe.checkout.sessions.create({
|
||
|
|
mode: "subscription",
|
||
|
|
payment_method_types: ["card"],
|
||
|
|
line_items: [
|
||
|
|
{
|
||
|
|
price_data: {
|
||
|
|
currency: "usd",
|
||
|
|
product_data: {
|
||
|
|
name: selectedTier.name,
|
||
|
|
description: `${selectedTier.storageLimit}GB storage limit`,
|
||
|
|
},
|
||
|
|
unit_amount: formatAmountForStripe(selectedTier.amount),
|
||
|
|
recurring: {
|
||
|
|
interval: "month",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
quantity: 1,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
success_url: `${origin}/?success=true&session_id={CHECKOUT_SESSION_ID}`,
|
||
|
|
cancel_url: `${origin}/?canceled=true`,
|
||
|
|
metadata: {
|
||
|
|
userId: userId,
|
||
|
|
tier: tier,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
return NextResponse.json({ sessionId: session.id, url: session.url });
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("Error creating checkout session:", error);
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: error.message || "Failed to create checkout session" },
|
||
|
|
{ status: 500 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|