基于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 实现窗口滚动搜索框停靠效果(类似滚动停靠)
Mar 27 Javascript
Javascript中this的用法详解
Sep 22 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
Jan 23 Javascript
js实现背景图片感应鼠标变化的方法
Feb 28 Javascript
深入分析下javascript中的[]()+!
Jul 07 Javascript
JavaScript对HTML DOM使用EventListener进行操作
Oct 21 Javascript
js实现四舍五入完全保留两位小数的方法
Aug 02 Javascript
jquery操作checkbox火狐下第二次无法勾选的解决方法
Oct 10 Javascript
jQuery实现的省市联动菜单功能示例【测试可用】
Jan 13 Javascript
解决Layui 表单提交数据为空的问题
Aug 15 Javascript
vue1.0和vue2.0的watch监听事件写法详解
Sep 11 Javascript
JavaScript从原型到原型链深入理解
Jun 03 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
是否存在第一台收音机的说法
2021/03/01 无线电
什么是短波收听SWL
2021/03/01 无线电
discuz程序的PHP加密函数原理分析
2011/08/05 PHP
php使用mkdir创建多级目录入门例子
2014/05/10 PHP
php生成PDF格式文件并且加密
2015/06/22 PHP
javascript 静态对象和构造函数的使用和公私问题
2010/03/02 Javascript
用JQUERY增删元素的代码
2012/02/14 Javascript
jquery+css+ul模拟列表菜单具体实现思路
2013/04/15 Javascript
下拉菜单点击实现连接跳转功能的js代码
2013/05/19 Javascript
JS实现倒计时和文字滚动的效果实例
2014/10/29 Javascript
拥有一个属于自己的javascript表单验证插件
2016/03/24 Javascript
React实现双向绑定示例代码
2016/09/19 Javascript
js实现简单的选项卡效果
2017/02/23 Javascript
详解Angular Reactive Form 表单验证
2017/07/06 Javascript
jQuery HTML设置内容和属性操作实例分析
2020/05/20 jQuery
[03:03]DOTA2 2017国际邀请赛开幕战队入场仪式
2017/08/09 DOTA
PYTHON正则表达式 re模块使用说明
2011/05/19 Python
Python查找相似单词的方法
2015/03/05 Python
分析Python编程时利用wxPython来支持多线程的方法
2015/04/07 Python
在Python的web框架中配置app的教程
2015/04/30 Python
Python3连接SQLServer、Oracle、MySql的方法
2018/06/28 Python
Python中return self的用法详解
2018/07/27 Python
不管你的Python报什么错,用这个模块就能正常运行
2018/09/14 Python
Python面向对象程序设计多继承和多态用法示例
2019/04/08 Python
Django Celery异步任务队列的实现
2019/07/24 Python
M1芯片安装python3.9.1的实现
2021/02/02 Python
如何用 Python 制作 GitHub 消息助手
2021/02/20 Python
CSS3 开发工具收集
2010/04/17 HTML / CSS
eBay比利时购物网站:eBay.be
2019/08/09 全球购物
创业计划书撰写原则
2014/01/25 职场文书
互联网电子商务专业毕业生求职信
2014/03/18 职场文书
人间正道是沧桑观后感
2015/06/15 职场文书
2019商业计划书格式、范文
2019/04/24 职场文书
PHP实现两种排课方式
2021/06/26 PHP
详解Oracle数据库中自带的所有表结构(sql代码)
2021/11/20 Oracle
Zabbix对Kafka topic积压数据监控的问题(bug优化)
2022/07/07 Servers