基于node.js实现微信支付退款功能


Posted in Javascript onDecember 19, 2017

缘起

有付款就会有退款

注意,退款支持部分退款

左口袋的钱退到右口袋罗

基于node.js实现微信支付退款功能 

这次发起的退款请求0.01元是实时到账的,因此,用户在小程序端发起的退款只是一个请求到后台,后台审核人员审核无误后才后微信发起退款操作。

引入第三方module

在package.json 中加入"weixin-pay": "^1.1.7"这一条

代码目录结构

基于node.js实现微信支付退款功能 

入参

{ 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与商户号不匹配的报错,return_code: 'FAIL', return_msg: '商户号mch_id与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”

基于node.js实现微信支付退款功能 

最后

如果没有写退款功能或者不想写退款功能怎么办,其实可以从微信支付的后台pay.weixin.qq.com,也是能退款出去的,只是不想忘记了要人工将订单状态置为退款状态。

总结

以上所述是小编给大家介绍的基于node.js实现微信支付退款功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 手动给表增加数据的小例子
Jul 10 Javascript
基于Bootstrap+jQuery.validate实现Form表单验证
Dec 16 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
Oct 25 Javascript
AngularJS实现数据列表的增加、删除和上移下移等功能实例
Sep 05 Javascript
angular使用post、get向后台传参的问题实例
May 27 Javascript
angular2中Http请求原理与用法详解
Jan 11 Javascript
手写简单的jQuery雪花飘落效果实例
Apr 22 jQuery
如何让node运行es6模块文件及其原理详解
Dec 11 Javascript
js实现百度淘宝搜索功能
Feb 17 Javascript
最全vue的vue-amap使用高德地图插件画多边形范围的示例代码
Jul 17 Javascript
JS继承实现方法及优缺点详解
Sep 02 Javascript
Vue 实例中使用$refs的注意事项
Jan 29 Vue.js
React Native之prop-types进行属性确认详解
Dec 19 #Javascript
响应式框架Bootstrap栅格系统的实例
Dec 19 #Javascript
vue.js element-ui validate中代码不执行问题解决方法
Dec 18 #Javascript
AngularJs点击状态值改变背景色的实例
Dec 18 #Javascript
jQuery实现点击DIV同时点击CheckBox,并为DIV上背景色的实例
Dec 18 #jQuery
JS实现点击复选框变更DIV显示状态的示例代码
Dec 18 #Javascript
Vue下的国际化处理方法
Dec 18 #Javascript
You might like
简单的用PHP编写的导航条程序
2006/10/09 PHP
PHP实现显示照片exif信息的方法
2014/07/11 PHP
php微信公众号开发(3)php实现简单微信文本通讯
2016/12/15 PHP
php之header的不同用法总结(实例讲解)
2017/11/28 PHP
JavaScript 封装Ajax传递的数据代码
2009/06/05 Javascript
js 优化次数过多的循环 考虑到性能问题
2011/03/05 Javascript
网页防止tab键的使用快速解决方法
2013/11/07 Javascript
jquery实现炫酷的叠加层自动切换特效
2015/02/01 Javascript
JavaScript中判断数据类型的方法总结
2016/05/24 Javascript
Highcharts学习之坐标轴
2016/08/02 Javascript
基于JavaScript实现自定义滚动条
2017/01/25 Javascript
使用bat打开多个cmd窗口执行gulp、node
2017/02/17 Javascript
详解AngularJS2 Http服务
2017/06/26 Javascript
webpack实现一个行内样式px转vw的loader示例
2018/09/13 Javascript
使用Angular 6创建各种动画效果的方法
2018/10/10 Javascript
vue中导出Excel表格的实现代码
2018/10/18 Javascript
[01:51]2014DOTA2国际邀请赛 这个赛场没有失败者VGTi5再见
2014/07/23 DOTA
[01:21:07]EG vs Liquid 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
使用setup.py安装python包和卸载python包的方法
2013/11/27 Python
python格式化字符串实例总结
2014/09/28 Python
Python正则表达式教程之二:捕获篇
2017/03/02 Python
Python多进程multiprocessing用法实例分析
2017/08/18 Python
python matplotlib坐标轴设置的方法
2017/12/05 Python
解决Pandas to_json()中文乱码,转化为json数组的问题
2018/05/10 Python
深入浅析python 中的匿名函数
2018/05/21 Python
Python中反射和描述器总结
2018/09/23 Python
python实现三维拟合的方法
2018/12/29 Python
python实现截取屏幕保存文件,删除N天前截图的例子
2019/08/27 Python
python matplotlib折线图样式实现过程
2019/11/04 Python
python实现图片上添加图片
2019/11/26 Python
viagogo意大利票务平台:演唱会、体育比赛、戏剧门票
2018/01/26 全球购物
获奖的大学生创业计划书
2014/01/05 职场文书
2014统计局民主生活会对照检查材料思想汇报
2014/10/02 职场文书
廉政承诺书
2015/01/19 职场文书
Maven学习----Maven安装与环境变量配置教程
2021/06/29 Java/Android
选购到合适的激光打印机
2022/04/21 数码科技