WeChat public account has been transferred to WeChat built-in browser h5 payment

(1) WeChat official account and WeChat merchant platform configuration

Configure according to the tutorial on the WeChat public platform

 

 

1. Set up payment directory

Please make sure that the requested directory during the actual payment is consistent with the directory configured in the background, otherwise the WeChat payment will not be able to be invoked successfully.

Set your official account payment directory on the WeChat merchant platform (pay.weixin.qq.com), and set the path: merchant platform --> product center --> development configuration, as shown in Figure 7.7. The official account payment will verify whether the request source has been configured on the merchant platform when requesting payment, so you must ensure that the payment directory has been configured correctly, otherwise the verification will fail and the payment request will not succeed.

Payment directory configuration

Figure 7.7 WeChat Official Account Payment-Payment Directory Configuration

2. Set authorized domain name

When developing official account payment, the user’s openid must be transmitted in the unified order interface, and to obtain openid, you need to set the domain name for obtaining openid on the public platform. Only the domain name that has been set is a valid domain name for obtaining openid, otherwise Will get failed. The specific interface is shown in Figure 7.8:

Authorized domain name of WeChat webpageAuthorized domain name of WeChat webpage

Figure 7.8 WeChat webpage authorized domain name settings

 

Three, configure the merchant secret key key

 

Reference article https://jingyan.baidu.com/article/75ab0bcbbf7034d6864db2c3.html

Note that after configuring the secret key, you must save the secret key yourself, and you cannot view the secret key on the merchant platform. The following signature algorithm requires the merchant secret key.

(Two) unified order

One, configuration and parameters

Refer to the documentation, the things to note are:

1. The callback address notify_url of WeChat payment result notification must be port 80, if it is not port 80, it can be reverse proxy through nginx

2. Transaction type here is the official account payment, fill in JSAPI

3.openid, when the official account payment is trade_type=JSAPI, this parameter must be passed, this parameter is the openid obtained after the front-end WeChat login

Second, the code implementation

1. Nodejs as the background to achieve a unified order interface

 

h5_order: function(attach, body, mch_id, openid, out_trade_no, total_fee, notify_url,spbill_create_ip,scene_info) {
    var deferred = Q.defer();
    var appid = "wx4280cd3b0ecf2a38";//"wx7df91d705b3f0a15";   // h5的appid
    var nonce_str = this.createNonceStr();
    var trade_type = "JSAPI";
    var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    var spbill_create_ip = "115.192.87.205";//写死了这边
    var formData = "<xml>";
    formData += "<appid>" + appid + "</appid>"; //appid  必填
    //formData += "<attach>" + attach + "</attach>"; //附加数据
    formData += "<body>" + body + "</body>";   //必填
    formData += "<mch_id>" + mch_id + "</mch_id>"; //商户号  //必填
    formData += "<nonce_str>" + nonce_str + "</nonce_str>"; //随机字符串,不长于32位。 //必填
    formData += "<notify_url>" + notify_url + "</notify_url>";  //必填
    formData += "<openid>" + openid + "</openid>";
    formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>";  //必填
    formData += "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>";  //IP地址需要动态获取 //必填
    formData += "<total_fee>" + total_fee + "</total_fee>";  //必填
    formData += "<trade_type>" + trade_type + "</trade_type>";  //必填
    //formData += "<sign>" + this.getSign(appid, mch_id, "", body, nonce_str) + "</sign>";  //  getSign: function(appid, mch_id, device_info, body, nonce_str) {
    //formData += "<scene_info>" + JSON.stringify(scene_info) + "</scene_info>";
    formData += "<sign>" + this.signOne(appid, attach, body, mch_id, nonce_str, notify_url, openid, out_trade_no, spbill_create_ip, total_fee, "JSAPI") + "</sign>";
    formData += "</xml>";

    //console.log("formData:"+formData);
    var self = this;
    request({
        url: url,
        method: 'POST',
        body: formData
    }, function(err, response, body) {
        if (!err && response.statusCode == 200) {
            console.log(body);
            var parser = new xml2js.Parser({ trim:true, explicitArray:false, explicitRoot:false });//解析签名结果xml转json
            parser.parseString(body, function(err, result){
                var prepay_id = result['prepay_id'];
                var timeStamp = self.createTimeStamp();
                var package="prepay_id="+prepay_id;
                var _paySignjs = self.signTwoH5(appid, nonce_str, package,timeStamp,"MD5");
                var args = {
                    appId: appid,
                    package: package,
                    timeStamp: timeStamp,
                    nonceStr: nonce_str,
                    paySign: _paySignjs
                };
                //console.log("进行二次签名后数据", args);
                deferred.resolve(args);
            });
        } else {
            console.log(body);
        }
    });
    return deferred.promise;
},

