这两天弄支付宝的回调页面,被坑了两天,记录一下。javascript
首先获取请求参数java
//获取参数 let post_param = typeof req.body == 'string' ? req.body.split('&') : []; for(let val of get_param) { let tmp = val.split('='); params[tmp[0]] = decodeURIComponent(tmp[1].replace(/\+/g,'%20')); }
接着校验是不是支付宝的请求api
//请求来源校验 let options = { hostname : 'mapi.alipay.com', path : `/gateway.do?service=notify_verify&partner=${ALIPAY_ID}¬ify_id=${notify_id}`, method : 'GET' }; let alipay_rt = ''; let req = require('https').request(options, (res) => { res.on('data', async (rt) => { alipay_rt += rt; }); res.on('end', async (rt) => { //校验是不是支付宝的请求 if(alipay_rt !== 'true') { reply('faild');return; } }); });
而后按要求校验签名async
let tmp = []; let str = ''; let keys = Object.keys(param); keys.sort();//排序 for(let key of keys) { if(key != 'sign' && key != 'sign_type' && param[key])//剔除空值及签名字段 { tmp.push(`${key}=${param[key]}`); } } str = tmp.join('&'); let publickey = ['-----BEGIN PUBLIC KEY-----\n']; let i = 0; while(i < ALIPAY_RSA.length) { publickey.push(ALIPAY_RSA.substring(i,i+64)+'\n'); i+=64; } publickey.push('-----END PUBLIC KEY-----'); return require('crypto').createVerify('RSA-SHA1').update(str).verify(publickey.join(''), sign, 'base64');
以上校验经过后,再检查一下订单信息,就能够更新订单状态了。post
有两点要注意,一是接收参数要解码,这里因为NODEJS把参数中的空格转为了+号,解码前须要把+号替换为%20;二是校验签名前,要把公钥加上开头和结尾标识,还有中间的换行。ui