最近产品部出了一个需求,要做一个分享的功能、在客户端微信上面打开弹出一个h5的分享弹窗,点击可以分享到微信朋友及朋友圈分享出去一张图片,如下图:
当时就想到,一般不都是微信中右上角有个三个点,点击可以分享的嘛,干嘛要还做这个多此一举,于是跟产品部讨论一番,说需点击分享按钮分享出去一张图片,平时我们点击右上角都是分享当前页面的链接,满足不了,彻底被产品部的需求震惊了,当时就想反手一巴掌,接下来就不用说了,遇到各种坑了,先来讲讲微信这个分享的步骤吧。
微信分享的步骤:
注意:一定要找个已经绑定好的微信公众号 appId和secret、并且要引入微信的js
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
1、获取访问的token
String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret=a06e8ca9ea174a15b606d3db94e162e8";
2、通过token来获取ticket
String accessTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
3、通过上面获取的token和ticket来组装一个url生成一个签名signature
/**
* TODO - 获取微信认证信息签名信息
* @return
*/
@RequestMapping(value = "/get_wechat_authentication_info.htm")
@ResponseBody
public Map<String,Object> get_wechat_share_info(String accessToken,String ticket,String appId, String url) {
Map<String, Object> jsonMap = new HashMap<String, Object>();
/* * 产生随机字符串 * */
String noncestr = UUID.randomUUID().toString().replaceAll( "\\-","").toUpperCase();
/* * 产生时间数值 * */
long timestamp = System.currentTimeMillis() / 1000;
/* * 产生字符串str和签名signature * */
String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url;
String signature = SHA1(str);
jsonMap.put("timestamp",timestamp);
jsonMap.put("accessToken",accessToken);
jsonMap.put("ticket",ticket);
jsonMap.put("nonceStr",noncestr);
jsonMap.put("signature",signature);
jsonMap.put("appId",appId);
return jsonMap;
}
接下来是js中调用微信的一些函数来做分享处理、微信朋友及朋友圈的两个监听函数分别是:
wx.ready(function () {
// 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
wx.onMenuShareAppMessage(obj);
wx.error(function(res){
alert("errorMSG"+res);
})
})
wx.ready(function () {
// 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
wx.onMenuShareTimeline(obj);
})
这个是我写的微信分享函数直接调用就可以了,里面已经封装了一个obj对象,因为分享出来的图片都不一样,所以直接封装起来
/**
* 微信分享
* @param type 1:朋友、2:朋友圈
* @param title
* @param desc
* @param link
* @param imgUrl
*/
function shareWechat(type){
var obj = {
title: '两步路2018年度十大游记达人评选', // 分享标题
desc: '约靠谱队友,上「户外助手」', // 分享描述
//分享的链接域名货路径必须与当前页面对应的公众号JS安全域名一直,也就是说这个appId的公众号里面必须要绑定这个www.xx.com域名,不然会出现提示 config inval url问题
link: 'https://www.xx.com/community/index_travel_vote.htm',
link: picUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
// 该链接是重定向链接,因为需要获取用户code,但是该链接又无法直接写微信获取code的链接,
// 所以需要点击后重新加载新的页面,来实现重定向,重新打开获取code的微信链接,实现获取用户信息的功能;
imgUrl: picUrl, // 分享图标
fail: function (res) {
alert(JSON.stringify(res)+"---");
},
/*success: function (res) {
// 用户确认分享后执行的回调函数
alert('success'+res);
},
cancel: function (res) {
alert('cancel'+res);
}*/
};
if(type==1){
wx.ready(function () {
// 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
wx.onMenuShareAppMessage(obj);
wx.error(function(res){
alert("errorMSG"+res);
})
})
}else if(type == 2){
wx.ready(function () {
// 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
wx.onMenuShareTimeline(obj);
})
}
}
这个是获取微信认证的想过信息,列入token、ticket、签名的一些ajax请求
//获取微信token
function getWxAccessToken(url){
$.ajax({
type:'get',
url: basePath + "/get_wechat_token.htm",
dataType:'json',
success:function(data){
var url = location.href;
if (data.errcode == "0") {
$.ajax({
type:'post',
url: basePath+'/community/get_wechat_authentication_info.htm',
data:{accessToken:data.access_token,ticket:data.ticket,url:url,appId:data.appId},
success:function(data){
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId,
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
]// 必填,需要使用的JS接口列表
});
}
});
}
}
});
}
注:获取微信认证信息必须在后台代码中请求,不能通过ajax来访问的,
/**
* TODO - 获取微信token
* @return
*/
@RequestMapping(value = "/get_wechat_token.htm")
@ResponseBody
public Map<String,Object> get_wechat_token(){
Map<String, Object> jsonMap = null;
// m - 构建请求url
String accessTokenUrl = null;
String appId = "wxf4089e0e20e0c844b";
try {
if(redisUtil.get("jsonMap")!=null){
jsonMap = JSON.parseObject(redisUtil.get("jsonMap").toString(),Map.class);
}else{
accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret=a06e8ca9ea174a15b606d3db94e162e8";
byte[] httpResult = HttpUtil.httpGet(accessTokenUrl, null);
String httpResultJson = null;
httpResultJson = new String(httpResult, "utf-8");
jsonMap = JSON.parseObject(httpResultJson, Map.class);
String access_token = jsonMap.get("access_token")+"";
String expires_in = jsonMap.get("expires_in")+"";
if(StringUtil.isNotBlank(access_token) && StringUtil.isNotBlank(expires_in)){
String accessTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
byte[] httpResult2 = HttpUtil.httpGet(accessTicketUrl, null);
httpResultJson = new String(httpResult2, "utf-8");
jsonMap.clear();
jsonMap = JSON.parseObject(httpResultJson, Map.class);
jsonMap.put("access_token",access_token);
jsonMap.put("appId",appId);
redisUtil.set("jsonMap",JSON.toJSONString(jsonMap),Long.valueOf(expires_in));
}
}
}catch (Exception e) {
logger.error("wechat配置文件异常", e);
return jsonMap;
}
return jsonMap;
}
签名的方法:
上面代码已经写完了,最后发现,点击分享弹出H5窗口分享微信居然不成功、再点击右上角的那个弹出来的微信窗口点击分享朋友居然成功了,做到这里我吐血了,居然微信把监听事件已经绑定到了自带的三个右上角弹出来的窗口分享中,自己开发的H5弹出来的不支持,只能改变右上角的那个分享,所以到最后还是放弃了这个开发,好在产品部优化了分享这个功能,经过这次研究还是蛮有收获的。
遇到的问题:
1.分享的链接Link 域名必须要绑定微信公众号JS接口中
2.H5自己开发的页面分享不支持监听事件,只能使用微信自带的弹窗
3.微信测试这个比较烦人,对环境比较苛刻,一定要绑定域名,切记!!!