Closed highmore closed 1 year ago
在用Koa
项目代码片段,供参考:
import { readFileSync } from 'fs';
import Router from 'koa-router';
import { Rsa, Formatter, Aes } from 'wechatpay-axios-plugin';
const base64 = 'base64', SUCCESS = 'SUCCESS', WechatpayNonce = 'wechatpay-nonce', WechatpaySerial = 'wechatpay-serial', WechatpaySignature = 'wechatpay-signature', WechatpayTimestamp = 'wechatpay-timestamp';
const WXPAY_APIV3 = 'exposed_your_key_here_have_risks';
const PUBKEY = {
'ABCD': readFileSync('/path/to/wechatpay/cert.pem'),
};
export default (new Router)
.post('/', async ctx => {
const { headers: { [WechatpaySerial]: wechatpaySerial, [WechatpayNonce]: wechatpayNonce, [WechatpaySignature]: wechatpaySignature, [WechatpayTimestamp]: wechatpayTimestamp, } } = ctx;
wechatpaySerial && wechatpayNonce && wechatpaySignature && wechatpayTimestamp || ctx.throw(401, `Missing of the headers.`);
PUBKEY[wechatpaySerial] || ctx.throw(401, `Abuse of the header's ${WechatpaySerial}: ${wechatpaySerial}.`);
Math.abs(wechatpayTimestamp*1 - Formatter.timestamp()) > 300 && ctx.throw(403, `Abuse of the header's ${WechatpayTimestamp}: ${wechatpayTimestamp}.`);
Rsa.verify(Formatter.joinedByLineFeed(wechatpayTimestamp, wechatpayNonce, ctx.request.rawBody), wechatpaySignature, PUBKEY[wechatpaySerial]) || ctx.throw(403, `Abuse of the header's ${WechatpaySignature}: ${wechatpaySignature}.`);
const { id: event_id, event_type, create_time, resource: { ciphertext, associated_data, nonce } } = ctx.request.body;
const decrypted = JSON.parse(Aes.AesGcm.decrypt(nonce, Buffer.from(WXPAY_APIV3, base64), ciphertext, associated_data));
//退款通知 @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_11.shtml
console.debug(event_id, event_type, create_time, decrypted);
// 更多逻辑...
ctx.body = {code: SUCCESS, message: `Thanks for the notification.` };
});
非常感谢您的回答,还有一个小问题: 代码中的 WXPAY_APIV3 是指微信支付证书里面的 apiclient_key.pem 还是 apiclient_cert.pem 或者是 API_V3 密匙?
非常感谢您的回答,还有一个小问题: 代码中的 WXPAY_APIV3 是指微信支付证书里面的 apiclient_key.pem 还是 apiclient_cert.pem 或者是 API_V3 密匙?
WXPAY_APIV3
是 APIv3密钥,这里是用的base64字符串构型;PUBKEY
对象是 微信支付平台证书,可以通过内置的 wxp crt
工具下载,键为证书序列号
,值为证书文件字节流
;噢,感谢耐心解答。您提供的代码中有一段:
const decrypted = JSON.parse(Aes.AesGcm.decrypt(nonce, Buffer.from(WXPAY_APIV3, base64), ciphertext, associated_data));
这里的 Buffer.from(WXPAY_APIV3, base64) 把我弄糊涂了,应该是 Buffer.from(ciphertext, base64) 才对吧? 最后再请教一个问题:您提供的Koa代码中Rsa.verify(Formatter.joinedByLineFeed(wechatpayTimestamp, wechatpayNonce, ctx.request.rawBody), wechatpaySignature, PUBKEY[wechatpaySerial]) || ctx.throw(403, ‘Abuse of the header's ${WechatpaySignature}: ${wechatpaySignature}.’);
使用了 ctx.request.rawBody 来验证签名 因为我使用的是 Express,怎样才能拿到 rawBody ?
借用中间件能力 https://github.com/expressjs/body-parser ,例如:
app.use(bodyParser.json({
verify: function (req, res, buf, encoding) {
req.rawBody = buf;
}
}));
感谢,完美搞定!
RT