微信開發越來越流行,我們知道在微信中有付款也有退款功能,這樣的功能非常常見,這篇文章主要介紹了node.js實現微信支付退款功能,需要的朋友可以參考下,希望能幫助大家。
緣起
有付款就會有退款
注意,退款支援部分退款
左口袋的錢退到右口袋羅
這次發起的退款要求0.01元是即時到帳的,因此,用戶在小程式端發起的退款只是一個請求到後台,後台審核人員審核無誤後才後微信發起退款操作。
引入第三方module
在package.json 中加入"weixin-pay": "^1.1.7"這條
#程式碼目錄結構
#
入參
{ transaction_id: '4200000005201712165508745023', // 交易 out_trade_no: '5b97cba0ae164bd58dfe9e77891d3aaf', // 自己这头的交易号 out_refund_no: '6f3240c353934105be34eb9f2d364cec', // 退款订单,自己生成 total_fee: 1, // 退款总额 nonce_str: '1xSZW0op0KcdKoMYxnyxhEuF1fAQefhU', // 随机串 appid: 'wxff154ce14ad59a55', // 小程序 appid mch_id: '1447716902', // 微信支付商户id sign: '416FCB62F9B8F03C82E83052CC77524B' // 签名,weixin-pay这个module帮助生成 }
然後由wxpay為我們生成其餘字段,例如nonce_str,sign,當然還少不了p12證書,
#這個早選在wxpay初始程式碼裡已經設定了,pfx: fs.readFileSync(__dirname + '/../../../cert/apiclient_cert.p12'), //微信商家平台憑證
lib/wechat/ utils/wxpay.js的原始碼
const WXPay = require('weixin-pay'); // 引入weixin-pay这个第三方模块 const {weapp} = require('../../../utils/config'); // 我自己的全局配置文件,包括了appid key 等 const fs = require('fs'); const wxpay = WXPay({ appid: weapp.APPID, mch_id: weapp.MCHID, partner_key: weapp.KEY, //微信商户平台 API secret,非小程序 secret pfx: fs.readFileSync(__dirname + '/../../../cert/apiclient_cert.p12'), }); module.exports = wxpay;
另外還有一個util.js工具類別
用於驗證與錯誤回調
const wxpay = require('./wxpay'); const validateSign = results => { const sign = wxpay.sign(results); if (sign !== results.sign) { const error = new Error('微信返回参数签名结果不正确'); error.code = 'INVALID_RESULT_SIGN'; throw error; }; return results; }; const handleError = results => { if (results.return_code === 'FAIL') { throw new Error(results.return_msg); } if (results.result_code !== 'SUCCESS') { const error = new Error(results.err_code_des); error.code = results.err_code; throw error; } return results; }; module.exports = { validateSign, handleError, };
發起退款請求
#退款邏輯是這樣的,先從自己這邊的Order資料表中查出transaction_id/out_trade_no/total_fee,再拼上自己產生的out_refund_no退款單號,本次退款部分金額refund_fee,最後由weixin -pay這個模組下的wxpay.refund調起就可以了,成功就把訂單狀態改成"退款成功"
// 退款 router.post('/refund', function(req, res) { Order.findById(req.body._id, (err, order) => { if (err) { console.log(err); } console.log(order); // 生成微信设定的订单格式 var data = { transaction_id: order.transactionId, out_trade_no: order.tradeId, out_refund_no: uuid().replace(/-/g, ''), total_fee: order.amount, refund_fee: order.amount }; console.log(data); // 先查询订单,再退订单 wxpay.refund(data, (err, result) => { if (err) { console.log(err); res.send( utils.json({ code: 500, msg: '退款失败' }) ); } // 返回退款请求成功后,要将订单状态改成REFUNDED if (result.result_code === 'SUCCESS') { console.log(result); order.status = 'REFUNDED'; order.save((err, response) => { res.send( utils.json({ msg: '退款成功' }) ); }); } else { res.send( utils.json({ code: 500, msg: result.err_code_des }) ); } }); }); });
入參的坑
1.這次遇到的坑是refund_fee忘記傳值,也就是說微信退款是支持部分退款的,如果是全額退款,那麼將它賦值為total_fee相同
2.網上說的op_user_id: weapp. MCHID這個參數是非必選的
3.transaction_id 與out_trade_no 二選一即可,這樣在沒有記錄transaction_id的情況(例如沒有寫支付成功的callback)下,也能發起退款;其中優先級前者大於後者,在我在分別前其一故意給錯的過程中得到了驗證。
4.報了一個appid與商家號碼不符'原來是小程式還沒綁定公眾號微信支付,這真是個烏龍。
成功退款微信回傳的資料
appid:"wxff154ce14ad59a55" cash_fee:"1" cash_refund_fee:"1" coupon_refund_count:"0" coupon_refund_fee:"0" mch_id:"1447716902" nonce_str:"c44wOvB6a4bQJfRk" out_refund_no:"9ace1466432a4d548065dc8df95d904a" out_trade_no:"5b97cba0ae164bd58dfe9e77891d3aaf" refund_channel:"" refund_fee:"1" refund_id:"50000705182017121702756172970" result_code:"SUCCESS" return_code:"SUCCESS" return_msg:"OK" sign:"5C2E67B3250054E8A665BF1AE2E9BDA3" total_fee:"1" transaction_id:”4200000005201712165508745023”
重複退款將回傳如下
appid:"wxff154ce14ad59a55" err_code:"ERROR" err_code_des:"订单已全额退款" mch_id:"1447716902" nonce_str:"KP1YWlU7a5viZEgK" result_code:"FAIL" return_code:"SUCCESS" return_msg:"OK" sign:”C2A7DED787BEA644C325E37D96E9F41C”
最後
如果沒有寫退款功能或不想寫退款功能怎麼辦,其實可以從微信支付的後台pay.weixin.qq.com,也是能退款出去的,只是不想忘記了要人工將訂單狀態置為退款狀態。
相關推薦:
#以上是實例詳解node.js實作微信支付退款功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!