企业微信微信api开发 调起默认浏览以及支付方式

一、绑定JS接口安全域名
生产号绑定方法:登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
测试号绑定方法:进入测试号管理页面,找到JS接口安全域名项绑定
JS接口安全域名官方说法是:开发者可在该域名下调用微信开放的JS接口
域名格式:如果你的项目域名是http://test.domain.com,那么JS接口安全域名为test.domain.com。
域名绑定失败或者域名不存在会报错误:invalid url domain
二、引入微信js文件
引入方法:在需要调用JS接口的页面引入JS文件,用script标签引入即可
JS文件路径:http://res.wx.qq.com/open/js/jweixin-1.2.0.js(支持https)
三、通过wx.config接口注入权限验证
1、每个需要使用jssdk的页面都要使用config接口注入配置信息,wx.config调用方法如下:

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳,精确到秒
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [] // 必填,需要使用的JS接口列表,例如:['chooseImage','previewImage','uploadImage']
    })

其中appId,timestamp,nonceStr,signature必须从后台获取
四、后台生成并返回前端所需参数
1、jsapi_ticket
jsapi_ticket是公众号用于调用js接口的临时票据。有效期7200秒,跟公众号普通access_token一样,必须全局缓存起来,因为这个ticket获取次数有限,超过次数将无法使用。建议设置缓存时间为7198秒,因为当请求微信端生成jsapi_ticket返回给后台保存这个动作需要时间,如果设置7200秒,实际上最后一两秒时,缓存里面还存在,但实际在微信那边已经过期了,再拿这个ticket会出错。生成jsapi_ticket如下:
(1)获取普通access_token(GET请求):
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
(2)用第一步获取的access_token使用GET请求获取jsapi_ticket
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
正确获取信息如下:

{
 "errcode":0,
 "errmsg":"ok",
 "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
 "expires_in":7200
}

2、生成签名(signature)
签名规则:
1、参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分)。
2、对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序,sort()即可)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串(string)。
3、使用sha1加密拼接成的字符串string。注意:字段名和字段值都要使用原值,不要进行url转义

参与的字段示例:

    noncestr=Wm3WZYTPz0wzccnW
    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
    timestamp=1414587457
    url=http://mp.weixin.qq.com?params=value

拼接完成的字符串:

    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value

使用sha1加密后的signature:

    0f9de62fce790f9a083d5c99e95740ceb90c27ed

3、签名生成完后将appId、timestamp、nonceStr、signature一起返回到前端。格式示例:

    {
    	appId:appId,
    	timestamp:timestamp,
    	nonceStr: noncestr,
    	signature: signature
    }

前端拿到值后,写入到wx.config中相应字段即可

注意:
1、前端wx.config配置中的nonceStr字段名称的’s’是大写,但是后台生成签名的noncestr字段的‘s’是小写
2、时间戳(timestamp)值要记住精确到秒,不是毫秒。
3、生成签名的url(使用jssdk的页面地址,这个页面地址可以在浏览器访问),包含“?”号后面的所有参数,不包含“#”号后面的值。

如果是静默授权或者授权页面同意授权后跳转到的页面,页面路径会添加两个参数:code和state。
即授权后跳转页面为http://redirect.page.com,则完整路径为

http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE。

