CocosCreator H5 微信内置浏览器调起微信支付

CocosCreator H5 微信内置浏览器调起微信支付

先来看看效果图

这里写图片描述

微信公众平台相关文档传送门https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

下面来实现h5支付的功能(使用的CocosCreator)

  1. 引用jssdk.js文件
    在构建的web-mobile/index.html中添加
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
  1. 初始化jssdk
//这里的ticket是公众号用于调用微信JS接口的临时票据,正常情况下,ticket的有效期为7200秒,通过access_token来获取。由于获取ticket的api调用次数非常有限,频繁刷新ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存ticket 。
//这个ticket需要让服务器提供
//顺便在里面加了一个自定义分享的实现
initConfig : function (ticket) {
        var CryptoJS = CryptoJS || function (e, m) {
            var p = {}, j = p.lib = {}, l = function () { }, f = j.Base = { extend: function (a) { l.prototype = this; var c = new l; a && c.mixIn(a); c.hasOwnProperty("init") || (c.init = function () { c.$super.init.apply(this, arguments) }); c.init.prototype = c; c.$super = this; return c }, create: function () { var a = this.extend(); a.init.apply(a, arguments); return a }, init: function () { }, mixIn: function (a) { for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]); a.hasOwnProperty("toString") && (this.toString = a.toString) }, clone: function () { return this.init.prototype.extend(this) } },
                n = j.WordArray = f.extend({
                    init: function (a, c) { a = this.words = a || []; this.sigBytes = c != m ? c : 4 * a.length }, toString: function (a) { return (a || h).stringify(this) }, concat: function (a) { var c = this.words, q = a.words, d = this.sigBytes; a = a.sigBytes; this.clamp(); if (d % 4) for (var b = 0; b < a; b++)c[d + b >>> 2] |= (q[b >>> 2] >>> 24 - 8 * (b % 4) & 255) << 24 - 8 * ((d + b) % 4); else if (65535 < q.length) for (b = 0; b < a; b += 4)c[d + b >>> 2] = q[b >>> 2]; else c.push.apply(c, q); this.sigBytes += a; return this }, clamp: function () {
                        var a = this.words, c = this.sigBytes; a[c >>> 2] &= 4294967295 <<
                            32 - 8 * (c % 4); a.length = e.ceil(c / 4)
                    }, clone: function () { var a = f.clone.call(this); a.words = this.words.slice(0); return a }, random: function (a) { for (var c = [], b = 0; b < a; b += 4)c.push(4294967296 * e.random() | 0); return new n.init(c, a) }
                }), b = p.enc = {}, h = b.Hex = {
                    stringify: function (a) { var c = a.words; a = a.sigBytes; for (var b = [], d = 0; d < a; d++) { var f = c[d >>> 2] >>> 24 - 8 * (d % 4) & 255; b.push((f >>> 4).toString(16)); b.push((f & 15).toString(16)) } return b.join("") }, parse: function (a) {
                        for (var c = a.length, b = [], d = 0; d < c; d += 2)b[d >>> 3] |= parseInt(a.substr(d,
                            2), 16) << 24 - 4 * (d % 8); return new n.init(b, c / 2)
                    }
                }, g = b.Latin1 = { stringify: function (a) { var c = a.words; a = a.sigBytes; for (var b = [], d = 0; d < a; d++)b.push(String.fromCharCode(c[d >>> 2] >>> 24 - 8 * (d % 4) & 255)); return b.join("") }, parse: function (a) { for (var c = a.length, b = [], d = 0; d < c; d++)b[d >>> 2] |= (a.charCodeAt(d) & 255) << 24 - 8 * (d % 4); return new n.init(b, c) } }, r = b.Utf8 = { stringify: function (a) { try { return decodeURIComponent(escape(g.stringify(a))) } catch (c) { throw Error("Malformed UTF-8 data"); } }, parse: function (a) { return g.parse(unescape(encodeURIComponent(a))) } },
                k = j.BufferedBlockAlgorithm = f.extend({
                    reset: function () { this._data = new n.init; this._nDataBytes = 0 }, _append: function (a) { "string" == typeof a && (a = r.parse(a)); this._data.concat(a); this._nDataBytes += a.sigBytes }, _process: function (a) { var c = this._data, b = c.words, d = c.sigBytes, f = this.blockSize, h = d / (4 * f), h = a ? e.ceil(h) : e.max((h | 0) - this._minBufferSize, 0); a = h * f; d = e.min(4 * a, d); if (a) { for (var g = 0; g < a; g += f)this._doProcessBlock(b, g); g = b.splice(0, a); c.sigBytes -= d } return new n.init(g, d) }, clone: function () {
                        var a = f.clone.call(this);
                        a._data = this._data.clone(); return a
                    }, _minBufferSize: 0
                }); j.Hasher = k.extend({
                    cfg: f.extend(), init: function (a) { this.cfg = this.cfg.extend(a); this.reset() }, reset: function () { k.reset.call(this); this._doReset() }, update: function (a) { this._append(a); this._process(); return this }, finalize: function (a) { a && this._append(a); return this._doFinalize() }, blockSize: 16, _createHelper: function (a) { return function (c, b) { return (new a.init(b)).finalize(c) } }, _createHmacHelper: function (a) {
                        return function (b, f) {
                            return (new s.HMAC.init(a,
                                f)).finalize(b)
                        }
                    }
                }); var s = p.algo = {}; return p
        }(Math);
        (function () {
            var e = CryptoJS, m = e.lib, p = m.WordArray, j = m.Hasher, l = [], m = e.algo.SHA1 = j.extend({
                _doReset: function () { this._hash = new p.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (f, n) {
                    for (var b = this._hash.words, h = b[0], g = b[1], e = b[2], k = b[3], j = b[4], a = 0; 80 > a; a++) {
                        if (16 > a) l[a] = f[n + a] | 0; else { var c = l[a - 3] ^ l[a - 8] ^ l[a - 14] ^ l[a - 16]; l[a] = c << 1 | c >>> 31 } c = (h << 5 | h >>> 27) + j + l[a]; c = 20 > a ? c + ((g & e | ~g & k) + 1518500249) : 40 > a ? c + ((g ^ e ^ k) + 1859775393) : 60 > a ? c + ((g & e | g & k | e & k) - 1894007588) : c + ((g ^ e ^
                            k) - 899497514); j = k; k = e; e = g << 30 | g >>> 2; g = h; h = c
                    } b[0] = b[0] + h | 0; b[1] = b[1] + g | 0; b[2] = b[2] + e | 0; b[3] = b[3] + k | 0; b[4] = b[4] + j | 0
                }, _doFinalize: function () { var f = this._data, e = f.words, b = 8 * this._nDataBytes, h = 8 * f.sigBytes; e[h >>> 5] |= 128 << 24 - h % 32; e[(h + 64 >>> 9 << 4) + 14] = Math.floor(b / 4294967296); e[(h + 64 >>> 9 << 4) + 15] = b; f.sigBytes = 4 * e.length; this._process(); return this._hash }, clone: function () { var e = j.clone.call(this); e._hash = this._hash.clone(); return e }
            }); e.SHA1 = j._createHelper(m); e.HmacSHA1 = j._createHmacHelper(m)
        })();
        var data = new Date();
        var timestamp = data.getTime() + "";
        var nonceStr = Math.random() * 1000 + "";
        var url = location.href.split('#')[0];
        var string = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;

        var signature = CryptoJS.SHA1(string, { string: true }).toString()
        if(typeof(wx)=="undefined"){ 
            return;
        }
        wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: HeadDefine.appid, // 必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: nonceStr, // 必填,生成签名的随机串
            signature: signature,// 必填,签名,见附录1
            jsApiList: [
                "onMenuShareTimeline",
                "onMenuShareAppMessage",
                "chooseWXPay",
            ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });
        wx.ready(function () {
            // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
            wx.onMenuShareAppMessage({
                title: "", // 分享标题
                desc: "", // 分享描述
                link:location.href.split('#')[0], // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                imgUrl: "", // 分享图标
                type: 'link', // 分享类型,music、video或link,不填默认为link
                dataUrl: "", // 如果type是music或video,则要提供数据链接,默认为空
                success: function () {
                    // 用户确认分享后执行的回调函数

                },
                cancel: function () {
                    // 用户取消分享后执行的回调函数

                }
            });
        }.bind(this));
        wx.error(function (res) {

            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
        });
    }
  1. 调用支付接口(直接把代码放到用户点击按钮购买的地方就可以)
