基于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 相关文章推荐
JQuery扩展插件Validate 2通过参数设置验证规则
Sep 05 Javascript
js控制的回到页面顶端goTop的代码实现
Mar 20 Javascript
js跨域访问示例(客户端/服务端)
May 19 Javascript
浅谈Javascript中的Function与Object
Jan 26 Javascript
ajax的分页查询示例(不刷新页面)
Jan 11 Javascript
最常用的jQuery表单验证(简单)
May 23 jQuery
JS中Map和ForEach的区别
Feb 05 Javascript
ES6 更易于继承的类语法的使用
Feb 11 Javascript
angularjs1.X 重构controller 的方法小结
Aug 15 Javascript
基于axios 的responseType类型的设置方法
Oct 29 Javascript
Vue自定义指令结合阿里云OSS优化图片的实现方法
Nov 12 Javascript
2019年度web前端面试题总结(主要为Vue面试题)
Jan 12 Javascript
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自定义函数判断是否为Get、Post及Ajax提交的方法
2017/07/27 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
教您去掉ie网页加载进度条的方法
2010/12/09 Javascript
jquery validate poshytip 自定义样式
2012/11/26 Javascript
js脚本分页代码分享(7种样式)
2015/08/19 Javascript
浅谈js之字面量、对象字面量的访问、关键字in的用法
2016/11/20 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
2017/01/11 Javascript
template.js前端模板引擎使用详解
2017/10/10 Javascript
vue2.0实现音乐/视频播放进度条组件
2018/06/06 Javascript
tracking.js页面人脸识别插件使用方法
2020/04/16 Javascript
NodeJS读取分析Nginx错误日志的方法
2019/05/14 NodeJs
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
浅谈vue 组件中的setInterval方法和window的不同
2020/07/30 Javascript
vue打开其他项目页面并传入数据详解
2020/11/25 Vue.js
python更新列表的方法
2015/07/28 Python
Python selenium 三种等待方式详解(必会)
2016/09/15 Python
Python数据分析之如何利用pandas查询数据示例代码
2017/09/01 Python
Python基于分水岭算法解决走迷宫游戏示例
2017/09/26 Python
Python字符串格式化%s%d%f详解
2018/02/02 Python
Python进阶之全面解读高级特性之切片
2019/02/19 Python
Python Excel处理库openpyxl使用详解
2019/05/09 Python
Python面向对象之继承和多态用法分析
2019/06/08 Python
Python多线程爬取豆瓣影评API接口
2019/10/22 Python
python 实现人和电脑猜拳的示例代码
2020/03/02 Python
HTML5拖放API实现拖放排序的实例代码
2017/05/11 HTML / CSS
一套带答案的C++笔试题
2014/01/10 面试题
女娲补天教学反思
2014/02/05 职场文书
计算机专业自荐信
2014/05/24 职场文书
工地宣传标语
2014/06/18 职场文书
本科应届生求职信
2014/08/05 职场文书
文明倡议书
2015/01/19 职场文书
岗位职责范本大全
2015/02/26 职场文书
2015年财政局工作总结
2015/05/21 职场文书
队列队形口号
2015/12/25 职场文书
go类型转换及与C的类型转换方式
2021/05/05 Golang
上帝为你开了一扇窗之Tkinter常用函数详解
2021/06/02 Python