那么生成签名的url必须为授权后跳转页面的完整路径。前端获取这个路径:location.href.split(’#’)[0]

如果前端使用ajax(使用jquery)获取wx.config配置所需的几个参数的值,可以这样做:

$.ajax({
	url: 'http://backend.com?fullUrl=' + location.href.split('#')[0]//这里的参数fullUrl是当前页面的完整url(除去#后面部分)
	type: 'GET',
	success: function(res) {
		//操作后台返回值
	}
})

后台要怎么操作前端传过来的query值呢?大家肯定一眼看出来 获取query中的fullUrl字段不就行了。

后台代码:(使用nodejs的koa框架)

    let query = this.request.query;//获取查询字符串
    let fullUrl = query.fullUrl;//获取查询字符串中的fullUrl字段

从前端请求获取签名接口开始,博主打印了query的值。。也就是let query = this.request.query的值。。结果发现。query值为:

{
	fullUrl: 'http://redirect.page.com?code=kdijafdhjaikeiu20kaiela',
	state: 'STATE'
}

微信网页授权后跳转的页面完整路径为

http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE

路径最后面的’&state=STATE’。当我们把这个完整路径当做查询字符串传到后台的时候,因为没有对这个路径进行encodeURIComponent.所以后台将’&state=STATE’单独看成了一个查询字符串参数。
(公众号文档发现’附录5-常见错误及解决方法’第六条)

使用encodeURIComponent(location.href.split('#')[0])即可

五、调用接口
wx.config配置完成后会执行wx.ready方法,所有接口必须要在config返回结果之后操作。config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。当前页面要使用的接口,要写入到config配置中的jsApiList中

六、常见问题
1、invalid url domain:
js接口安全域名错误。可以看看第一项
2、invalid signature:
要么是jsapi_ticket错误,要么是签名算法问题,要么是算法的参数有问题,注意noncestr中的’s’是小写的。如果都是对的。那就是前端传的url有问题了。。。好好检查一下,不要像博主一样啊。。。。
3、permission denied:
这个问题一般是没有接口权限的问题,有的接口是要认证之后才可以使用,当然,测试号不会有这个问题

七、举例—企业微信打开默认浏览器

    // 判断是否为pc端企业微信
    function isWeiXin() {
        var ua = window.navigator.userAgent.toLowerCase();
        if (ua.match(/windowswechat/i) == 'windowswechat'&&'wxwork'==ua.match(/wxwork/i)) {
    //发送请求向后台获取wx.config信息
            $.ajax({
                url: '/work-wx?url='+encodeURIComponent(window.location.href),
                type: 'post',
                contentType:"application/json",
                dataType: 'json',
                success: function(data) { _config(data) },
                error:function (err) { console.log(err)}
            });
        } else {return false; }
    }

    function _config(signInfo){
        wx.config({
            debug : false,
            beta : true,
            appId : signInfo.appId,
            timestamp : signInfo.timestamp,
            nonceStr : signInfo.noncestr,
            signature : signInfo.signature,
            jsApiList : ['openDefaultBrowser']
        })
        wx.ready(function(){
            wx.invoke('openDefaultBrowser', {
                'url': window.location.href // 在默认浏览器打开redirect_uri,并附加code参数;也可以直接指定要打开的url,此时不会附带上code参数。
            }, function(res){
                if(res.err_msg == "openDefaultBrowser:ok"){
                        wx.closeWindow();
                        window.close();
                }
            });
        });
    }

八、调起支付页面

    // 判断打开方式
    let openFun = getOpenFun()
    // 获取href
    let href = window.location.href
    let searchId = orderId || this.props.match.params.orderId
    //判断是否有code 获取重定向地址
    if (href.split('#')[0].split('?').length < 2) {
        if (openFun === 'microMessenger') {
            api.getWeChatCode({orderId: searchId, courseId: this.props.match.params.courseId}).then(res => {
                if (res) window.location = res
            })
        } else if (openFun === 'wxwork') {
            api.getWxworkCode({orderId: searchId, courseId: this.props.match.params.courseId}).then(res => {
                if (res) window.location = res
            })
        }
    } else {   //有code
        this.code = href.split('#')[0].split('?')[1].split('code=')[1].split('&')[0]
        if (openFun === 'microMessenger') {
            api.paidOrder({orderId: this.props.match.params.orderId, code: this.code}).then(res => {
                if (res) window.location = res
            })
        } else if (openFun === 'wxwork') {  // 微信打开
            // 获取openid
            api.getWxworkOpenid({code: this.code}).then(res => {
                // 判断code是否过期
                if (res.available) {
                    let openId = res.openId
                    // 支付所需信息
                    api.wxWorkPrepay({orderId: this.props.match.params.orderId, openId: openId}).then(res => {
                        if (res) {
                        	//微信配置
                            this.getWxConfig(res)
                        }
                    })
                } else {
                    api.getWxworkCode({orderId: searchId, courseId: this.props.match.params.courseId}).then(res => {
                        if (res) window.location = res
                    })
                }
            })
        }
    }

    getWxConfig(payInfo) {
        let courseId = this.props.match.params.courseId
        let goPath = window.location.origin + '/#/course/record/' + courseId
        sessionStorage.isGohome = 'go'
        let url = encodeURIComponent(window.location.href.split('#')[0])
        Api.getWxConfig(url).then(res => {
            if (res) {
                window.wx.config({
                    beta: true,// 必须这么写,否则wx.invoke调用形式的jsapi会有问题
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: res.corpId, // 必填,企业微信的corpID
                    timestamp: res.timestamp, // 必填,生成签名的时间戳
                    nonceStr: res.nonceStr, // 必填,生成签名的随机串
                    signature: res.corpSignature,// 必填,签名,见 附录-JS-SDK使用权限签名算法
                    jsApiList: ["getBrandWCPayRequest", "onHistoryBack"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
            }
            window.wx.ready(function () {
                window.WeixinJSBridge.invoke(
                    'getBrandWCPayRequest', {
                        "appId": payInfo.appId,     //公众号名称,由商户传入
                        "timeStamp": payInfo.timestamp,         //时间戳,自1970年以来的秒数
                        "nonceStr": payInfo.nonceStr, //随机串
                        "package": "prepay_id=" + payInfo.prepayId,
                        "signType": payInfo.signType,         //微信签名方式:
                        "paySign": payInfo.paySign //微信签名
                    },
                    function (res) {
                        window.location.href = goPath
                        if (res.err_msg === "get_brand_wcpay_request:ok") {
                            // 使用以上方式判断前端返回,微信团队郑重提示:
                            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                        }
                    });
            });
        }).catch(err => { })
    }

    export const getOpenFun = function () {
        let ua = window.navigator.userAgent.toLowerCase();
        if(ua.match(/MicroMessenger/i)&&!ua.match(/wxwork/i)){
            return 'microMessenger'
        }else if(ua.match(/MicroMessenger/i)&&ua.match(/wxwork/i)){
            return 'wxwork'
        }else{
            return 'other'
        }
    };

你可能感兴趣的:(企业微信微信api开发 调起默认浏览以及支付方式)