1、AirKiss介绍

http://iot.weixin.qq.com/document-7_1.html

2、JSAPI

微信硬件JSAPI接口属于微信JS-SDK的一部分

微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。

使用微信JS-SDK,公众号开发者可借助微信高效地使用拍照、选图、语音、位置、蓝牙、WiFi等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。

使用微信硬件JSAPI,设备厂商可以在网页通过内javascript,对设备操作的接口。例如扫描设备,连接设备,收发数据,绑定设备,Airkiss配网等。

这里写图片描述

HTML通过JSAPI可以和设备本地收发数据(即HTML发送给微信客户端,微信客户端发给设备),无需通过服务器中转,所以速度较快。所以实时性要求高的蓝牙设备(如遥控汽车)可采用JSAPI收发数据。

微信硬件JSAPI接口列表:http://iot.weixin.qq.com/document-3_2.html

微信硬件JSAPI使用说明:http://iot.weixin.qq.com/document-3_3.html

3、业务代码

3.1 页面引用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/"+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>LETUS</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta name="format-detection" content="telephone=no">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <link rel="stylesheet" href="amazeui/assets/css/amazeui.min.css"/>
  <style>
* { margin: 0; padding: 0; }  
 html, body { height: 100%; width: 100%; }  
  </style>
  <script>

</script>
</head>
<body>
<h1>设置设备Wifi</h1>
<br><br>
<div id="message"></div>
</body>
<!--[if (gte IE 9)|!(IE)]><!-->
<script src="/js/jquery.min.js"></script>
<!--<![endif]-->
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script type="text/javascript">

    wx.config({
        beta : true, // 开启内测接口调用,注入wx.invoke方法
        debug : false, // 开启调试模式
        appId : '${config.appId}', // 第三方app唯一标识
        timestamp : '${config.timestamp}', // 生成签名的时间戳
        nonceStr : '${config.nonce}', // 生成签名的随机串
        signature : '${config.signature}',// 签名
        jsApiList : ['configWXDeviceWiFi'] // 需要使用的jsapi列表
    });

    var second = 5;
    wx.ready(function () {
        wx.checkJsApi({
            jsApiList: ['configWXDeviceWiFi'],
            success: function(res) {
                wx.invoke('configWXDeviceWiFi', {}, function(res){
                    var err_msg = res.err_msg;
                    if(err_msg == 'configWXDeviceWiFi:ok') {
                        $('#message').html("配置 WIFI成功,<span id='second'>5</span>秒后跳转到首页。");
                        setInterval(count,1000);
                        return;
                    } else {
                        $('#message').html("配置 WIFI失败,是否<a href=\"/wechat/scan/airkiss" + window.location.search +  "\">再次扫描</a>。<br>不配置WIFI,<a href=\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf1867e87a4eeeb16&redirect_uri=http://letux.xyz/wechat/page/main&response_type=code&scope=snsapi_base&state=1#wechat_redirect\">直接进入首页</a>。");
                    }
                });
            }
        });
    });

    function count(){
        second--;
        $('#second').html(second);
        if(second == 0){
            //跳转到首页
            window.location.href='/consumer/main'
        }
    }
</script>
</html>

要使用JSAPI功能,先引用JSSDK文件:http://res.wx.qq.com/open/js/jweixin-1.0.0.js

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

wx.config的方法的参数大部分由后台生成,本文中是JsAPIConfig对象。jsApiList数组中,传入需要额外使用的jsapi名称,我们用到的AirKiss功能是configWXDeviceWiFi接口。
这里写图片描述

    wx.config({
        beta : true, // 开启内测接口调用,注入wx.invoke方法
        debug : false, // 开启调试模式
        appId : '${config.appId}', // 第三方app唯一标识
        timestamp : '${config.timestamp}', // 生成签名的时间戳
        nonceStr : '${config.nonce}', // 生成签名的随机串
        signature : '${config.signature}',// 签名
        jsApiList : ['configWXDeviceWiFi'] // 需要使用的jsapi列表
    });

检查浏览器是否支持configWXDeviceWiFi接口,并使用此接口。

    wx.ready(function () {
        wx.checkJsApi({
            jsApiList: ['configWXDeviceWiFi'],
            success: function(res) {
                wx.invoke('configWXDeviceWiFi', {}, function(res){
                    var err_msg = res.err_msg;
                    if(err_msg == 'configWXDeviceWiFi:ok') {
                        //配置成功
                    } else {
                        //配置失败
                    }
                });
            }
        });
    });

