nodejs 微信退款
阿新 • • 發佈:2018-12-29
基於nodejs 微信退款
說明
只是單純的記錄學習過程
官方文件:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
準備
1.當然已經有了已支付的訂單
2.退款需要雙向證書,證書下載可見官網
微信商戶平臺(pay.weixin.qq.com)–>賬戶中心–>賬戶設定–>API安全 。
那就開始吧
exports.miniRefund = function (req,res) {
let refundData = req.body;//獲取資料 在這裡我獲取的其實就是該訂單支付的時候的資訊,因為當時存起來了,大家根據自己邏輯新增資料
let appid = refundData.appid;//公眾賬號ID
let mch_id = refundData.mch_id//商戶號
let nonce_str = refundData.nonce_str//這是隨機字串,為了方便我用的是該訂單在支付的時候的隨機字串
let out_trade_no = refundData.out_trade_no;//支付的訂單號
let out_refund_no = refundData. out_refund_no;//退款訂單號
let total_fee= refundData.total_fee;//支付金額
let refund_fee = total_fee;//退款金額 因為我的邏輯是全額退款所以退款金額等於支付金額
let refund_desc = refundData.refund_desc;//退款原因
let sign = wechatUtil.refundSign(appid,mch_id,nonce_str,out_trade_no,out_refund_no,total_fee,refund_fee,refund_desc);//最重要的一步 簽名 這是呼叫了我自己封裝的一個方法,後面也會貼出來,關於簽名大家可以到網上看一下就不說了
let formData = "<xml>";
formData += "<appid>"+appid+"</appid>";
formData += "<mch_id>"+mch_id+"</mch_id>";
formData += "<nonce_str>"+nonce_str+"</nonce_str>";
formData += "<out_trade_no>"+out_trade_no+"</out_trade_no>";
formData += "<out_refund_no>"+out_refund_no+"</out_refund_no>";
formData += "<total_fee>"+total_fee+"</total_fee>";
formData += "<refund_fee>"+refund_fee+"</refund_fee>";
formData += "<refund_desc>"+refund_desc+"</refund_desc>";
formData += "<sign>"+sign+"</sign>";
formData += "</xml>";
/*==================================================*/
//接下來我們要用到一個request
let request = require('request');//當然我們引用要寫在最上面,但為了看的清楚點就一步一步走吧
request({
//請求地址
url:'https://api.mch.weixin.qq.com/secapi/pay/refund',
//還記得準備的證書嗎這裡就用到啦
agentOptions: {
cert: fs.readFileSync(path1.join(__dirname,'../../cert/apiclient_cert.pem')),
key: fs.readFileSync(path1.join(__dirname,'../../cert/apiclient_key.pem' ))
},
method: 'POST',
//攜帶這我們拼接好的引數
body:formData
}, function (err,body) {
//getXMLNodeValue:因為微信返回的結果是xml形式的所以封裝了一個解析的方法,會面會貼出來
let trade_state_desc = wechatUtil.getXMLNodeValue('return_code', body.body.toString('utf-8'));
let return_msg = wechatUtil.getXMLNodeValue('return_msg', body.body.toString('utf-8'));
let err_code_des = wechatUtil.getXMLNodeValue('err_code_des', body.body.toString('utf-8'));
//為什麼要加上這個引數err_code_des....我也很是無奈前兩個引數只能正面是真的訪問成功了,但是我試了一下 瞎寫的訂單號提交
//這兩個引數還是正常的,但會多出 err_code_des這個引數,返回的是提示資訊.所以前兩個引數正確且沒有這個引數的時候我才能知道
//提交的資訊沒有問題,所以就這樣寫了,但肯定不是很好,我會想想解決辦法. if(return_code=='SUCCESS'&&return_msg=='OK'&&err_code_des==undefined){
log.info("退款成功")
let data = {
result:'1',
msg:'已退款成功'
};
res.json(data)
}else {
let data = {
result:'0',
msg:err_code_des
};
res.json(data)
}
});
}
接下是加簽的方法和解析xml的方法
//解析xml資料
exports.getXMLNodeValue = (node_name,xml)=>{
log.info(xml);
let tmp = xml.split("<"+node_name+">");
if(tmp[1]!=undefined){
let _tmp = tmp[1].split("</"+node_name+">");
let tmp1 = _tmp[0].split('[');
let _tmp1 = tmp1[2].split(']');
return _tmp1[0];
}
};
//退款簽名
exports.refundSign=(appid,mch_id,nonce_str,out_trade_no,out_refund_no,total_fee,refund_fee,refund_desc)=>{
let ret = {
appid: appid,
mch_id: mch_id,
nonce_str:nonce_str,
out_trade_no:out_trade_no,//注意左邊引數名,
out_refund_no:out_refund_no,
total_fee:total_fee,
refund_fee:refund_fee,
refund_desc:refund_desc
};
log.info("查詢簽名驗證的引數",ret);
let string = raw(ret);
let key = "金鑰*************";
string = string + '&key='+key;
return crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase();
};
//排序PS : key toLowerCase
function raw(args) {
var keys = Object.keys(args);
keys = keys.sort();
var newArgs = {};
keys.forEach(function (key) {
newArgs[key.toLowerCase()] = args[key];
});
var string = '';
for (var k in newArgs) {
string += '&' + k + '=' + newArgs[k];
}
string = string.substr(1);
console.log(string);
return string;
};
結束
但還是有很多問題…可以看到商品詳情是undefined,但我在文件中也沒有找到商品詳情的引數,
有點煩,希望儘快解決,當然我們還是少了一步,我們還應該通過查詢退款來做驗證,因為我還沒弄,但感覺難度也不會很大,後面會補上