gaurv007's picture
Replace all clauseguard.com URLs with clauseguardweb.netlify.app
d219561 verified
import { NextRequest, NextResponse } from "next/server";
import Razorpay from "razorpay";
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
let resend: any = null;
if (process.env.RESEND_API_KEY) {
import("resend").then(({ Resend }) => { resend = new Resend(process.env.RESEND_API_KEY); });
}
export async function POST(req: NextRequest) {
const rawBody = await req.text();
const signature = req.headers.get("x-razorpay-signature") || "";
const webhookSecret = process.env.RAZORPAY_WEBHOOK_SECRET!;
// Verify signature
const isValid = Razorpay.validateWebhookSignature(rawBody, signature, webhookSecret);
if (!isValid) {
return NextResponse.json({ error: "Invalid signature" }, { status: 400 });
}
const event = JSON.parse(rawBody);
const eventType: string = event.event;
switch (eventType) {
case "subscription.activated": {
const sub = event.payload.subscription.entity;
const plan = sub.notes?.plan || "pro";
const userId = sub.notes?.user_id;
if (userId) {
const { data } = await supabase
.from("profiles")
.update({
plan,
razorpay_subscription_id: sub.id,
updated_at: new Date().toISOString(),
})
.eq("id", userId)
.select("email")
.single();
// Send welcome email
if (data?.email && resend) {
await resend.emails.send({
from: "ClauseGuard <noreply@clauseguardweb.netlify.app>",
to: [data.email],
subject: `Welcome to ClauseGuard ${plan.charAt(0).toUpperCase() + plan.slice(1)}`,
html: `<p>Your ${plan} subscription is active. You now have unlimited scans.</p><p><a href="https://clauseguardweb.netlify.app/dashboard-pages/dashboard">Go to dashboard</a></p>`,
});
}
}
break;
}
case "subscription.charged": {
// Recurring payment succeeded — nothing to update, plan already active
break;
}
case "subscription.cancelled":
case "subscription.completed": {
const sub = event.payload.subscription.entity;
const userId = sub.notes?.user_id;
if (userId) {
await supabase
.from("profiles")
.update({
plan: "free",
razorpay_subscription_id: null,
updated_at: new Date().toISOString(),
})
.eq("id", userId);
}
break;
}
case "subscription.halted": {
const sub = event.payload.subscription.entity;
const userId = sub.notes?.user_id;
if (userId) {
const { data } = await supabase
.from("profiles")
.select("email")
.eq("id", userId)
.single();
if (data?.email && resend) {
await resend.emails.send({
from: "ClauseGuard <noreply@clauseguardweb.netlify.app>",
to: [data.email],
subject: "Payment failed — subscription paused",
html: "<p>Your payment failed and your subscription has been paused. Please update your payment method to continue.</p>",
});
}
}
break;
}
case "payment.failed": {
// Razorpay auto-retries for subscriptions — log for monitoring
const payment = event.payload.payment.entity;
console.warn("Payment failed:", payment.id, payment.error_description);
break;
}
}
return NextResponse.json({ status: "ok" });
}