var appId = "xxx";//公众号appId
var timestamp = new Date().getTime().toString();//支付签名时间戳
var nonceStr = (Math.random() * 1000).toString();// 支付签名随机串
//prepayId : 这个参数是服务器获取的微信统一下单号
var prepay_id = 'prepay_id=' + prepayId;// 统一支付接口返回的prepay_id参数值
var signType = 'MD5';// 签名方式
//生成签名的规则我就不多说了,直接看文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
var stringA = "appId=" + appId + "&nonceStr=" + nonceStr + "&package=" + prepay_id + "&signType=" + signType + "&timeStamp=" + timestamp;
var stringSignTemp = stringA + "&key=xxxxxx" //注:key为商户平台设置的密钥key
//utilMd5:是一个网上要的md5js文件,在后面会上传
var sign = utilMd5.hexMD5(stringSignTemp).toUpperCase();//注:MD5签名方式
//WeixinJSBridge : 微信内置对象在其他浏览器中无效。
WeixinJSBridge.invoke(
    'getBrandWCPayRequest', {
           "appId": appId,     //公众号名称,由商户传入     
           "timeStamp": timestamp,         //时间戳,自1970年以来的秒数     
           "nonceStr": nonceStr, //随机串     
           "package": prepay_id,
           "signType": signType,         //微信签名方式:     
           "paySign": sign //微信签名 
     },
     function (res) {
           // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 
           if (res.err_msg == "get_brand_wcpay_request:ok"){
               alert("充值成功");
           } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
               alert("取消成功");
           } else {
               alert(res.err_msg);
           }
    }
);