3.2 JsAPIConfig实体类

package com.benben.timetable.wechat.entity;

/**
 * JS-SDK使用的配置信息
 * @ClassName: JsAPIConfig 
 * @Description: TODO
 * @author 潘广伟(笨笨) 
 * @date 2015年8月17日 下午3:12:35 
 *
 */
public class JsAPIConfig {
    private boolean debug;
    private String appId;
    private String timestamp;
    private String nonce;
    private String signature;
    private String title;
    private String link;
    private String signType;
    private String packageName;

    public JsAPIConfig(){
        signType = "MD5";
    }

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public String getNonce() {
        return nonce;
    }

    public void setNonce(String nonce) {
        this.nonce = nonce;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public String getSignType() {
        return signType;
    }

    public void setSignType(String signType) {
        this.signType = signType;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }   
}

这里默认使用MD5加密方式。

3.3 获取api_ticket

api_ticket会在生成JsAPIConfig对象signature(签名)属性时用到。

api_ticket获取地址:https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=ACCESS_TOKEN

通过http get请求方式获取:

    /**
     * 获取jsTicket
     * @Title: getJsTicketFromWechat 
     * @Description: TODO
     * @param @return
     * @param @throws Exception   
     * @return String   
     * @throws
     */
    public  String getJsTicketFromWechat() throws Exception{  
        String token = getTokenFromCache();
        String responeText = httpConnection.get(ticketUrl+token);
        JSONObject obj = JSONObject.fromObject(responeText);
        String jsTicket = obj.getString("ticket");
        SystemCache.getWechatJsTicketCache().addJsTicket(jsTicket);

        return jsTicket;  
    }

返回JSON格式数据:

 {
    "errcode":0,
    "errmsg":"ok",
    "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKdvsdshFKA",
    "expires_in":7200
}

注意事项(很重要):

1.用于卡券接口签名的api_ticket与我们这里通过config接口注入权限验证配置使用的jsapi_ticket不同。
卡券的ticket获取地址为:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card

2.由于获取api_ticket 的api 调用次数非常有限,频繁刷新api_ticket 会导致api调用受限,影响自身业务,开发者需在自己的服务存储与更新api_ticket。api_ticket 的有效期为7200 秒。

3.4 生成 JsAPIConfig

    /**
     * 生成JsAPIConfig
     * @Title: createConfig
     * @Description: TODO
     * @param @param link 使用AirKiss的链接地址
     * @param @return
     * @param @throws Exception    
     * @return JsAPIConfig    
     * @throws
     */
    public JsAPIConfig createConfig(String link) throws Exception {
        JsAPIConfig config = new JsAPIConfig();
        config.setLink(link);
        String nonce = UUID.randomUUID().toString();
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String src = "jsapi_ticket=" + getJsTicketFromCache() + "&noncestr="
                + nonce + "&timestamp=" + timestamp + "&url="
                + config.getLink();
        String signature = SHAEncryptor.sha1(src);

        config.setAppId(appId);
        config.setDebug(true);
        config.setNonce(nonce);
        config.setTimestamp(timestamp);
        config.setSignature(signature);

        return config;
    }

这里的getJsTicketFromCache()是从缓存中获取ticket了。有关缓存相关的技术,请自个度娘。

    /**
     * 从缓存中获取JsTicket
     * @Title: getJsTicketFromCache
     * @Description: TODO
     * @param @return
     * @param @throws Exception    
     * @return String    
     * @throws
     */
    public String getJsTicketFromCache() throws Exception{  
        String ticket =  SystemCache.getWechatJsTicketCache().getJsTicket();

        if(ticket == null){
            ticket = getJsTicketFromWechat();
        }

        return ticket;
    }

我们要生成JsAPIConfig对象,需要引入使用AirKiss的页面。如我们这里的页面地址是http://letus.xyz/wechat/scan/airkiss

JsAPIConfig config = createConfig("http://letus.xyz/wechat/scan/airkiss");

4、AirKiss页面

这里写图片描述

当配置属性调用成功后,会来到AirKiss页面。输入移动设备所在网络的WiFi密码并确定,微信会通过AirKiss技术,把周围的硬件设备配置到同一网络中。

配置成功会返回configWXDeviceWiFi:ok信息。在配置成功后,我们再做相应的页面跳转逻辑即可。

HttpConnection:https://code.csdn.net/snippets/1361856

SHAEncryptor :https://code.csdn.net/snippets/1555369

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