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.

125 lines
3.8 KiB

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