基于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 相关文章推荐
10款新鲜出炉的 jQuery 插件(Ajax 插件,有幻灯片、图片画廊、菜单等)
Jun 08 Javascript
js DOM的学习笔记
Dec 22 Javascript
JQGrid的用法解析(列编辑,添加行,删除行)
Nov 08 Javascript
EasyUI中combobox默认值注意事项
Mar 01 Javascript
基于JavaScript实现在新的tab页打开url
Aug 04 Javascript
jQuery扩展实现text提示还能输入多少字节的方法
Nov 28 Javascript
加载 vue 远程代码的组件实例详解
Nov 20 Javascript
js 公式编辑器 - 自定义匹配规则 - 带提示下拉框 - 动态获取光标像素坐标
Jan 04 Javascript
mpvue中配置vuex并持久化到本地Storage图文教程解析
Mar 15 Javascript
详解新手使用vue-router传参时注意事项
Jun 06 Javascript
详解JavaScript执行模型
Nov 16 Javascript
Vue全家桶入门基础教程
May 14 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
短波的认识
2021/03/01 无线电
PHP在特殊字符前加斜杠的实现代码
2011/07/17 PHP
ajax完美实现两个网页 分页功能的实例代码
2013/04/16 PHP
详解php中生成标准uuid(guid)的方法
2019/04/28 PHP
brook javascript框架介绍
2011/10/10 Javascript
开发 Internet Explorer 右键功能表(ContextMenu)
2013/07/03 Javascript
Node.js中的模块机制学习笔记
2014/11/04 Javascript
浅谈node.js中async异步编程
2015/10/22 Javascript
基于jQuery Tipso插件实现消息提示框特效
2016/03/16 Javascript
JS中正则表达式只有3种匹配模式(没有单行模式)详解
2016/07/28 Javascript
JavaScript与ActionScript3两者的同性与差异性
2016/09/22 Javascript
jQuery Ajax传值到Servlet出现乱码问题的解决方法
2016/10/09 Javascript
Angular实现购物车计算示例代码
2017/02/21 Javascript
Google 爬虫如何抓取 JavaScript 的内容
2017/04/07 Javascript
JavaScript实现百度搜索框效果
2020/03/26 Javascript
Angular5.0 子组件通过service传递值给父组件的方法
2018/07/13 Javascript
Vue filter格式化时间戳时间成标准日期格式的方法
2018/09/16 Javascript
vue 音乐App QQ音乐搜索列表最新接口跨域设置方法
2018/09/25 Javascript
js常用方法、检查是否有特殊字符串、倒序截取字符串操作完整示例
2020/01/26 Javascript
仿照Element-ui实现一个简易的$message方法
2020/09/14 Javascript
python利用dir函数查看类中所有成员函数示例代码
2017/09/08 Python
python字符串与url编码的转换实例
2018/05/10 Python
Python实现K折交叉验证法的方法步骤
2019/07/11 Python
python BlockingScheduler定时任务及其他方式的实现
2019/09/19 Python
教师师德教育的自我评价
2013/10/31 职场文书
医德医风自我评价
2014/09/19 职场文书
乡镇领导干部个人对照检查材料思想汇报
2014/09/23 职场文书
机关干部四风问题自我剖析及整改措施
2014/10/26 职场文书
2014学生会工作总结报告
2014/12/02 职场文书
2014年技术部工作总结
2014/12/12 职场文书
材料采购员岗位职责
2015/04/03 职场文书
销售内勤岗位职责范本
2015/04/13 职场文书
2015年资料员工作总结
2015/04/25 职场文书
三好学生主要事迹怎么写
2015/11/03 职场文书
基于Pygame实现简单的贪吃蛇游戏
2021/12/06 Python
2021好看的国漫排行榜前十名 《完美世界》上榜,《元龙》排名第一
2022/03/18 国漫