微信小程序接入微信支付(node后端)

微信小程序接入微信支付

现在小程序越来越流行起来,微信小程序的开发也在不断的完善,现在我们就来讲讲微信小程序如何接入微信支付。

微信小程序发起微信支付API接口

我们在微信官方的开发文档中可以查到微信小程序的支付接口wx.requestPayment(Object object),在里面可以查到必填的参数和格式等。
实例代码:

wx.requestPayment({
  timeStamp: '', // 时间戳,从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间
  nonceStr: '', // 随机字符串,长度为32个字符以下
  package: '', // 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
  signType: 'MD5',
  paySign: '', // 签名,具体签名方案参见 小程序支付接口文档
  success(res) { }, // 接口调用成功的回调函数
  fail(res) { } // 接口调用失败的回调函数
})

object.signType 的合法值----MD5或者HMAC-SHA256

当然这些参数都是需要自己后端(node)处理后得到参数,传回微信小程序的。

微信支付接口文档

发起微信支付。了解更多信息,请查看微信支付接口文档

商户系统(node后端)和微信支付系统主要交互

  1. 小程序内调用登录接口,获取到用户的openid,api参见公共api;
  2. 商户server调用支付统一下单,api参见公共api
  3. 商户server调用再次签名,api参见公共api
  4. 商户server接收支付通知,api参见公共api
  5. 商户server查询支付结果,api参见公共api

主要是签名生成算法,算法实例如下面的node代码实例中的函数getSign(signParams)

node后端示例代码

/*
* @Author: zhangyong
* @Date:   2018-04-17
* @Descrition : wechat 微信支付功能
*/

var queryString = require('querystring');
var crypto = require('crypto');
var request = require('request');
var uuid = require('uuid');
var sql = require('./assets/sql/sql')
var xml2jsparseString = require('xml2js').parseString;
// 引入项目的配置信息
const CONFIG = require('../config')
var config = CONFIG.app_info;

// wechat 支付类 (使用 es6 的语法)
class WechatAppletPay {
    /**
     * 构造函数
     * @param params 传递进来的方法
     */
    constructor( userInfo ){
        this.userInfo = userInfo;
        this.order_id = "";
    }

    /**
     * 获取微信统一下单参数
     */
    getUnifiedorderXmlParams(obj){

        var body = '<xml> ' +
            '<appid>'+config.wxappid+'</appid> ' +
            '<body>'+obj.body+'</body> ' +
            '<mch_id>'+config.mch_id+'</mch_id> ' +
            '<nonce_str>'+obj.nonce_str+'</nonce_str> ' +
            '<notify_url>'+obj.notify_url+'</notify_url>' +
            '<openid>'+obj.openid+'</openid> ' +
            '<out_trade_no>'+obj.out_trade_no+'</out_trade_no>'+
            '<spbill_create_ip>'+obj.spbill_create_ip+'</spbill_create_ip> ' +
            '<total_fee>'+obj.total_fee+'</total_fee> ' +
            '<trade_type>'+obj.trade_type+'</trade_type> ' +
            '<sign>'+obj.sign+'</sign> ' +
            '</xml>';
        return body;
    }

    /**
     * 获取微信统一下单的接口数据
     */
    getPrepayId(obj){
        var that = this;
        // 生成统一下单接口参数
        var UnifiedorderParams = {
            appid : config.wxappid,
            body : obj.bookid,
            mch_id : config.mch_id,
            nonce_str: this.createNonceStr(),
            notify_url : obj.notify_url,// 微信付款后的回调地址
            openid : this.userInfo.openid,
            out_trade_no : uuid.v4().replace(/-/g,''),//new Date().getTime(), //订单号
            spbill_create_ip : obj.spbill_create_ip,
            total_fee : obj.total_fee,
            trade_type : 'JSAPI'
        };
        that.order_id = UnifiedorderParams.out_trade_no;
        // 返回 promise 对象
        return  new Promise(function (resolve, reject) {
            // 获取 sign 参数
            UnifiedorderParams.sign = that.getSign(UnifiedorderParams);
            var url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
            request.post({url : url, body:JSON.stringify(that.getUnifiedorderXmlParams(UnifiedorderParams))}, function (error, response, body) {
                var prepay_id = '';
                if (!error && response.statusCode == 200) {
                    // 微信返回的数据为 xml 格式, 需要装换为 json 数据, 便于使用
                    xml2jsparseString(body, {async:true}, function (error, result) {
                        prepay_id = result.xml.prepay_id[0];
                        // 放回数组的第一个元素
                        resolve(prepay_id);
                    });
                } else {
                    reject(body);
                }
            });
        })
    }

    /**
     * 获取微信支付的签名
     * @param payParams
     */
    getSign(signParams){
        // 按参数名ASCII码从小到大排序
        var keys = Object.keys(signParams);
        keys = keys.sort();
        var newArgs = {};
        keys.forEach(function (val, key) {
            if (signParams[val]){
                newArgs[val] = signParams[val];
            }
        })
        // 拼接API密钥
        var string = queryString.stringify(newArgs)+'&key='+config.wxpaykey;
        // 生成签名
        return crypto.createHash('md5').update(queryString.unescape(string), 'utf8').digest("hex").toUpperCase();
    }

    /**
     * 微信支付的所有参数
     * @param req 请求的资源, 获取必要的数据
     */
    getBrandWCPayParams( obj, callback ){
        var that = this;
        var prepay_id_promise = that.getPrepayId(obj);
        prepay_id_promise.then(function (prepay_id) {
            var prepay_id = prepay_id;
            var wcPayParams = {
                "appId" : config.wxappid,     // 微信小程序的APPID
                "timeStamp" : parseInt(new Date().getTime() / 1000).toString(),         //时间戳,自1970年以来的秒数
                "nonceStr" : that.createNonceStr(), // 随机串
                // 通过统一下单接口获取
                "package" : "prepay_id="+prepay_id,
                "signType" : "MD5",         // 微信签名方式:
            };
            wcPayParams.paySign = that.getSign(wcPayParams); //微信支付签名
            wcPayParams.order_id = that.order_id; //微信支订单号
            callback(wcPayParams);
        },function (error) {
            callback(error);
        });
    }

    /**
     * 获取随机的NonceStr
     */
    createNonceStr() {
        return Math.random().toString(36).substr(2, 15);
    };

}

module.exports = WechatAppletPay;

调用WechatAppletPay方法

var WechatAppletPay= new WechatAppletPay(userInfo);
WechatAppletPay.getBrandWCPayParams(req.body, function (data) {
    console.log(data);
})

没有更多推荐了,返回首页