2. Signature function signOne:

 

signOne: function(appid, attach, body, mch_id, nonce_str, notify_url, openid, out_trade_no, spbill_create_ip, total_fee, trade_type) {
    //参数名ASCII码从小到大排序(字典序)
    var ret = {
        appid: appid,//ok
        //attach: attach,
        body: body,//ok
        mch_id: mch_id,//ok
        nonce_str: nonce_str,//ok
        notify_url: notify_url,
        openid: openid,
        out_trade_no: out_trade_no,
        spbill_create_ip: spbill_create_ip,
        total_fee: total_fee,
        trade_type: trade_type    //类型
    };
    var string = this.raw(ret);
    string = string + '&key=' + key; //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
    console.log("signOne string:"+string);
    var crypto = require('crypto');
    var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');//md5加密操作
    return sign.toUpperCase();//转换成大写字母
},
 
//拼接
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;
}

2. Signature function signTwoH5:

 

signTwoH5: function(appid, nonceStr, package,timestamp,signType) {
    var ret = {
        appId: appid,
        nonceStr: nonceStr,
        package: package,
        timeStamp: timestamp,
        signType:signType,
    };

    var string = this.raw(ret);
    string = string + '&key=' + key;
    console.log("signTwo string:  " + string);

    var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
    return sign.toUpperCase();
}

3. Generate timestamp and random string function

 

// 随机字符串产生函数
createNonceStr: function() {
    return Math.random().toString(36).substr(2, 15);
},

// 时间戳产生函数
createTimeStamp: function() {
    return parseInt(new Date().getTime() / 1000) + '';
},

4. The server generates the pre-payment order number and other information and sends it to the front-end, and the front-end WeChat built-in browser invokes the payment code as follows:

 

                    function onBridgeReady () {
 
alert( JSON. stringify( args));
WeixinJSBridge . The Invoke (
'getBrandWCPayRequest', {
"appId" :args . appId , // Official account name, passed in by the merchant
"timeStamp" : String ( args . timeStamp ), //Time stamp, the number of seconds since 1970
"nonceStr" :args . nonceStr , //random string
"package" :args. package,
"signType" : "MD5" , //WeChat signature method:
"paySign" :args . paySign //WeChat signature
},
function( res){
 
if ( res . err_msg == "get_brand_wcpay_request:ok" ) { // Use the above method to determine the front-end return, the WeChat team solemnly reminds: res.err_msg will return ok after the user has successfully paid, but it does not guarantee that it is absolutely reliable.
if( callback){
callback( 0);
}
} else if( res. err_msg == "get_brand_wcpay_request:cancel"){
if( callback){
callback( 1);
}
} else{
alert( JSON. stringify( res));
if ( callback ){
callback(- 1);
}
}
 
 
}
);
}
if ( typeof WeixinJSBridge == "undefined"){
if( document. addEventListener ){
document. addEventListener( 'WeixinJSBridgeReady', onBridgeReady, false);
} else if ( document. attachEvent){
document. attachEvent( 'WeixinJSBridgeReady', onBridgeReady);
document. attachEvent( 'onWeixinJSBridgeReady', onBridgeReady);
}
} else{
 
onBridgeReady();
}

Any error messages can be printed out with alert(JSON.stringify(res))

Guess you like

Origin blog.csdn.net/wdglhack/article/details/80089674
Recommended