微信JS-SDK是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包。
通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。
关于小程序使用JS-SDK小程序的web-view相关的API调用参考地址:web-view | 微信开放文档
JS-SDK主要是给微信公众号使用的,在小程序的web-view中嵌套的html5页面可以通过调用JS-SDK,从而实现了调用微信端几个指定的相关API功能,比如拍照、上传图片、扫一扫等。以下介绍如何调用扫一扫功能。
一、引用并加载微信JS-SDK库
调用所有微信API接口前,必须先引用JS-SDK库。
以下有两种方法引用JS-SDK库,推荐方法2.
方法1.通过script引用JS文件,此方法也是微信官方文档的示例方法
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)。
方法2.通过webpack引入
安装
npm install weixin-js-sdk -S
使用:在main.js文件中,使用import引用并命名为wx,再将wx设置到vue.prototype属性中。这样全局都可以通过this.$wx.***的方式使用js-sdk的API了。
import wx from "weixin-js-sdk"; Vue.prototype.$wx = wx
二、demo页面调用扫一扫函数前的初始化工作
以下为demo页面,在mounted中调用后端JAVA接口获取初始化微信config接口需要的appId和ticket(JAVA代码参见后文)。
在methods中定义的初始化方法wechatApiInit,主要是实现通过config接口注入权限验证配置。并按微信官方文档的要求,注入config前做了签名算法。scan方法就是页面点击“扫一扫”按钮的触发事件。
mounted:
mounted: function () {
//申请微信jsadk接口 扫一扫
var jsApiList = ["scanQRCode"];
//访问后端JAVA接口:获取appId
getAppKey({
params: ""
}).then((res)=>{
this.appId=res.entity.appId;
})
//访问后端JAVA接口:获取微信JS-SDK的ticket
loadTicket({
params: "",
}).then((res) => {
console.log("RES>>", res);
if (res.entity.ticket) {
//将ticket传入 进行JS-SDK调用的初始化
this.wechatApiInit({ ticket: res.entity.ticket, jsApiList });
} else {
console.log("loadTicket获取失败");
}
});
},
methods:
//微信api 初始化
wechatApiInit(jsonResult) {
console.log("jsonResult>>>", jsonResult);
if (!this.$wxapi.is_weixin()) {
console.log("当前环境不是微信.")
return;
}
//字符合并
var raw = function (args) {
var keys = Object.keys(args);
keys = keys.sort();
var newArgs = {};
keys.forEach(function (key) {
newArgs[key.toLowerCase()] = args[key];
});
var string = "";
for (var k in newArgs) {
string += "&" + k + "=" + newArgs[k];
}
string = string.substr(1);
return string;
};
var vurl= location.href;
//console.log("location.href:"+vurl);
vurl=location.href.split('#')[0];
//console.log("vurl:"+vurl);
//数据包
var ret = {
jsapi_ticket: jsonResult.ticket,
nonceStr: Math.random().toString(36).substr(2, 15),
timestamp: parseInt(new Date().getTime() / 1000) + "",
url: vurl
};
//console.log("RET:", ret);
let string1= raw(ret);
//console.log("string1:"+string1);
let ticket=hex_sha1(string1);
//console.log("ticket",ticket);
//console.log("jsonResult.jsApiList",jsonResult.jsApiList);
//console.log("appId:",this.appId);
//通过config接口注入权限验证配置
this.$wx.config({
debug: false,//调试时设置为true
appId: this.appId,
timestamp: ret.timestamp,
nonceStr: ret.nonceStr,
signature: ticket,
jsApiList: jsonResult.jsApiList
});
},
//扫一扫 按钮触发事件
scan() {
var that=this;
this.$wx.miniProgram.getEnv(function (res) {
console.log(res.miniprogram); // true
if (res.miniprogram) {
console.log("小程序scan.");
that.$wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function (res) {
var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
//alert(result);
that.getDeviceCode(result);//将扫码结果传到自定义的方法去执行
},
});
} else {
console.log("app scan.");
}
});
}
调试时,请将config中的debug设置为true,如果有异常,可以看到调试异常的信息。注意scan方法中this和that的使用。
三、JAVA后端接口代码
说明:JAVA后端接口主要实现了获取appId,获取ticket值(自动验证超时)。
部分方法为自定义的公用方法类(比如读取xml配置项,发送http请求等),这里就不一一给出了,可以用自己的方法替代实现。这里主要是给出实现的主要步骤。
// 微信JS接口的临时票据 public ResultMsg loadTicket(@RequestBody HashMapmap) { String estr = "微信JS接口的临时票据(loadTicket):"; ResultMsg rMsg = new ResultMsg(); logger.debug(estr + "loadTicket ok."); try { String vUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + isExistAccess_Token() + "&type=jsapi"; logger.debug("vurl:" + vUrl); String msg = Comm.httpGet(vUrl); logger.debug(msg); rMsg.setEntity(Comm.toHashMap(msg)); rMsg.setSuccess(); return rMsg; } catch (Exception e) { logger.error(estr + e.toString()); return null; } } // 微信appID public ResultMsg getAppKey(@RequestBody HashMap map) { String estr = "微信appID和appSecret:"; ResultMsg resultMsg = new ResultMsg(); try { HashMap rmap = new HashMap (); rmap.put("appId", getAppId()); //rmap.put("appsecret", getAppSecret()); resultMsg.setEntity(JSONObject.fromObject(rmap)); resultMsg.setSuccess(); logger.info(resultMsg.toString()); return resultMsg; } catch (Exception e) { logger.error(estr + e.toString()); return resultMsg; } } // 获取access_token值 public String isExistAccess_Token() { try { String path = this.getClass().getClassLoader().getResource("config/token.xml").getPath(); String token = Comm.xmlRead(path, "access_token");// tonken值 String YouXRQ = Comm.xmlRead(path, "expires_in");// 有效日期 SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date dt = sf.parse(YouXRQ); Date dtnow = new Date(); logger.debug(" 当前时间>>" + dtnow.getTime() + "|| 记录时间>>" + dt.getTime()); if (dtnow.getTime() > dt.getTime()) { String msg = getAccessToKen(); HashMap map = Comm.toHashMap(msg); token = map.get("access_token").toString(); // logger.info(path); Comm.xmlWrite(path, "access_token", token);// 保存最新token String expires_in = map.get("expires_in").toString();// 失效时长(秒) Integer expires = Integer.valueOf(expires_in); Calendar cal = Calendar.getInstance(); cal.setTime(dtnow); cal.add(Calendar.SECOND, expires);// 保存过期时间 Comm.xmlWrite(path, "expires_in", sf.format(cal.getTime())); logger.info("新token时效." + sf.format(cal.getTime())); return token; } else { logger.info("获取原token值:" + token); return token; } } catch (Exception e) { e.printStackTrace(); return ""; } } // 刷新微信token(仅供内部获取token值调用) private String getAccessToKen() { String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + "&appid=" + getAppId() + "&secret=" + getAppSecret(); String msg = ""; try { msg = Comm.httpGet(tokenUrl); logger.info("刷新微信token:" + msg); return msg; } catch (Exception e) { logger.error(e.toString()); return msg; } }
四、需要避免踩到的坑
开发小程序调用JS-SDK时,使用的appId、AppSecret都必须是微信公众号而不是小程序的,同样也必须在微信公众号的业务域名中添加小程序的url调用地址,切记!!
否则会出现“40048,invalid url domain”不合法的url域名。业务域名设置时不能带http://的协议头,设置示例为: aaa.com



