微信JS SDK配置授权,实现分享接口
微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享、扫一扫、卡券、支付等微信特有的能力。7月份的时候,因为这个分享的证书获取问题深深的栽了一坑,后面看到“config:ok”的时候真的算是石头落地,瞬间感觉世界很美好..
这篇文章是微信开发的很多前置条件,包括了服务端基于JAVA的获取和缓存全局的access_token,获取和缓存全局的jsapi_ticket,以及前端配置授权组件封装,调用分享组件封装。
配置授权思路:首先根据access_token获取jsapi_ticket,在通过获取到的jsapi_ticket以及随机生成的字符串、时间戳,再加上需要授权的页面地址url,进行SHA-1加密,返回加密字符串,最后根据加密串调用微信提供的config接口。
配置JS接口安全域名
公众平台--公众号设置--功能设置--js接口安全域名

获取、缓存全局的access_token
/**
* 微信全局票据 ---->>>> access_token
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public String getBaseAccessToken() throws ClientProtocolException, IOException{ try {
String value = redisService.get("WEIXIN_BASE_ACCESS_TOKEN");
if (!StringUtils.isEmpty(value)) {
LOGGER.info("Get base access_token from redis is successful.value:{}",value);
return value;
}else{
synchronized (this) {
//缓存中没有、或已经失效
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+WX_APPID+"&secret="+ WX_APPSECRET;
String rs = apiService.doGet(url); JSONObject obj_content = JSONObject.parseObject(rs);
String accessToken = obj_content.getString("access_token");
Integer time = Integer.parseInt(obj_content.getString("expires_in").toString()); //写缓存
redisService.set("WEIXIN_BASE_ACCESS_TOKEN", accessToken, time - 3600);
LOGGER.info("Set base access_token to redis is successful.parameters time:{},realtime",time,time-3600);
return accessToken;
}
}
} catch (Exception e) {
LOGGER.error("Get base access_token from redis is error.");
}
return null;
}
先从缓存中取key为“WX_BASE_ACCESS_TOKEN” ,如果命中直接返回值,反之通过httpclient发送GET请求调用微信提供的接口获取全局的access_token,同时将取到的值写入缓存。
获取、缓存全局的jsapi_ticket
/**
* jsapi_ticket是公众号用于调用微信JS接口的临时票据
* @return
* @throws IOException
* @throws ClientProtocolException
*/
public String getJsapiTicket() throws ClientProtocolException, IOException{
try {
String value = redisService.get("WEIXIN_JS_API_TICKET");
if (!StringUtils.isEmpty(value)) {
return value;
}else{
synchronized (this) {
//缓存中没有、或已经失效
//获取全局的access_token,唯一票据
String accessToken = getBaseAccessToken(); String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ accessToken +"&type=jsapi"; String rs = apiService.doGet(url); JSONObject obj_content = JSONObject.parseObject(rs);
String jsapi_ticket = obj_content.getString("ticket");
Integer time = Integer.parseInt(obj_content.getString("expires_in").toString()); //写缓存
redisService.set("WEIXIN_JS_API_TICKET", jsapi_ticket, time - 3600); return jsapi_ticket;
}
}
} catch (Exception e) {
LOGGER.error("Get js_api_ticket from redis is error:{}",e);
} return null;
}
由于获取jsapi_ticket微信有100000次限制,所以必须用上缓存。同理获取access_token,我这里为了保险起见缓存失效时间设置为官方提供的时间再减去一个小时。
jssdk加密串获取restful
1.Controller
/**
* 微信分享证书获取
* @param
* @return signature
* @throws IOException
*/
@RequestMapping(value = "/signature", method = RequestMethod.GET)
public @ResponseBody String createSignature(
@RequestParam String url) throws IOException{ LOGGER.info("RestFul of createSignature parameters url:{}",url); try {
String rs = wechatService.createSignature(url);
LOGGER.info("RestFul of signature is successful.",rs); return rs;
} catch (Exception e) {
LOGGER.error("RestFul of signature is error.",e);
} return null;
}
2.Service
/**
* 根据jsapi_ticket等参数进行SHA1加密
* @param nonceStr 随机字符串
* @param timestamp 当前时间戳
* @param url 当前页面url
*/
public String createSignature(String url) throws ClientProtocolException, IOException{
String nonceStr = create_nonce_str();
String timestamp = create_timestamp(); String signature = "jsapi_ticket="+getJsapiTicket();
signature += "&noncestr="+nonceStr;
signature += "×tamp="+timestamp;
signature += "&url="+url; try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(signature.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (Exception e) {
LOGGER.error("Signature for SHA-1 is error:{}",e);
} Map<String, String> map = new HashMap<String, String>();
map.put("timestamp", timestamp);
map.put("nonceStr", nonceStr);
map.put("signature", signature);
map.put("appid", WX_APPID);
return JSON.toJSONString(map, true);
}
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
WX_APPID为公众号appid,通过spring@value注解从配置文件获取,这里不细说。
3.生成随机字符串
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
4.时间格式化
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
到此为止后台全部完成,其实没有太多的解释,仔细读一遍代码,可读性应该还行!
封装获取授权组件,实现分享方法
require.config({
urlArgs: "v=20161116" ,
baseUrl : "/static",
paths: {
jweixin: 'component/jweixin/jweixin-1.0.0',
share: 'component/wechat/share'//微信分享组件
}
})
首先通过调用后台接口获取加密字符串,调用微信提供的wx.config()方法
//jsSDK授权
$.signature = function(wx,opts,currentUrl,callback){ $.ajax({
data: {url: currentUrl},
type: "GET",
url: WX_ROOT + "wechat/signature",
success: function (json) {
if (json) {
var data = JSON.parse(json); wx.config({
debug: false,
appId: data.appid,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone'
]
}); wechatShare.options.isSignature = true; callback && callback(opts,wx);
}
}
});
}
建议:开发环境建议开启调式模式,方便打印日志定位问题debug: true
所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,我这里用一个全局变量isSignature缓存了是否已经配置授权,然后执行回调。如实现分享接口:
//分享
$.share = function(opts,wx) {
var options = {
currentUrl: window.location.href.split('#')[0],
imgUrl: null,
title: '达农保险',
desc: null,
shareUrl: null
} $.extend(true, options, opts || {}); //判断是否已经授权
if(!wechatShare.options.isSignature){
$.signature(wx,opts,options.currentUrl,$.share)
}else{
wx.ready(function(){
//分享到朋友圈
wx.onMenuShareTimeline({
title: options.title,
link: options.shareUrl,
imgUrl: options.imgUrl,
success: function () {
//分享统计,分享来源 1 朋友圈 2分享给朋友 3分享到QQ 4分享到QQ空间 }
}); //分享给朋友
wx.onMenuShareAppMessage({
title: options.title,
desc: options.desc,
link: options.shareUrl,
imgUrl: options.imgUrl
});
});
} }
我先确认是否已经配置授权,如果没有授权则调用$.signature()回调函数里传入$.share,有点类似递归调用,当再次回到share方法的时候isSignature已经是true了,则执行wx.ready()方法,再调需要调用的接口,微信开放提供了很多接口给我们,分享只是其中一个。只有想不到的,没有实现不了的....
注意:currentUrl 必须是动态获取的,通过window.location.href方法,因为页面分享,微信客户端会在你的链接末尾加入其它参数,所以需要再将url用‘#’割一下,取第一个,如果有中文最好是用encodeURIComponent转义一下,保证签名获取成功。如果报invalid signature,大部分原因是传入的url,和加密算法的问题,仔细检查!
调用:
var ua = navigator.userAgent.toLowerCase(),
isWechat = ua.indexOf('micromessenger') != -1;//判断是否为微信浏览器
var shareData = {
title: ‘测试分享’,
desc: ‘这里是描述,分享到朋友圈不会显示’,
link: APP_ROOT + '/base/downloadApp,//分享后打开的链接,必须在配置的安全域名下
imgUrl: PIC_PATH + (self.data.shareListData[0].imgSmall || '/static/img/coupon/getTicPic.png'),//分享后显示的图片
success: function(){
setTimeout(function(){
//运营数据统计
},0)//伪异步方式调用
}
}
//微信浏览器分享加载
if(isWechat){
require(['jweixin'],function(wx){
require(['share'],function(){
$.share(shareData,wx);
})
})
}
完整js:https://github.com/helijun/component/blob/master/wechat/share.js
常用问题总结:
最开始做这个分享功能的时候,因为一个证书获取失败的原因(invalid signature)真的是断断续续困了好几天,有的时候真的是毫无头绪了。反复检查代码,逐字逐行的看,真的没有发现任何异常,通过微信提供的一个js接口签名校验工具测试也是返回ture,然而就是报证书失败!微信官方文档又有点模棱两可,到最后星期六的一个下午,静下心来,再耐心的检查了一遍后台SHA1加密算法,终于看到config true.. 曙光
开发中我们总是会遇到各种各样的问题,程序员和bug永远都是好朋友同时又是敌人,我们总是徘徊在bug的边缘,有时候当遇到很奇怪的问题的时候不妨先放一下,注意力先转移一下,去阳台吹吹风,说不定在某一个时刻,问题突然就解开了..
接口签名校验工具
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
微信JS SDK配置授权,实现分享接口的更多相关文章
- 微信JS SDK接入的几点注意事项
微信JS SDK接入,主要可以先参考官网说明文档,总结起来有几个步骤: 1.绑定域名:先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”.备注:登录后可在“开发者中心”查看对 ...
- 实战微信JS SDK开发:贺卡制作与播放(1)
前段时间忙于CanTK 2.0的开发,所以博客一直没有更新.CanTK 2.0主要增强了游戏和富媒体的开发,现在编码和测试基本完成了,等文档完成了再正式发布,里面有不少激动人心的功能,等发布时再一一细 ...
- 微信js sdk上传多张图片
微信js sdk上传多张图片,微信上传多张图片 该案例已tp3.2商城为例 直接上代码: php代码: public function ind(){ $appid="111111111111 ...
- 微信开发(2):微信js sdk分享朋友圈,朋友,获取config接口注入权限验证(转)
进行微信开发已经一阵子了,从最初的什么也不懂,到微信授权登录,分享,更改底部菜单,素材管理,等. 今天记录一下微信jssdk 的分享给朋友的功能,获取config接口注入. 官方文档走一下简单说:四步 ...
- 微信js SDK接口
微信JS-SDK说明文档 http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html 一.微信登录功能 在进行微信OAut ...
- 微信js sdk分享开发摘记java版
绑定域名和引入js的就不说了 废话不说直接上代码 public void share(HttpServletRequest request) throws Exception { StringBuff ...
- 微信JS SDK Demo 官方案例[转]
摘要: 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用 ...
- 微信JS SDK Demo
微信JS-SDK 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置原文:http://www.cnblogs.com/txw1958/p/ ...
- 微信JS SDK Demo 官方案例
微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享 ...
随机推荐
- wpf 遍历控件及其值
/// <summary> /// 遍历控件及其值 /// </summary> /// <param name="uiControls">界面 ...
- CCS应用中常见的一些小技巧
在单片机开发中,通常需要精确估算代码运行时间,用于对算法优化以及对项目平台选择提供参考,通常算法如果用汇编编写,可以人工计算出运行时间,用C语言编写也可以通过反汇编代码而计算到较为精确的运行时间,但当 ...
- php冒泡排序和快速排序
如有错误,请指出... //快速排序(array_merge整合数组)function quick_sort($arr){ $num=count($arr); if($num<=1){ retu ...
- mysql复习相关
Mysql相关 mysql增删改查 我们需要修改数据表名或者修改数据表字段时,就需要使用到Mysql Alter命令 删除,添加或修改表字段 alter table student drop regi ...
- Thread 学习记录 <1> -- volatile和synchronized
恐怕比较一下volatile和synchronized的不同是最容易解释清楚的.volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1; ...
- Windows 服务的安装(1)
在上一篇文章中创建了window服务 http://www.cnblogs.com/netqq/p/4182259.html 在本篇中将教会你如何安装这个服务 服务程序的开发和运行环境均为:windo ...
- 关于MySQL的wait_timeout连接超时问题报错解决方案
bug回顾 : 想必大家在用MySQL时都会遇到连接超时的问题,如下图所示: ### Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsExce ...
- 【IOS】将一组包含中文的数据按照#ABC...Z✿分组
上一篇文章[IOS]模仿windowsphone列表索引控件YFMetroListBox里面 我们一步步的实现了WindowsPhone风格的索引. 但是有没有发现,如果你要实现按照字母排序,你还得自 ...
- 决策树-ID3
id3:无法直接处理数值型数据,可以通过量化方法将数值型数据处理成标称型数据,但涉及太多特征划分,不建议 决策树:的最大优点在于可以给出数据的内在含义,数据形式非常容易理解: 决策树介绍:决策树分类器 ...
- python爬虫小项目实战