utilMd5.js

/* 
 1. A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 
 2. Digest Algorithm, as defined in RFC 1321. 
 3. Version 1.1 Copyright (C) Paul Johnston 1999 - 2002. 
 4. Code also contributed by Greg Holt 
 5. See http://pajhome.org.uk/site/legal.html for details. 
 */ 

/* 
 6. Add integers, wrapping at 2^32. This uses 16-bit operations internally 
 7. to work around bugs in some JS interpreters. 
 */ 
function safe_add(x, y)  
{  
 var lsw = (x & 0xFFFF) + (y & 0xFFFF)  
 var msw = (x >> 16) + (y >> 16) + (lsw >> 16)  
 return (msw << 16) | (lsw & 0xFFFF)  
}  

/* 
 8. Bitwise rotate a 32-bit number to the left. 
 */ 
function rol(num, cnt)  
{  
 return (num << cnt) | (num >>> (32 - cnt))  
}  

/* 
 9. These functions implement the four basic operations the algorithm uses. 
 */ 
function cmn(q, a, b, x, s, t)  
{  
 return safe_add(rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)  
}  
function ff(a, b, c, d, x, s, t)  
{  
 return cmn((b & c) | ((~b) & d), a, b, x, s, t)  
}  
function gg(a, b, c, d, x, s, t)  
{  
 return cmn((b & d) | (c & (~d)), a, b, x, s, t)  
}  
function hh(a, b, c, d, x, s, t)  
{  
 return cmn(b ^ c ^ d, a, b, x, s, t)  
}  
function ii(a, b, c, d, x, s, t)  
{  
 return cmn(c ^ (b | (~d)), a, b, x, s, t)  
}  

/* 
 10. Calculate the MD5 of an array of little-endian words, producing an array 
 11. of little-endian words. 
 */ 
