import { NextRequest, NextResponse } from "next/server"; import { stripe } from "@/lib/stripe"; import { getPool } from "@/lib/database"; import Stripe from "stripe"; export async function POST(request: NextRequest) { const body = await request.text(); const signature = request.headers.get("stripe-signature"); if (!signature) { return NextResponse.json({ error: "No signature" }, { status: 400 }); } const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; if (!webhookSecret) { console.error("Missing STRIPE_WEBHOOK_SECRET"); return NextResponse.json( { error: "Webhook secret not configured" }, { status: 500 } ); } let event: Stripe.Event; try { event = stripe.webhooks.constructEvent(body, signature, webhookSecret); } catch (err: any) { console.error(`Webhook signature verification failed: ${err.message}`); return NextResponse.json( { error: `Webhook Error: ${err.message}` }, { status: 400 } ); } const pool = getPool(); const client = await pool.connect(); try { // Handle different event types switch (event.type) { case "checkout.session.completed": { const session = event.data.object as Stripe.Checkout.Session; const userId = session.metadata?.userId; const tier = session.metadata?.tier; console.log("Webhook received - userId:", userId, "tier:", tier); if (!userId || !tier) { console.error("Missing user or tier in session metadata"); break; } // Check if subscription exists const existing = await client.query( `SELECT id FROM subscriptions WHERE user_id = $1`, [userId] ); // Normalize tier name const tierName = tier.toUpperCase(); console.log("Processing tier:", tierName); const storageLimit = tierName === "BASIC" ? 5 : tierName === "STANDARD" ? 20 : tierName === "PREMIUM" ? 100 : 5; if (existing.rows.length > 0) { // Update existing subscription await client.query( `UPDATE subscriptions SET status = 'ACTIVE', tier = $1, storage_limit_gb = $2, updated_at = CURRENT_TIMESTAMP WHERE user_id = $3`, [tierName, storageLimit, userId] ); console.log(`Subscription updated for user ${userId}`); } else { // Create new subscription await client.query( `INSERT INTO subscriptions (user_id, tier, status, storage_limit_gb, current_usage_gb) VALUES ($1, $2, 'ACTIVE', $3, 0)`, [userId, tierName, storageLimit] ); console.log(`Subscription created for user ${userId}`); } break; } case "customer.subscription.deleted": case "customer.subscription.updated": { const subscription = event.data.object as Stripe.Subscription; const customerId = subscription.customer as string; // Find user by customer ID and update subscription status const status = subscription.status === "active" ? "ACTIVE" : "INACTIVE"; await client.query( `UPDATE subscriptions SET status = $1, updated_at = CURRENT_TIMESTAMP WHERE stripe_customer_id = $2`, [status, customerId] ); console.log(`Subscription ${event.type} for customer ${customerId}`); break; } default: console.log(`Unhandled event type: ${event.type}`); } return NextResponse.json({ received: true }); } catch (error) { console.error("Error processing webhook:", error); return NextResponse.json( { error: "Webhook processing failed" }, { status: 500 } ); } finally { client.release(); } }