Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cant verify signature #380

Open
profabhishekjha opened this issue Sep 29, 2023 · 10 comments
Open

cant verify signature #380

profabhishekjha opened this issue Sep 29, 2023 · 10 comments

Comments

@profabhishekjha
Copy link

Steps to reproduce the behavior

import crypto from "crypto";
import prisma from "@/utils/connect";
import { NextResponse } from "next/server";

export const POST = async (req) => {
try {
const body = await req.json();
const { event, payload } = body;

  // Your Razorpay key secret
  const razorpayKeySecret = "**************";

  // Retrieve the Razorpay signature from the x-razorpay-signature header
  const razorpaySignature = req.headers.get("x-razorpay-signature");

  // Verify the Razorpay signature
  const generatedSignature = crypto
    .createHmac("sha256", razorpayKeySecret)
    .update(JSON.stringify(payload))
    .digest("hex");

  if (generatedSignature !== razorpaySignature) {
    console.error("Invalid Razorpay signature");
    return new NextResponse("Invalid Razorpay signature", { status: 401 });
  }

  switch (event) {
    case "payment.authorized":
      break;
    case "payment.captured":
      const donationId = payload.payment.entity.notes.donationId;

      if (donationId) {
        await prisma.donation.update({
          where: { id: donationId },
          data: { status: "Success" },
        });
        console.log("Payment Captured:", donationId);
      } else {
        console.error(
          "Invalid or missing donationId from Razorpay webhook payload"
        );
        return new NextResponse("Invalid or missing donationId", {
          status: 400,
        });
      }
      break;
    default:
      // Handle other events if needed
      console.log("Unhandled Event:", event);
  }

  return new NextResponse("Webhook Received", { status: 200 });
} catch (error) {
  console.error("Error processing webhook:", error);
  return new NextResponse(
    JSON.stringify({ message: "Something went wrong!" }, { status: 500 })
  );
}

};

Expected behavior

it should verify signature but no , its not, please help me if anyone can

Actual behavior

its not matching both the values

Code snippets

import crypto from "crypto";
  import prisma from "@/utils/connect";
  import { NextResponse } from "next/server";

  export const POST = async (req) => {
    try {
      const body = await req.json();
      const { event, payload } = body;

      // Your Razorpay key secret
      const razorpayKeySecret = "**************";

      // Retrieve the Razorpay signature from the x-razorpay-signature header
      const razorpaySignature = req.headers.get("x-razorpay-signature");

      // Verify the Razorpay signature
      const generatedSignature = crypto
        .createHmac("sha256", razorpayKeySecret)
        .update(JSON.stringify(payload))
        .digest("hex");

      if (generatedSignature !== razorpaySignature) {
        console.error("Invalid Razorpay signature");
        return new NextResponse("Invalid Razorpay signature", { status: 401 });
      }

      switch (event) {
        case "payment.authorized":
          break;
        case "payment.captured":
          const donationId = payload.payment.entity.notes.donationId;

          if (donationId) {
            await prisma.donation.update({
              where: { id: donationId },
              data: { status: "Success" },
            });
            console.log("Payment Captured:", donationId);
          } else {
            console.error(
              "Invalid or missing donationId from Razorpay webhook payload"
            );
            return new NextResponse("Invalid or missing donationId", {
              status: 400,
            });
          }
          break;
        default:
          // Handle other events if needed
          console.log("Unhandled Event:", event);
      }

      return new NextResponse("Webhook Received", { status: 200 });
    } catch (error) {
      console.error("Error processing webhook:", error);
      return new NextResponse(
        JSON.stringify({ message: "Something went wrong!" }, { status: 500 })
      );
    }
  };

Node version

latest

Library version

latest

Additional Information

No response

@crypticatul
Copy link

crypticatul commented Dec 30, 2023

We are also facing the same issue. Is anyone working on this?
@projectashik

@dhwaj1902
Copy link

I am facing the same issue. Can anyone in Razorpay help us with this?
or @profabhishekjha have you figured out any solution for this?

@kakdeykaushik
Copy link

You can use validatePaymentVerification function to verify payment signature. Refer to this doc

@dhwaj1902
Copy link

Hi @kakdeykaushik,
I have also used validatePaymentVerification, but I could not verify the signature in the webhook response.

@Sen-442b
Copy link

Sen-442b commented Jun 6, 2024

In the docs they have mentioned using raw requestbody (req.body) as the message to create the hash signature.
In your case, you're using payload of the body

