這兩天弄支付寶的回調頁面,被坑了兩天,記錄一下。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