Cashfree signature is not validating in javascript

107 views Asked by At

I am integrating cashfree gateway in our website which uses nodejs(koa server). To validate the signature they send request body and timestamp in headers so to validate it I have to generate signature at by concating timestamp with raw body ( amount field must contain 2 digits after decimal ).

I am facing issue in javascript because cashfree wants amount field in 2 decimal place even in whole number but javascript converts (1898.00 into 1898) basically it does not understand decimal numbers when I parse the number in float and use toFixed(2) so data type changes to string. I want to pass payment_amount and order_amount in float number for a whole number also in javascript Is it possible to do that please help me here

ideal object {"data":{"order":{"order_id":"order_453912VQqDHqtQDCQdRfZj5Q1W4G3apB","order_amount":17500.00,"order_currency":"INR","order_tags":{"address":"Hello World","localTransactionId":"2290","paymentFor":"1849939000004509001","type":"invoice"}},"payment":{"cf_payment_id":2148739167,"payment_status":"SUCCESS","payment_amount":17500.00,"payment_currency":"INR","payment_message":"Transaction Successful","payment_time":"2023-09-15T17:19:10+05:30","bank_reference":"85511","auth_id":null,"payment_method":{"app":{"channel":null,"upi_id":null}},"payment_group":"wallet"},"customer_details":{"customer_name":null,"customer_id":"1849939000003987046","customer_email":"[email protected]","customer_phone":"+918909997453"}},"event_time":"2023-09-15T17:19:12+05:30","type":"PAYMENT_SUCCESS_WEBHOOK"}

what I my code is able to generate

1)without decimal places for whole number

{"data":{"order":{"order_id":"order_453912VQqDHqtQDCQdRfZj5Q1W4G3apB","order_amount":17500,"order_currency":"INR","order_tags":{"address":"Hello World","localTransactionId":"2290","paymentFor":"1849939000004509001","type":"invoice"}},"payment":{"cf_payment_id":2148739167,"payment_status":"SUCCESS","payment_amount":17500,"payment_currency":"INR","payment_message":"Transaction Successful","payment_time":"2023-09-15T17:19:10+05:30","bank_reference":"85511","auth_id":null,"payment_method":{"app":{"channel":null,"upi_id":null}},"payment_group":"wallet"},"customer_details":{"customer_name":null,"customer_id":"1849939000003987046","customer_email":"[email protected]","customer_phone":"+918909997453"}},"event_time":"2023-09-15T17:19:12+05:30","type":"PAYMENT_SUCCESS_WEBHOOK"}

  1. in string datatype

{"data":{"order":{"order_id":"order_453912VQqDHqtQDCQdRfZj5Q1W4G3apB","order_amount":"17500.00","order_currency":"INR","order_tags":{"address":"Hello World","localTransactionId":"2290","paymentFor":"1849939000004509001","type":"invoice"}},"payment":{"cf_payment_id":2148739167,"payment_status":"SUCCESS","payment_amount":"17500.00","payment_currency":"INR","payment_message":"Transaction Successful","payment_time":"2023-09-15T17:19:10+05:30","bank_reference":"85511","auth_id":null,"payment_method":{"app":{"channel":null,"upi_id":null}},"payment_group":"wallet"},"customer_details":{"customer_name":null,"customer_id":"1849939000003987046","customer_email":"[email protected]","customer_phone":"+918909997453"}},"event_time":"2023-09-15T17:19:12+05:30","type":"PAYMENT_SUCCESS_WEBHOOK"}

2

There are 2 answers

1
Arin Chaudhary On

Your answer is :

// Sample object
const inputData = {
    "data": {
        "order": {
            "order_id": "order_453912VQqDHqtQDCQdRfZj5Q1W4G3apB",
            "order_amount": 17500.00, // This should be converted to a float with 2 decimal places
            "order_currency": "INR",
            // ...
        },
        "payment": {
            "cf_payment_id": 2148739167,
            "payment_status": "SUCCESS",
            "payment_amount": 17500.00, // This should be converted to a float with 2 decimal places
            "payment_currency": "INR",
            // ...
        },
        // ...
    },
    // ...
};

// Convert order_amount and payment_amount to floats with 2 decimal places
inputData.data.order.order_amount = parseFloat(inputData.data.order.order_amount).toFixed(2);
inputData.data.payment.payment_amount = parseFloat(inputData.data.payment.payment_amount).toFixed(2);

console.log(inputData);
3
obh On

I don't think you need to convert the object at all. Even before parsing the object, you should just grab the raw body and do the signature verification first.

see here: https://github.com/cashfree/cashfree-pg-webhook/blob/main/node/server.js

Basically, we just copy the raw requestbody in another parameter and use that for signature verification.

app.use(
  express.json({
    limit: '2mb',
    verify: (req, res, buf) => {
      req.rawBody = buf.toString();
    },
  })
);

Edit: final solution for koa is to just include unparsed body.But broadly you need to grab the raw request and use that instead of the parsed body.

app.use( koaBody({includeUnparsed: true }), ) 
const unparsedBody = ctx.request.body[Symbol.for('unparsedBody')]; 

change package.json with the "koa-body": "^4.2.0" and now your ctx will have the unparsed body in the above mention keyas