function coreMD5(x)  
{  
 var a = 1732584193  
 var b = -271733879  
 var c = -1732584194  
 var d = 271733878  

 for(var i = 0; i < x.length; i += 16)  
 {  
  var olda = a  
  var oldb = b  
  var oldc = c  
  var oldd = d  

  a = ff(a, b, c, d, x[i+ 0], 7 , -680876936)  
  d = ff(d, a, b, c, x[i+ 1], 12, -389564586)  
  c = ff(c, d, a, b, x[i+ 2], 17, 606105819)  
  b = ff(b, c, d, a, x[i+ 3], 22, -1044525330)  
  a = ff(a, b, c, d, x[i+ 4], 7 , -176418897)  
  d = ff(d, a, b, c, x[i+ 5], 12, 1200080426)  
  c = ff(c, d, a, b, x[i+ 6], 17, -1473231341)  
  b = ff(b, c, d, a, x[i+ 7], 22, -45705983)  
  a = ff(a, b, c, d, x[i+ 8], 7 , 1770035416)  
  d = ff(d, a, b, c, x[i+ 9], 12, -1958414417)  
  c = ff(c, d, a, b, x[i+10], 17, -42063)  
  b = ff(b, c, d, a, x[i+11], 22, -1990404162)  
  a = ff(a, b, c, d, x[i+12], 7 , 1804603682)  
  d = ff(d, a, b, c, x[i+13], 12, -40341101)  
  c = ff(c, d, a, b, x[i+14], 17, -1502002290)  
  b = ff(b, c, d, a, x[i+15], 22, 1236535329)  

  a = gg(a, b, c, d, x[i+ 1], 5 , -165796510)  
  d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632)  
  c = gg(c, d, a, b, x[i+11], 14, 643717713)  
  b = gg(b, c, d, a, x[i+ 0], 20, -373897302)  
  a = gg(a, b, c, d, x[i+ 5], 5 , -701558691)  
  d = gg(d, a, b, c, x[i+10], 9 , 38016083)  
  c = gg(c, d, a, b, x[i+15], 14, -660478335)  
  b = gg(b, c, d, a, x[i+ 4], 20, -405537848)  
  a = gg(a, b, c, d, x[i+ 9], 5 , 568446438)  
  d = gg(d, a, b, c, x[i+14], 9 , -1019803690)  
  c = gg(c, d, a, b, x[i+ 3], 14, -187363961)  
  b = gg(b, c, d, a, x[i+ 8], 20, 1163531501)  
  a = gg(a, b, c, d, x[i+13], 5 , -1444681467)  
  d = gg(d, a, b, c, x[i+ 2], 9 , -51403784)  
  c = gg(c, d, a, b, x[i+ 7], 14, 1735328473)  
  b = gg(b, c, d, a, x[i+12], 20, -1926607734)  

  a = hh(a, b, c, d, x[i+ 5], 4 , -378558)  
  d = hh(d, a, b, c, x[i+ 8], 11, -2022574463)  
  c = hh(c, d, a, b, x[i+11], 16, 1839030562)  
  b = hh(b, c, d, a, x[i+14], 23, -35309556)  
  a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060)  
  d = hh(d, a, b, c, x[i+ 4], 11, 1272893353)  
  c = hh(c, d, a, b, x[i+ 7], 16, -155497632)  
  b = hh(b, c, d, a, x[i+10], 23, -1094730640)  
  a = hh(a, b, c, d, x[i+13], 4 , 681279174)  
  d = hh(d, a, b, c, x[i+ 0], 11, -358537222)  
  c = hh(c, d, a, b, x[i+ 3], 16, -722521979)  
  b = hh(b, c, d, a, x[i+ 6], 23, 76029189)  
  a = hh(a, b, c, d, x[i+ 9], 4 , -640364487)  
  d = hh(d, a, b, c, x[i+12], 11, -421815835)  
  c = hh(c, d, a, b, x[i+15], 16, 530742520)  
  b = hh(b, c, d, a, x[i+ 2], 23, -995338651)  

  a = ii(a, b, c, d, x[i+ 0], 6 , -198630844)  
  d = ii(d, a, b, c, x[i+ 7], 10, 1126891415)  
  c = ii(c, d, a, b, x[i+14], 15, -1416354905)  
  b = ii(b, c, d, a, x[i+ 5], 21, -57434055)  
  a = ii(a, b, c, d, x[i+12], 6 , 1700485571)  
  d = ii(d, a, b, c, x[i+ 3], 10, -1894986606)  
  c = ii(c, d, a, b, x[i+10], 15, -1051523)  
  b = ii(b, c, d, a, x[i+ 1], 21, -2054922799)  
  a = ii(a, b, c, d, x[i+ 8], 6 , 1873313359)  
  d = ii(d, a, b, c, x[i+15], 10, -30611744)  
  c = ii(c, d, a, b, x[i+ 6], 15, -1560198380)  
  b = ii(b, c, d, a, x[i+13], 21, 1309151649)  
  a = ii(a, b, c, d, x[i+ 4], 6 , -145523070)  
  d = ii(d, a, b, c, x[i+11], 10, -1120210379)  
  c = ii(c, d, a, b, x[i+ 2], 15, 718787259)  
  b = ii(b, c, d, a, x[i+ 9], 21, -343485551)  

  a = safe_add(a, olda)  
  b = safe_add(b, oldb)  
  c = safe_add(c, oldc)  
  d = safe_add(d, oldd)  
 }  
 return [a, b, c, d]  
}  

