2019-09-22 10:38:13
在统一下单中讲到了微信支付的统一下单,统一下单完成后就是客户端的事情了,根据返回的信息来调起微信支付,完成付款。当付款完成后,微信服务器会post支付结果通知我们,此接口需要单独来写,并且需要按照微信文档的要求来返回数据。
接收通知一般会进行如下步骤:
接收xml格式的数据和接收json的方式是不一样的,下面我们来看一下该如何接收微信支付通知结果的xml格式数据,我们还是将它写在pay.js文件中:
/**
* 解析通过post传递过来的xml信息
* @param req
* @returns {Promise<any>}
*/
exports.parseReqXmlData = (req)=>{
let notionData = "";
req.setEncoding('utf8');
req.on('data', (chunk)=>{
notionData += chunk;
});
return new Promise((resolve,reject)=>{
req.on("end",()=>{
resolve(notionData)
});
req.on("error",(e)=>{
reject(e)
})
})
};
我们不能用之前的req.body或req.query来进行接收了,要通过监听data来获取数据,上面我们将其封装成了promise的方式来进行返回数据。
接收到数据之后要做的就是解析,解析方法在统一下单中已经写过了,在这不在赘述,解析完成之后需要进行验签操作,以防恶意调用此接口进行支付结果的伪造,验签和签名的步骤差不多,就是对比一下传递过来的参数和签名是否一致,下面我们来看一下具体的实现方法
/**
* 校验返回结果签名是否正确
* @param obj 待校验对象
* @param key 商户平台设置的密钥key
* @returns {boolean} 返回结果 true为正确,false为不正确
*/
exports.checkPayResultSign = (obj,key)=>{
try{
let tempObj = Object.assign({},obj);
let resultSign = tempObj.sign;
delete tempObj.sign;
tempObj = exports.getWechatSign(tempObj,key);
if(tempObj){
return resultSign == tempObj.sign
}else{
console.log("checkPayResultSign:签名校验异常");
return false;
}
}catch(e){
console.log(e);
return false
}
};
如上方法就是进行签名校验,其实就是将传递过来的参数保存起来,然后在对参数进行签名,两次对比是否一致,签名方法在统一下单中已经写过了,需要的小伙伴可以看一下。
验签成功后要做的就是构造xml格式数据,通知微信服务器我们接收成功了。
/**
* 微信支付成功后,微信服务器主动回调方法,
*/
router.post("/payNotice",async (req,res)=>{
try{
let key="sdkfnowemcoiwem4"//这里我将key写死在这里了,正常是需要从数据库或配置文件中读取
let xmlPost = await exports.parseReqXmlData(req)//解析获取xml
let formatNotion = await exports.parseXml(xmlPost);//将xml格式解析为json格式
let result= "";
if(formatNotion.return_code === "SUCCESS"){
console.log(formatNotion);
let checkPayResultSign = exports.checkPayResultSign(formatNotion,key);
console.log("支付返回信息签名校验:"+checkPayResultSign);
if(checkPayResultSign){
result = `<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>`;
}else{
result = `<xml><return_code><![CDATA[FALSE]]></return_code><return_msg><![CDATA[FALSE]]></return_msg></xml>`;
}
}else{
result = `<xml><return_code><![CDATA[FALSE]]></return_code><return_msg><![CDATA[FALSE]]></return_msg></xml>`;
}
res.writeHead(200, {'Content-Type': 'text/xml'});
res.end(result)
}catch(e){
console.log("回调通知异常:"+JSON.stringify(e));
res.json({
success:false
});
}
catch里面我返回的是json格式,这个其实是为非正常调用返回的,正常微信调用是不会走catch的,所以不用过多考虑它,返回xml格式需要设置header,将Content-Type设置为text/xml,以告诉对方我们发送的是xml格式的数据。
至此如何接收微信支付通知结果就介绍完了,后续会继续介绍订单查询等后续接口