微信公众号H5页面开发--微信JS-SDK引用

微信公众号H5页面开发–微信JS-SDK引用

微信提供了微信公众号开发者手册,官方地址:https://mp.weixin.qq.com/

公众号内许多复杂的业务场景,都是通过网页形式来提供服务,这时需要用到: 微信JS-SDK。以地理位置接口为例进行阐述。

写在前面 非常重要!
  • 微信公众号接口必须以http://或https://开头,分别支持80端口和443端口。
  • 由于微信7.0版本升级了对https的安全限制,在微信7.0版本及以上版本使用http协议访问定位组件会导致定位失败。尤其是安卓,所以必须升级https。

1. 域名绑定

微信公众号请求网页授权之前,开发者需要先登记授权回调域名。
注意:这里填写的是域名,且为全域名。授权后该域名下的其他页面都可以授权,例如:www.qq.com为回调域名,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。
官方:微信公众平台 >> 微信网页开发 >> 微信网页授权

2.js文件引入

官方:
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.4.0.js (支持https)。
备注:支持使用 AMD/CMD 标准模块加载方法加载

3.通过config接口注入权限验证配置信息

所有引用微信JS-SDK的页面都需要提供权限验证信息,否则无法调用。同样的URL只需要配置一次即可,URL发生变化时需要重新调用配置信息进行验证。

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

这里涉及到两类配置信息的获取,一类是appId所属的公众号标识类配置信息,另一类是签名。JS接口列表可以根据需求在微信公众平台附录中获取。这里所写的是两个地理接口的相关js接口:
jsApiList: ['openLocation','getLocation'] // 必填,需要使用的JS接口列表

  1. 公众号标识
    微信提供了微信公众帐号测试号,绑定个人微信号即可使用。申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
    进入后,第一行就提供了appID和appsecret。不同微信号绑定的微信公众测试号提供的appID和appsecret不同,如果多人参与开发,要注意区分。

在这里插入图片描述

接口配置信息主要用于消息接口的配置。公众号是以微信用户的一个联系人形式存在的,消息会话是公众号与用户交互的基础。在这里填写的URL主要用于接收用户信息,进行业务操作后返回信息,没有单独的页面链接。如果不是H5开发的话这里可以空着不写。

微信公众号H5页面开发--微信JS-SDK引用_第1张图片

这里填写的域名就是上面1点提到的回调域名绑定授权,具体请看上面1. 域名绑定
在这里插入图片描述

  1. 签名配置信息获取

生成签名之前,我们要先获取两个参数:access_token 和 jsapi_ticket 。这两个参数的有效期为7200秒,所以一般是放在全局变量中。
官方:微信公众平台 >> 开始开发 >> 获取access_token

接口调用请求说明:

https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
微信公众号H5页面开发--微信JS-SDK引用_第2张图片

 public static String getAccessToken(String appId, String secret, String accessTokenUrl) {
        HttpClient client = HttpClients.createDefault();	
	// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        HttpGet get = new HttpGet(MessageFormat.format(accessTokenUrl,appId,secret));
        // 创建Get请求
        try {
            String accessToken = (String) CacheUtil.get("wxCache", "accessToken");
    	    //这里把accessToken放在全局变量中,通过CacheUtil缓存工具类判断accessToken是否失效
            if (StringUtils.isBlank(accessToken) || StringUtils.isEmpty(accessToken)) {
                HttpResponse response = client.execute(get);
    		// 由客户端执行(发送)Get请求
                HttpEntity entity = response.getEntity();
    		// 从响应模型中获取响应实体
                String result = EntityUtils.toString(entity, "UTF-8");
                Map accessTokenMap = JSON.parseObject(result);
                accessToken = (String)accessTokenMap.get("access_token");
    		//将响应实体进行编码转换
                CacheUtil.put("wxCache", "accessToken", accessToken);
    		//将accessToken存入缓存变量中
            }
            return accessToken;
        } catch (ClientProtocolException e) {
            log.error(e.getMessage());
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return  null;
    }

用同样的get请求方法,获得jsapi_ticket。与access_token性质相似,有效期为7200秒,建议放在全局变量中,便于下次请求的时候判断是否仍在有效期内。

public static String getTicket(String accessToken,String ticketUrl) {
    HttpClient client = HttpClients.createDefault();
    HttpGet get = new HttpGet(MessageFormat.format(ticketUrl,accessToken));
    try {
        String ticket = (String) CacheUtil.get("wxCache", "jsapi_ticket");
        if (StringUtils.isBlank(ticket) || StringUtils.isEmpty(ticket)) {
            HttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, "UTF-8");
	    Map jsApiTicketMap = JSON.parseObject(result);
            ticket = (String)jsApiTicketMap.get("ticket");

            CacheUtil.put("wxCache", "jsapi_ticket", ticket);
        }
        return ticket;
    } catch (ClientProtocolException e) {
        log.error(e.getMessage());
    } catch (IOException e) {
        log.error(e.getMessage());
    }
    return null;
}

