有关 node.js 达成微信支付退款功能的实现方式

why 189 2024-08-20

这篇文章主要介绍了node.js实现微信支付退款功能,在微信开发中有有付款就会有退款,这样的功能非常常见,需要的朋友可以参考下

有付款就会有退款

注意,退款支持部分退款

左口袋的钱退到右口袋罗

image.png 

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

引入第三方module

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

代码目录结构

image.png 

入参


1

2

3

4

5

6

7

8

{ 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的源码


1

2

3

4

5

6

7

8

9

10

11

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工具类

用于验证与错误回调


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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调起就可以了,成功就把订单状态改成"退款成功"


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

// 退款

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不匹配'原来是小程序还没绑定公众号微信支付,这真是一个乌龙。

成功退款微信返回的数据


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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”


重复退款将返回如下


1

2

3

4

5

6

7

8

9

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”


image.png 

最后

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

以上就是本文的全部内容,希望对大家的学习有所帮助。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微信小程序里 input 表单、redio 及下拉列表的使用方法
下一篇:微信小程序中开发快递查询功能的详细介绍
相关文章

 发表评论

暂时没有评论,来抢沙发吧~