const generatedSignature = crypto
        .createHmac("sha256", razorpayKeySecret)
        .update(JSON.stringify(req.body)) // raw requestBody  
        .digest("hex");

@RaunakMandal
Copy link

@Sen-442b I have used the raw req.body, and it's failing only for 'invoice.paid'. Any light on that?

const validation = validateWebhookSignature(
         JSON.stringify(req.body),
         razorpaySignature as string,
         process.env.RAZORPAY_WEBHOOK_SECRET as string
      );`

@Sen-442b
Copy link

Sen-442b commented Aug 9, 2024

@Sen-442b I have used the raw req.body, and it's failing only for 'invoice.paid'. Any light on that?

const validation = validateWebhookSignature(
         JSON.stringify(req.body),
         razorpaySignature as string,
         process.env.RAZORPAY_WEBHOOK_SECRET as string
      );`
  1. Have you included the 'invoice.paid' event in your webhook settings in the Razorpay dashboard?
  2. Are you using middleware to ensure that the request body is parsed as raw data?

Here's a snippet of the code that's working on my end:

app.post(
  '/api/webhook',
  bodyParser.raw({ type: 'application/json' }), //third party library
  checkDuplicateEvent,
  async (request, response) => {
    try {
      const webhookSignature = request.headers['x-razorpay-signature'];
      const webhookSecret = process.env.RAZORPAY_WEBHOOK_ENDPOINT_SECRET;
      const isValidRequest = validateWebhookSignature(
        request.body,
        webhookSignature,
        webhookSecret
      );

      if (isValidRequest) {
        console.log('webhook validated');
      } else {
        console.log('webhook not validated');
        return response.status(400).send('Invalid request');
      }
      
      

@RaunakMandal
Copy link

I am apparently not using any third party library to parse raw body. I am using NextJS, so it is anyway using bodyparser.json({}).

Payment.captured webhook is enabled, it is even getting verified. There is definitely some issue with the invoice.paid.

@Dhirajchaudari
Copy link

I am apparently not using any third party library to parse raw body. I am using NextJS, so it is anyway using bodyparser.json({}).

Payment.captured webhook is enabled, it is even getting verified. There is definitely some issue with the invoice.paid.

please help us I'm also facing issue with invoice.paid

@Avik-creator
Copy link

Avik-creator commented Oct 3, 2024

import crypto, { createHmac } from "crypto";
import { NextRequest, NextResponse } from "next/server";
import Razorpay from "razorpay";
export async function POST(req: NextRequest, res: NextResponse) {
  const bodyreq = await req.json();

  // Correctly accessing the fields from the body
  const orderCreationId = bodyreq?.orderCreationId;
  const razorpay_order_id = bodyreq?.razorpayOrderId; // Corrected
  const razorpay_payment_id = bodyreq?.razorpayPaymentId; // Corrected
  const razorpay_signature = bodyreq?.razorpaySignature; // Corrected

  // Check for missing required fields
  if (!orderCreationId || !razorpay_order_id || !razorpay_payment_id || !razorpay_signature) {
    return NextResponse.json({ isOk: false, message: "Missing required fields" }, { status: 400 });
  }

  const secret = process.env.NEXT_PUBLIC_RAZORPAY_WEBHOOK_SECRET;

  if (!secret) {
    console.error("RAZORPAY_WEBHOOK_SECRET is not set");
    return NextResponse.json({ isOk: false, message: "Internal Server Error" }, { status: 500 });
  }

  try {
    // Create the expected signature using the correct order ID and payment ID
    const body = razorpay_order_id + "|" + razorpay_payment_id;

    const valid = Razorpay.validateWebhookSignature(JSON.stringify(bodyreq), razorpay_signature as string, secret);

    console.log(valid);

    console.log(valid, "sfgjhsdfkjh");

    // Verify the received signature against the expected signature
    if (valid) {
      console.log("Payment verified");
      return NextResponse.json({ isOk: true, message: "Payment verified" }, { status: 200 });
    } else {
      return NextResponse.json({ isOk: false, message: "Invalid signature" }, { status: 400 });
    }
  } catch (error) {
    console.error("Error verifying RazorPay payment:", error);
    return NextResponse.json({ isOk: false, message: "Internal Server Error" }, { status: 500 });
  }
}

I am doing the above in Nextjs, but it is showing me false for valid signature. Any Help Regarding this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants