node.jsbase64payment-gatewayhmac

Trying to implement SimplePay (OTP) payment gateway in a NodeJS project, but I fail to get the same signature as in the tech documentation


I'm trying to implement SimplePay (OTP) payment gateway in a NodeJS project.

So far I'm only exploring and following the technical documentation, and try to put together the test start request as per the documentation, but I cannot get the same signature as it's expected in the docs.

Documentation (examples are with their PHP SDK):

How to create the signature:

signature = codeBase64(hmacWithSha384(merchantKey, message))

(so create a HMCAC SHA384 hash of the whole JSON sent in the post body (this is the message), and use the merchantKey, then base64 encode the has result)

merchantKey:

FxDa5w314kLlNseq2sKuVwaqZshZT5d6

message (should be the whole JSON sent in the POST body):

{"salt":"c1ca1d0e9fc2323b3dda7cf145e36f5e","merchant":"PUBLICTESTHUF","orderRef":"101010516348232058105","currency":"HUF","customerEmail":"sdk_test@otpmobil.com","language":"HU","sdkVersion":"SimplePayV2.1_Payment_PHP_SDK_2.0.7_190701:dd236896400d7463677a82a47f53e36e","methods":\["CARD"\],"total":"25","timeout":"2021-10-30T12:30:11+00:00","url":"https://sdk.simplepay.hu/back.php"}

Expected outcome of the signature according to the docs:

gcDJ8J7TyT1rC/Ygj/8CihXaLwniMWRav09QSEMQUnv5TbYaEDvQAuBE1mW3plvZ

Now I've tried a lot of things, but can't seem to get the same signature. Here's my code, and questions:

const bodyAsText = `{"salt":"c1ca1d0e9fc2323b3dda7cf145e36f5e","merchant":"PUBLICTESTHUF","orderRef":"101010516348232058105","currency":"HUF","customerEmail":"sdk_test@otpmobil.com","language":"HU","sdkVersion":"SimplePayV2.1_Payment_PHP_SDK_2.0.7_190701:dd236896400d7463677a82a47f53e36e","methods":\["CARD"\],"total":"25","timeout":"2021-10-30T12:30:11+00:00","url":"https://sdk.simplepay.hu/back.php"}\`;

const message = JSON.parse(bodyAsText);

const merchantKey = "FxDa5w314kLlNseq2sKuVwaqZshZT5d6";

const signature = createHmac("sha384", merchantKey)
.update(JSON.stringify(message))
.digest("base64");

console.log("Your signature is: ", signature);\

I've also tried this way:

const signature = createHmac("sha384", merchantKey) .update(JSON.stringify(message)) .digest().toString('base64');

But the result is the same:

dwvuWq4Hyec9BtriL4N+LC42u4G10PcHcpcvCM9TIxL7VJJFBvIi5jQLev86Pedu

I've tried submitting the request via postman. for the same JSON in body, I get signature error with my signature, and success with the one written in docs, which is kind of expected, I just don't get what I'm missing.


Solution

  • The issue is caused by the URL in the message and differences between PHP (to which the documentation refers) and JavaScript/NodeJS (what you are using).

    In PHP, \/ is not treated as an escape sequence and is interpreted as \/. In JavaScript, \/ is treated as an escape sequence and interpreted as /. For the input to be interpreted as \/, \/ (or /) must be replaced with \\/ in the message string, e.g.:

    const crypto = require('crypto');
    
    const merchantKey = "FxDa5w314kLlNseq2sKuVwaqZshZT5d6";
    const body = {"salt":"c1ca1d0e9fc2323b3dda7cf145e36f5e","merchant":"PUBLICTESTHUF","orderRef":"101010516348232058105","currency":"HUF","customerEmail":"sdk_test@otpmobil.com","language":"HU","sdkVersion":"SimplePayV2.1_Payment_PHP_SDK_2.0.7_190701:dd236896400d7463677a82a47f53e36e","methods":["CARD"],"total":"25","timeout":"2021-10-30T12:30:11+00:00","url":"https:\/\/sdk.simplepay.hu\/back.php"}
    const message = JSON.stringify(body).replace(/\//g, "\\\/");
    
    const signature = crypto.createHmac("sha384", merchantKey)
    .update(message)
    .digest("base64");
    
    console.log("Your signature is: ", signature); // Your signature is:  gcDJ8J7TyT1rC/Ygj/8CihXaLwniMWRav09QSEMQUnv5TbYaEDvQAuBE1mW3plvZ
    

    Note that this fix is to be made in the message string, not in the JavaScript object, where \/ would be interpreted as /, and \\/ as \\/ (and not as \/).

    Also note that there are two typos in the JavaScript object you posted for the message: The backslashes before the two square brackets must be removed.