11import { NextResponse } from "next/server" ;
2- import Stripe from "stripe " ;
2+ import crypto from "crypto " ;
33import { Resend } from "resend" ;
44
5-
65export async function POST ( req : Request ) {
7- const stripe = new Stripe ( process . env . STRIPE_SECRET_KEY || "dummy_key" , {
8- apiVersion : "2026-02-25.clover" , // Adjust to the version you are using
9- } ) ;
6+ try {
7+ const body = await req . text ( ) ;
8+ const signature = req . headers . get ( "x-razorpay-signature" ) as string ;
9+ const webhookSecret = process . env . RAZORPAY_WEBHOOK_SECRET as string ;
1010
11- const body = await req . text ( ) ;
12- const signature = req . headers . get ( "stripe-signature" ) as string ;
11+ if ( ! signature || ! webhookSecret ) {
12+ console . error ( "Missing webhook signature or secret" ) ;
13+ return new NextResponse ( "Invalid request" , { status : 400 } ) ;
14+ }
1315
14- let event : Stripe . Event ;
16+ // Verify the signature
17+ const expectedSignature = crypto
18+ . createHmac ( "sha256" , webhookSecret )
19+ . update ( body )
20+ . digest ( "hex" ) ;
1521
16- try {
17- event = stripe . webhooks . constructEvent (
18- body ,
19- signature ,
20- process . env . STRIPE_WEBHOOK_SECRET as string
21- ) ;
22- } catch ( error : any ) {
23- console . error ( `Webhook signature verification failed: ${ error . message } ` ) ;
24- return new NextResponse ( `Webhook Error: ${ error . message } ` , { status : 400 } ) ;
25- }
22+ if ( expectedSignature !== signature ) {
23+ console . error ( "Webhook signature verification failed" ) ;
24+ return new NextResponse ( "Invalid signature" , { status : 400 } ) ;
25+ }
2626
27- // Handle the checkout session completion
28- if ( event . type === "checkout.session.completed" ) {
29- const session = event . data . object as Stripe . Checkout . Session ;
30- const customerEmail = session . customer_details ?. email ;
31- const paymentIntentId = session . payment_intent as string ;
27+ // Parse event
28+ const event = JSON . parse ( body ) ;
3229
33- if ( ! customerEmail ) {
34- console . error ( "No customer email found in session." ) ;
35- return new NextResponse ( "Invalid Session Data" , { status : 400 } ) ;
36- }
30+ // Handle the order.paid event
31+ if ( event . event === "order.paid" ) {
32+ const paymentEntity = event . payload . payment . entity ;
33+ const orderEntity = event . payload . order . entity ;
3734
38- try {
39- if ( session . payment_status === "paid" ) {
40- // Create a new license in Keygen
41- await createLicenseForKeygen ( customerEmail , session . id , paymentIntentId ) ;
35+ const customerEmail = paymentEntity . email ;
36+ const paymentId = paymentEntity . id ;
37+ const orderId = orderEntity . id ;
38+
39+ if ( ! customerEmail ) {
40+ console . error ( "No customer email found in Razorpay payment data." ) ;
41+ return new NextResponse ( "Invalid Session Data" , { status : 400 } ) ;
4242 }
43- } catch ( e : any ) {
44- console . error ( "Failed to process order:" , e ) ;
45- // Stripe will retry the webhook if we fail.
46- // In production, we'd log this, potentially to Sentry or PostHog
47- return new NextResponse ( "Internal Server Error" , { status : 500 } ) ;
43+
44+ // Create a new license in Keygen
45+ await createLicenseForKeygen ( customerEmail , orderId , paymentId ) ;
4846 }
49- }
5047
51- // Return a 200 response to acknowledge receipt of the event
52- return new NextResponse ( JSON . stringify ( { received : true } ) , { status : 200 } ) ;
48+ return new NextResponse ( JSON . stringify ( { received : true } ) , { status : 200 } ) ;
49+ } catch ( error : any ) {
50+ console . error ( `Webhook Error: ${ error . message } ` ) ;
51+ return new NextResponse ( `Webhook Error: ${ error . message } ` , { status : 500 } ) ;
52+ }
5353}
5454
5555// -------------------------------------------------------------
5656// Core Business Logic
5757// -------------------------------------------------------------
5858
59- async function createLicenseForKeygen ( email : string , sessionId : string , paymentIntentId : string ) {
59+ async function createLicenseForKeygen ( email : string , orderId : string , paymentId : string ) {
6060 const accountId = process . env . VITE_KEYGEN_ACCOUNT_ID ;
6161 const policyId = process . env . VITE_KEYGEN_POLICY_ID ;
6262 const keygenToken = process . env . KEYGEN_API_TOKEN ;
@@ -79,8 +79,8 @@ async function createLicenseForKeygen(email: string, sessionId: string, paymentI
7979 attributes : {
8080 name : email ,
8181 metadata : {
82- stripe_payment_id : paymentIntentId ,
83- stripe_session_id : sessionId
82+ razorpay_payment_id : paymentId ,
83+ razorpay_order_id : orderId
8484 }
8585 } ,
8686 relationships : {
0 commit comments