获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
签名生成规则如下:
参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。

//生成时间戳和随机字符串
        String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

时间戳和随机字符串都是随机生成的,但是随机生成规则不同,注意区分。

 //获取url
        String url = pathUrl;

url必须与用户进入页面的url相同,从前台传入,防止因为参数不同而引起的url不同,从而获取签名失败。
对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

 //将参数排序并拼接字符串
     String sortString = WeChatCommonUtil.sort(url, timestamp, ticket, noncestr);
  
 /**
     * @Param [signature, timestamp, ticket, echostr]
     * @Return java.lang.String
     * @Description: 对所有待签名参数按照字段名的ASCII 码从小到大排序
     */
    public static String sort(String url, String timestamp, String ticket, String noncestr) {
        return "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url;
    }

对string1进行sha1签名,得到signature:
微信公众号H5页面开发--微信JS-SDK引用_第3张图片
至此,得到权限验证配置所有信息。

4.通过ready接口处理成功验证

以下步骤官网都有参考:

wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作.
// 所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。
// 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});

这里没有写到error接口,不够严谨。

wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});

5.判断当前客户端版本是否支持指定JS接口

wx.checkJsApi({
jsApiList: [‘chooseImage’], // 需要检测的JS接口列表
success: function(res) {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{“checkResult”:{“chooseImage”:true},“errMsg”:“checkJsApi:ok”}
}
});

需要检测的JS接口与config中填写的 jsApiList 基本一致。
config信息验证后,才会调用ready方法,所以将checkJsApi放在ready方法中执行。

6.参考官方文档调用所需接口

使用微信内置地图查看位置接口:用于打开导航地图,获取目的地坐标定位。

wx.openLocation({
latitude: , // 纬度,浮点数,范围为90 ~ -90
longitude: , // 经度,浮点数,范围为180 ~ -180。
name: ’ ', // 位置名
address: ’ ', // 地址详情说明
scale: 1, // 地图缩放级别,整形值,范围从1~28。默认为最大
infoUrl: ‘’ // 在查看位置界面底部显示的超链接,可点击跳转
});

获取地理位置接口:主要用于获取自身坐标定位。

wx.getLocation({
type: ‘wgs84’, // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入’gcj02’
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
}
});

注意:两个接口的经纬度都是浮点数类型,否则无法调用。

总结:获取微信配置信息验证的步骤比较复杂,必须没有误差,同时要考虑配置信息具有时效性,重复获取以及放在全局变量中。调用接口的代码文档官方都有提供,可以参考。

wx.ready(function () {
    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作.
    // 所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。
    // 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
   
    wx.checkJsApi({
        jsApiList: ['checkJsApi', 'openLocation', 'getLocation'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
        success: function (res) {
            // 以键值对的形式返回,可用的api值true,不可用为false
            // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
        }
    });

    wx.getLocation({
        type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
        dataType: "json",
        success: function (res) {
            var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
            var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
            var speed = res.speed; // 速度,以米/每秒计
            var accuracy = res.accuracy; // 位置精度
        }
    });

    $(".nav-to").on ('click','a',function () {
        wx.openLocation({
            latitude: parseFloat($(".nav-to").attr("lat")), // 纬度,浮点数,范围为90 ~ -90
            longitude:parseFloat($(".nav-to").attr("lng")), // 经度,浮点数,范围为180 ~ -180。
            name: $(".nav-to").attr("name"), // 位置名
            address: '', // 地址详情说明
            scale: 10, // 地图缩放级别,整形值,范围从1~28。默认为最大
            infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转
        });
    });
});

后续补充:
事实证明我真是too young too native = =

背景交代 与真正的公众号进行对接(以上都是用微信提供的测试公众号)时,除了以上步骤还有其他验证是在测试公众号上所不需要的,在此remark一下。

7.设置IP白名单

微信公众号H5页面开发--微信JS-SDK引用_第4张图片
根据要求把服务器的IP加入到IP白名单中,这样就不会被拦截了。

8.设置JS接口安全域名

微信公众号H5页面开发--微信JS-SDK引用_第5张图片
注意:确保可以访问!!!
不管是根目录还是路径目录,都要确保通过所填写的域名都可以访问到这个文件。同时微信所访问的其他路径也需要在这个路径目录下。
踩坑记录:如果程序设置了权限认证,则要记得放开认证,否则永远也无法访问到。

你可能感兴趣的:(微信公众号H5页面开发--微信JS-SDK引用)