zoukankan      html  css  js  c++  java
  • node 微信退款

     基于node 的微信退款

    申请微信退款:微信退款

    1.在前端页面访问 /refund

     

    var request = require('request');
    var WxPayRefund = require('./WxPayRefund');
    var config = require('./../config');
    var axios = require('axios')
        /* 退款 */
    const refund = async(ctx, next) => {
        const { request: req, response: res } = ctx
        // 退款 参数
        var RefundInfo = {
            mch_id: config.mch_id, //商户号
            out_refund_no: req.query.out_refund_no, //商户退款单号 //商户系统内部的退款单号(自己生成)
            out_trade_no: req.query.out_trade_no, //商户系统内部订单号
            refund_fee: req.query.refund_fee, //退款金额
            total_fee: req.query.total_fee, //订单金额
        };
        console.log('RefundInfo', RefundInfo);
        // 参数成功回调
        var result = await WxPayRefund.WxPayRefund(RefundInfo).then(function(data) {
            // 成功返回 退款参数
            return JSON.stringify(data);
        });
        ctx.type = 'json';
        ctx.body = result;
    }
    module.exports = { refund };

     

    1.1  WxPayRefund.js

    var express = require('express');
    var request = require('request');
    var Q = require("q");
    var crypto = require('crypto');
    var ejs = require('ejs');
    var fs = require('fs');
    // 需要的参数设置 自行定义
    var config = require("./../config");
    var router = express.Router();
    
    /* 微信 申请 退款 */
    var key = config.key; //此处为申请微信支付的API密码
    var APPID = config.AppID;
    var WxPayRefund = {
        // 生成微信的xml
        getXMLNodeValue: function(node_name, xml) {
            var tmp = xml.split("<" + node_name + ">");
            var _tmp = tmp[1].split("</" + node_name + ">");
            return _tmp[0];
        },
    
        raw: function(args) {
            var keys = Object.keys(args);
            keys = keys.sort()
            var newArgs = {};
            keys.forEach(function(key) {
                newArgs[key] = args[key];
            });
            var string = '';
            for (var k in newArgs) {
                string += '&' + k + '=' + newArgs[k];
            }
            string = string.substr(1);
            return string;
        },
    
        paysignjs: function(appid, nonceStr, package, signType, timeStamp) {
            var ret = {
                appId: appid,
                nonceStr: nonceStr,
                package: package,
                signType: signType,
                timeStamp: timeStamp
            };
            var string = this.raw(ret);
            string = string + '&key=' + key;
            var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
            return sign.toUpperCase();
        },
        //签名
        paysignjsapi: function(appid, mch_id, nonce_str, out_refund_no, out_trade_no, refund_fee, total_fee) {
            var ret = {
                appid: appid,
                mch_id: mch_id,
                nonce_str: nonce_str,
                // notify_url: notify_url,
                out_refund_no: out_refund_no,
                out_trade_no: out_trade_no,
                refund_fee: refund_fee,
                total_fee: total_fee,
            };
            var string = this.raw(ret);
            string = string + '&key=' + key; //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 
            var crypto = require('crypto');
            var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
            return sign.toUpperCase();
        },
    
        // 随机字符串产生函数 
        createNonceStr: function() {
            return Math.random().toString(36).substr(2, 15);
        },
    
        // 时间戳产生函数 
        createTimeStamp: function() {
            return parseInt(new Date().getTime() / 1000) + '';
        },
        // 此处的attach不能为空值 否则微信提示签名错误 
        WxPayRefund: function(_order) {
            var deferred = Q.defer();
            var appid = APPID;
            var nonce_str = this.createNonceStr();
            var timeStamp = this.createTimeStamp();
            var url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; //
            var formData = "<xml>";
            formData += "<appid>" + appid + "</appid>"; // 公众账号ID    appid
            formData += "<mch_id>" + _order.mch_id + "</mch_id>"; // 商户号    mch_id
            formData += "<nonce_str>" + nonce_str + "</nonce_str>"; // 随机字符串
            // formData += "<notify_url>" + _order.notify_url + "</notify_url>"; // 退款结果通知url
            formData += "<out_refund_no>" + _order.out_refund_no + "</out_refund_no>"; // 商户退款单号
            formData += "<out_trade_no>" + _order.out_trade_no + "</out_trade_no>"; //商户系统内部订单号
            formData += "<refund_fee>" + _order.refund_fee + "</refund_fee>"; // 退款金额
            formData += "<total_fee>" + _order.total_fee + "</total_fee>"; // 订单金额
            formData += "<sign>" + this.paysignjsapi(appid, _order.mch_id, nonce_str, _order.out_refund_no, _order.out_trade_no, _order.refund_fee, _order.total_fee) + "</sign>"; // 签名    sign
            formData += "</xml>";
            var self = this;
            request({
                url: url,
                method: 'POST',
                body: formData,
                agentOptions: {
                    pfx: fs.readFileSync(__dirname + './../cert/apiclient_cert.p12'),
                    passphrase: _order.mch_id
                }
            }, function(err, response, body) {
                if (!err && response.statusCode == 200) {
                    console.log('11', body);
                    var data = parser(body);
                    deferred.resolve(data);
                } else {
                    console.log('12', body);
                }
            });
            return deferred.promise;
        },
    };
    
    function parser(_da) {
        var xml = _da;
        xml = xml.slice('<xml>'.length, xml.indexOf('</xml>'));
        var tag = xml.match(/<w+>/g);
        var len = tag.length;
        var obj = new Object(); //将微信 支付成功 返回的 xml 数据处理为json格式
        for (var i = 0; i < len; i++) {
            var node_name = tag[i].replace(/<|>/g, '');
            var tmp = xml.split("<" + node_name + ">");
            var _tmp = tmp[1].split("</" + node_name + ">");
            var result = _tmp[0];
            if (result.match(/^(?!.*CDATA)/)) {
                obj[node_name] = result;
            } else {
                obj[node_name] = result.split('[')[2].split(']')[0];
            }
        }
        return obj;
    }
    module.exports = WxPayRefund;

     在这里再次感谢在人生路上帮助我的人!谢谢你们。

    如果以上代码对您有用,欢迎打赏!如有错误的地方也请您留言指出。

  • 相关阅读:
    SSH框架总结(框架分析+环境搭建+实例源码下载)(转)
    用PowerMockito来mock私有方法(转)
    Mockito简介(转)
    统治世界的十大算法
    ThreadLocal用法和实现原理(转)
    在Eclipse中使用JUnit4进行单元測试(0基础篇)
    libgdx, mouse 关节
    sprintf,你知道多少?
    北京簋街 美食全然攻略 + 簋街好吃的夜宵去处-----店铺介绍大全
    codeforces-148D-Bag of mice-概率DP
  • 原文地址:https://www.cnblogs.com/jimmy1293/p/8980757.html
Copyright © 2011-2022 走看看