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.
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.