Node.js 示例
示例为:
POST /payIn/orders/createAndPay,签名串为timestamp|nonce|rawBody。
javascript
const crypto = require("crypto");
function sign(timestamp, nonce, body, secret) {
const signData = `${timestamp}|${nonce}|${body}`;
return crypto.createHmac("sha256", secret).update(signData).digest("base64");
}
const body = JSON.stringify({
merchantOrderNo: "M202412220001",
amount: "100.00",
currency: "USD",
methodCode: "INTERNATIONAL_CARD",
methodData: {
cardNumber: "4111111111111111",
expiryMonth: "12",
expiryYear: "27",
securityCode: "123"
}
});
const timestamp = Date.now().toString();
const nonce = "b2b2f3b6a6f24a4ba3dcd0e777c9a888";
const signature = sign(timestamp, nonce, body, "sk_test_9f3b8a2d7c1e4f6a8b0c2d4e6f8a1b3c");
// 用 axios/fetch 发送请求并设置 Headers:
// X-Merchant-Id, X-Timestamp, X-Nonce, X-Sign验签示例(回调)
rawBody 为实际接收的原始 JSON 字符串。
javascript
const crypto = require("crypto");
function sign(timestamp, nonce, body, secret) {
const signData = `${timestamp}|${nonce}|${body}`;
return crypto.createHmac("sha256", secret).update(signData).digest("base64");
}
function verify(timestamp, nonce, rawBody, secret, signHeader) {
const expected = sign(timestamp, nonce, rawBody, secret);
const expectedBuf = Buffer.from(expected);
const signBuf = Buffer.from(signHeader);
if (expectedBuf.length !== signBuf.length) {
return false;
}
return crypto.timingSafeEqual(expectedBuf, signBuf);
}
const rawBody = '{"payNo":"P202312230001","tradeStatus":"SUCCESS"}';
const timestamp = "1734921005000";
const nonce = "b2b2f3b6a6f24a4ba3dcd0e777c9a888";
const signHeader = "base64_signature_from_header";
const ok = verify(timestamp, nonce, rawBody, "sk_test_9f3b8a2d7c1e4f6a8b0c2d4e6f8a1b3c", signHeader);
console.log(ok);