地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
首先在页面引用微信分享的js,注意js的版本,如果分享的链接是https开头的,建议js的版本在1.4.0以上 //res.wx.qq.com/open/js/jweixin-1.4.0.js
微信分享可以用初始化加载的方式或者ajax异步加载的方式
1.下面是页面加载完毕后即完成微信分享参数初始化的方法
初始化加载的意思就是,在页面加载完毕后,所有的参数已经完成赋值,可以直接进行微信分享,异步的化就是动态获取分享参数进行赋值(主要用于每次分享的文案有变化的情况)
(function(win, undefined) {
var $ = win.jQuery;
if (typeof hideMenuItems != "undefined" && hideMenuItems) {
wx.config({
debug: false,
appId: appId,
timestamp: timestamp,
nonceStr: noncestr,
signature: signature,
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'hideMenuItems']
});
} else {
wx.config({
debug: false,
appId: appId,
timestamp: timestamp,
nonceStr: noncestr,
signature: signature,
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage']
});
}
wx.ready(function () {
var shareData = {
title: title,
desc: desc,
link: url,
imgUrl: image,
success: function (res) {
$.ajax({
url: "/app/shareCallback?status=" + share,
type: "GET",
dataType: 'json',
success: function (d) {
}
});
},
cancel: function (res) {
},
fail: function (res) {
}
};
wx.onMenuShareTimeline(shareData);
wx.onMenuShareAppMessage(shareData);
if (typeof hideMenuItems != "undefined" && hideMenuItems) {
var val = hideMenuItemsValue.split(",");
wx.hideMenuItems({
menuList: val // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
});
}
});
if (typeof WeixinJSBridge != "undefined") {
var imgUrl = image;
var lineLink = url;
var descContent = desc;
var shareTitle = title;
var appid = appId;
function shareFriend() {
WeixinJSBridge.invoke('sendAppMessage', {
"appid": appid,
"img_url": imgUrl,
"link": lineLink,
"desc": descContent,
"title": shareTitle
}, function (res) {
WeixinJSBridge.call('closeWindow');
if (res.err_msg != 'send_app_msg:cancel' && res.err_msg != 'share_timeline:cancel') {
$.ajax({
url: "/app/shareCallback?status=" + share,
type: "GET",
dataType: 'json',
success: function (d) {
if (d.ret == 1) {
//分享朋友 回调
}
}
}
});
}
})
}
function shareTimeline() {
WeixinJSBridge.invoke('shareTimeline', {
"img_url": imgUrl,
"link": lineLink,
"desc": descContent,
"title": shareTitle
}, function (res) {
WeixinJSBridge.call('closeWindow');
if (res.err_msg != 'send_app_msg:cancel' && res.err_msg != 'share_timeline:cancel') {
$.ajax({
url: "/app/shareCallback?status=" + share,
type: "GET",
dataType: 'json',
success: function (d) {
if (d.ret == 1) {
//分享 朋友圈 回调
}
}
}
});
}
});
}
// 当微信内置浏览器完成内部初始化后会触发WeixinJSBridgeReady事件。
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
// 发送给好友
WeixinJSBridge.on('menu:share:appmessage', function (argv) {
shareFriend();
});
// 分享到朋友圈
WeixinJSBridge.on('menu:share:timeline', function (argv) {
shareTimeline();
});
}, false);
}
})(window);
可以看到微信的配置中需要用到的几个参数,appId,timestamp,nonceStr,signature,jsApiList
这几个参数,需要在后台创建分享时传入页面。
//创建分享的参数
public static void createShare(HttpServletRequest request, User user,String acivityName,String title,String desc,String img,String url){
String query = request.getQueryString();
String requestUrl = null;
if(StringUtils.isEmpty(query)){
requestUrl = request.getRequestURL().toString();
}else{
requestUrl = request.getRequestURL() + "?" + query;
}
Map ret = WeiXinServiceUtil.sign(WeiXinServiceUtil.serviceTestAppId,WeiXinServiceUtil.serviceTestSecret,requestUrl);
request.setAttribute("appId", ret.get("appId"));
request.setAttribute("timestamp", ret.get("timestamp"));
request.setAttribute("nonceStr", ret.get("nonceStr"));
request.setAttribute("signature", ret.get("signature"));
String activityRecordId = request.getParameter("activityRecordId");
if(ValidateUtil.isNumber(activityRecordId)){
request.setAttribute("share", acivityName+java.util.UUID.randomUUID().toString()+"&activityRecordId=" + activityRecordId + "&type=jxq&userId="+user.getUserId());
}else{
request.setAttribute("share", acivityName+java.util.UUID.randomUUID().toString());
}
request.setAttribute("title", title);
request.setAttribute("desc", desc);
request.setAttribute("image", img);
int userId = 0;
if(user != null){
userId = user.getUserId();
url += "&ref=" + IDEncryptor.getInstance().encryptWithoutException(userId);
}
request.setAttribute("appurl", url);
try{
request.setAttribute("apptitle", java.net.URLEncoder.encode((String)request.getAttribute("title"), "UTF-8"));
request.setAttribute("appdesc", java.net.URLEncoder.encode((String)request.getAttribute("desc"), "UTF-8"));
request.setAttribute("url", url);
url = java.net.URLEncoder.encode(url, "utf-8");
Boolean needWeiChatInfo = (Boolean)request.getAttribute("needWeiChatInfo");
String platSource = request.getAttribute("platSource").toString();
if(needWeiChatInfo != null && needWeiChatInfo == true && !platSource.equals("3")){
//url = url.replace("&","%26");
String tq = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeiXinServiceUtil.serviceTestAppId+ "&redirect_uri=" + url +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
request.setAttribute("url", tq);
request.setAttribute("appurl", tq);
}
}catch(Exception exp){
logger.error(exp.getMessage(),exp);
}
}
//微信验签方法
public synchronized static Map sign(String appId,String secret,String url) {
Map ret = new HashMap();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
JedisUtil jedisUtil = JedisUtil.getInstance();
String shareKey = jedisUtil.getJedisString(RedisConstant.REDIS_WX_SHARE_TOKEN_KEY);
//if(last_access == 0 || (System.currentTimeMillis() - last_access) > 2*3600*1000L){
if(StringUtil.isEmpty(shareKey)){
jsapi_ticket = httpToken(appId,secret);
if(StringUtils.isEmpty(jsapi_ticket)){
jsapi_ticket = httpToken(appId,secret);
if(StringUtils.isEmpty(jsapi_ticket)){
return ret;
}
}
jedisUtil.setStringAndTime(RedisConstant.REDIS_WX_SHARE_TOKEN_KEY, jsapi_ticket, RedisConstant.REDIS_WX_SHARE_TOKEN_KEY_TIME);
}else{
jsapi_ticket = shareKey;
}
boolean notHTTPS = url.startsWith("http://" + Config.MOBILE_DOMAIN);
if(notHTTPS && !Config.DEBUG) {
url = url.replace("http", "https");
}
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsapi_ticket +
"&noncestr=" + nonce_str +
"×tamp=" + timestamp +
"&url=" + url;
try
{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
ret.put("appId", appId);
return ret;
}
/**
* ajax请求获取分享参数
* @param request
* @param user
* @param acivityName
* @param title
* @param desc
* @param img
* @param url
* @param retMap
*/
public static void ajaxCreateShare(HttpServletRequest request, User user,String acivityName,String title,String desc,String img,String url, Map retMap){
String query = request.getParameter("htmlUrl");
String requestUrl = null;
if(StringUtil.isNotEmpty(query)){
requestUrl = query;
}else{
query = request.getQueryString();
if(StringUtils.isEmpty(query)){
requestUrl = request.getRequestURL().toString();
}else{
requestUrl = request.getRequestURL() + "?" + query;
}
}
Map ret = WeiXinServiceUtil.sign(WeiXinServiceUtil.serviceTestAppId,WeiXinServiceUtil.serviceTestSecret,requestUrl);
retMap.put("appId", ret.get("appId"));
retMap.put("timestamp", ret.get("timestamp"));
retMap.put("nonceStr", ret.get("nonceStr"));
retMap.put("signature", ret.get("signature"));
retMap.put("share", acivityName+java.util.UUID.randomUUID().toString());
retMap.put("title", title);
retMap.put("desc", desc);
retMap.put("image", img);
retMap.put("appurl", url);
try{
retMap.put("apptitle", java.net.URLEncoder.encode((String)retMap.get("title"), "UTF-8"));
retMap.put("appdesc", java.net.URLEncoder.encode((String)retMap.get("desc"), "UTF-8"));
retMap.put("url", url);
}catch(Exception exp){
logger.error(exp.getMessage(),exp);
}
}
异步获取分享参数的时候,需要注意传入当前要分享的页面的地址,微信验签时,验签的地址要与当前页面的地址保持一直,否则会导致微信校验失败,也就是分享出去的参数有误分享失败(坑)。
微信开发者工具,可以帮助我们模拟生产环境校验参数是否可以通过,当然你要准备好appId和可用的域名,便于微信校验
下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
微信无感授权可以获取用户的一个唯一标识openid ,可以对微信用户和平台用户进行关联。以我们的项目为例子,可以通过openid判断用户是否有进行过公众号关注,是否绑定平台等信息。
在我们分享的时候,如果需要进行分享并判断微信用户是否有相关操作的时候,
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid+ "&redirect_uri=" + url +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"
前面是无感授权的链接,redirect_uri 是分享后要跳转的链接
就需要向微信发送请求获取该openid,但是神奇的是微信竟然不给自己的链接进行校验通过,也就是说分享出去的链接必须是本项目的链接才可以。
要想解决这个问题,可以通过项目中转链接实现跳转,也可以通过按钮跳转来实现。
也就是说通过一个中间请求去重定向到我们带授权的请求就可以了。(如果有更好的方法,或者微信在后续的版本中解决了这个问题,请联系我,谢谢!)
本人水平有限,如有不当之处欢迎各位批评指正!