/* 
 12. Convert an array of little-endian words to a hex string. 
 */ 
function binl2hex(binarray)  
{  
 var hex_tab = "0123456789abcdef" 
 var str = "" 
 for(var i = 0; i < binarray.length * 4; i++)  
 {  
  str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +  
      hex_tab.charAt((binarray[i>>2] >> ((i%4)*8)) & 0xF)  
 }  
 return str  
}  

/* 
 13. Convert an array of little-endian words to a base64 encoded string. 
 */ 
function binl2b64(binarray)  
{  
 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 
 var str = "" 
 for(var i = 0; i < binarray.length * 32; i += 6)  
 {  
  str += tab.charAt(((binarray[i>>5] << (i%32)) & 0x3F) |  
           ((binarray[i>>5+1] >> (32-i%32)) & 0x3F))  
 }  
 return str  
}  

/* 
 14. Convert an 8-bit character string to a sequence of 16-word blocks, stored 
 15. as an array, and append appropriate padding for MD4/5 calculation. 
 16. If any of the characters are >255, the high byte is silently ignored. 
 */ 
function str2binl(str)  
{  
 var nblk = ((str.length + 8) >> 6) + 1 // number of 16-word blocks  
 var blks = new Array(nblk * 16)  
 for(var i = 0; i < nblk * 16; i++) blks[i] = 0  
 for(var i = 0; i < str.length; i++)  
  blks[i>>2] |= (str.charCodeAt(i) & 0xFF) << ((i%4) * 8)  
 blks[i>>2] |= 0x80 << ((i%4) * 8)  
 blks[nblk*16-2] = str.length * 8  
 return blks  
}  

/* 
 17. Convert a wide-character string to a sequence of 16-word blocks, stored as 
 18. an array, and append appropriate padding for MD4/5 calculation. 
 */ 
function strw2binl(str)  
{  
 var nblk = ((str.length + 4) >> 5) + 1 // number of 16-word blocks  
 var blks = new Array(nblk * 16)  
 for(var i = 0; i < nblk * 16; i++) blks[i] = 0  
 for(var i = 0; i < str.length; i++)  
  blks[i>>1] |= str.charCodeAt(i) << ((i%2) * 16)  
 blks[i>>1] |= 0x80 << ((i%2) * 16)  
 blks[nblk*16-2] = str.length * 16  
 return blks  
}  

/* 
 19. External interface 
 */ 
function hexMD5 (str) { return binl2hex(coreMD5( str2binl(str))) }  
function hexMD5w(str) { return binl2hex(coreMD5(strw2binl(str))) }  
function b64MD5 (str) { return binl2b64(coreMD5( str2binl(str))) }  
function b64MD5w(str) { return binl2b64(coreMD5(strw2binl(str))) }  
/* Backward compatibility */ 
function calcMD5(str) { return binl2hex(coreMD5( str2binl(str))) }  
module.exports = {  
 hexMD5: hexMD5  
} 
  1. 上面的代码就是支付的所有流程了,下面说一下我遇到的坑
    1.支付验证签名失败,多半是你的参数填错了,一定要注意大小写。当然你也可以把你的参数打印出来用签名验证工具检查一下https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1

    2.当前页面的url未注册,说到这个就要说一下这些代码不能在本地测试,只能发布出来放到服务器上测试。这个问题就是说你的域名没有绑定到微信公众号支付的支付授权目录里面
    这里写图片描述

展开阅读全文

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