在微信客户端中打开页面,点击右上角分享到朋友圈或者分享给朋友时候,希望可以自定义【抬头+描述+图片+链接】,而不是微信去截取当前页面的链接地址(有可能带一堆参数,而且每个整个活动中每个页面的地址可能都不一样),截取当前页面的title等。
示意图,如下:(上半部分为分享给朋友的样式,下半部分为分享到朋友圈的样式)
这个js将被需要的页面依赖,上线前可以修改这个js中的【抬头+描述+图片+链接】
//微信分享 var wxShare = (function () { var appId = 'wx2767b3767363f90e';//公众号APPID var title = '德邦证券放“大招”猴年春晚发红包';//抬头 var desc = '没有模糊玻璃,无需花钱即可抢红包咯~';//描述 var imgUrl = 'http://test.tebon.com.cn/trans/images/award/img_hb.gif';//图片 var link = 'http://test.tebon.com.cn/trans/award/manager/index.htm';//链接 var timestamp = '';//时间戳 后台生成 var nonceStr = '';//随机串 后台生成 var signature = '';//签名 后台生成 var _init = function (_title, _desc) { getSign(); }; var getSign = function () { var reurl = location.href.split('#')[0]; var para = {appid: appId, url: reurl}; $.ajax({ type: "post", data: para, async: true, url: contextPath + "/award/wxShare/wxShareSign.htm", dataType: "json", success: function (data) { if (data.result == "true") { timestamp = data.timestamp; nonceStr = data.noncestr; signature = data.signature; wxConfig(); wxReady(); wxError(); } else { alert(data.message); } } , error: function (xhr, errorType, error) { } } ) ; }; var wxConfig = function () { wx.config({ debug: false, appId: appId, timestamp: timestamp, nonceStr: nonceStr, signature: signature, jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage' ] }); }; var wxReady = function () { wx.ready(function () { //发送给朋友 wx.onMenuShareAppMessage({ title: title, desc: desc, link: link, imgUrl: imgUrl, trigger: function (res) { //alert('用户点击发送给朋友'); }, success: function (res) { //alert('已分享');跳转到排行榜页面 //window.location.href = 'revenue_ranking.html'; }, cancel: function (res) { //alert('已取消'); }, fail: function (res) { //alert(JSON.stringify(res)); } }); //分享到朋友圈 wx.onMenuShareTimeline({ title: title, desc: desc, link: link, imgUrl: imgUrl, trigger: function (res) { //alert('用户点击分享到朋友圈'); }, success: function (res) { //alert('已分享'); //window.location.href = 'revenue_ranking.html'; }, cancel: function (res) { //alert('已取消'); }, fail: function (res) { //alert(JSON.stringify(res)); } }); }); }; var wxError = function () { wx.error(function (res) { alert(res.errMsg); }); }; return { init: _init }; })(); //执行init wxShare.init();
微信要求,生成签名,需要在服务端生成,所以这个服务端类的用途是用于生成签名。
逻辑如下:
/* * @(#)GateInfoAction.java 1.0 2014-7-25下午4:17:49 * * 德邦证券股份有限公司 * Copyright (c) 2012-2014 Tebon, Inc. All rights reserved. */ package com.tebon.trans.web.award; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.tebon.sirius.cache.CacheFactoryProvider; import com.tebon.sirius.cache.ICache.CacheType; import com.tebon.sirius.utils.HttpClientUtils; import com.tebon.sirius.utils.JSonUtils; import com.tebon.sirius.utils.RandomGUIDUtils; import com.tebon.trans.web.BaseAbstractController; /** * 大转盘抽奖接口相关功能 * * @author liyb */ @Controller @RequestMapping("/award/wxShare/") public class AwardWxShareController extends BaseAbstractController { /** * 放redis缓存微信分享ticket 并且设置失效时间(毫秒数) */ private static final String REDIS_WX_SHARE_TICKET = "redis.wx.share.ticket"; private static final String REDIS_WX_SHARE_TICKET_DEAD_DATETIME = "redis.wx.share.ticket.dead.datetime"; @Autowired CacheFactoryProvider cacheFactoryProvider; /** * 微信分享生成签名逻辑 * @return */ @RequestMapping(value = "/wxShareSign") public @ResponseBody Map<String, String> testWxShareSign(HttpServletRequest request) throws Exception { /** * 微信分享生成签名逻辑 * 0.准备结果MAP */ Map<String, String> map = new HashMap<String, String>(); /** * 1.如果缓存中有ticket,而且没有过期,则直接用ticket */ String ticket = (String)cacheFactoryProvider.getCacheProvider(CacheType.REDIES).get(REDIS_WX_SHARE_TICKET); Long deadDateTime = (Long)cacheFactoryProvider.getCacheProvider(CacheType.REDIES).get(REDIS_WX_SHARE_TICKET_DEAD_DATETIME); log.info("从redis获取ticket:" + ticket); if(StringUtils.isBlank(ticket) || new Date().getTime() > deadDateTime.longValue()){ /** * 2.否则获取token * https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx2767b3767363f90e&secret=e42c1933553c1da62187d76379284fd1 * { * "access_token": "E-zdrtVh4qgrNO5n0f2NWmM0z0_XxYey_2X6jHaiDFp7SQl-sMK4aoZT1FDAKO-_U9EF2h7pHe7i0WIuKsVp8RA9qaN7n-zZ9wJx91PB-RMARLdAIALCW", * "expires_in": 7200 * } */ String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx2767b3767363f90e&secret=e42c1933553c1da62187d76379284fd1"; String jsonString = HttpClientUtils.getWebContentByGet(url); log.info("获取access_token返回:" + jsonString); WxShareResponse wxShareResponse = JSonUtils.nonDefaultMapper().fromJson(jsonString, WxShareResponse.class); if(StringUtils.isBlank(wxShareResponse.getAccess_token())){ map.put("result", "false"); map.put("message", "微信分享准备失败!"); return map; } /** * 3.再根据token获取ticket * https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=E-zdrtVh4qgrNO5n0f2NWmM0z0_XxYey_2X6jHaiDFp7SQl-sMK4aoZT1FDAKO-_U9EF2h7pHe7i0WIuKsVp8RA9qaN7n-zZ9wJx91PB-RMARLdAIALCW&type=jsapi * { * "errcode": 0, * "errmsg": "ok", * "ticket": "sM4AOVdWfPE4DxkXGEs8VDqK83ldYtSiGPegbeUXAElohlSKVPXjtbn6JqV5T2Nta1pqIl2b-uh1sapcge3SfQ", * "expires_in": 7200 * } */ url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + wxShareResponse.getAccess_token() + "&type=jsapi"; jsonString = HttpClientUtils.getWebContentByGet(url); log.info("获取ticket返回:" + jsonString); wxShareResponse = JSonUtils.nonDefaultMapper().fromJson(jsonString, WxShareResponse.class); if(StringUtils.isBlank(wxShareResponse.getTicket())){ map.put("result", "false"); map.put("message", "微信分享准备失败!"); return map; } /** * 4.设置ticket缓存,设置失效的毫秒数,当前时间+7200-100秒,以免正好差个几秒钟的误差 */ ticket = wxShareResponse.getTicket(); long expiresIn = wxShareResponse.getExpires_in(); cacheFactoryProvider.getCacheProvider(CacheType.REDIES).put(REDIS_WX_SHARE_TICKET, ticket); cacheFactoryProvider.getCacheProvider(CacheType.REDIES).put(REDIS_WX_SHARE_TICKET_DEAD_DATETIME, new Date().getTime() + (expiresIn - 100)*1000); } /** * 5.生成签名,返回前端 */ long timestamp = new Date().getTime(); String appid = request.getParameter("appid"); String url = request.getParameter("url"); String noncestr = new RandomGUIDUtils().toString(); log.info("timestamp=" + timestamp + ",appid=" + appid + ",url=" + url + ",noncestr=" + noncestr + ",ticket=" + ticket); String signString = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url; String sign = sha1Digest(signString); map.put("result", "true"); map.put("timestamp", StringUtils.EMPTY + timestamp); map.put("noncestr", noncestr); map.put("signature", sign); return map; } public String sha1Digest(String signString) { try { MessageDigest digest = java.security.MessageDigest .getInstance("SHA"); digest.update(signString.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字节数组转换为 十六进制 数 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } } /** * <dl> * <dt><b>Title:</b></dt> * <dd> * none * </dd> * <dt><b>Description:微信返回数据对象</b></dt> * <dd> * <p>none * </dd> * </dl> * * @author Administrator * @version 1.0, 2016年1月28日 * @since trans * */ class WxShareResponse { String access_token; long expires_in; String errcode; String errmsg; String ticket; public String getAccess_token() { return access_token; } public void setAccess_token(String access_token) { this.access_token = access_token; } public long getExpires_in() { return expires_in; } public void setExpires_in(long expires_in) { this.expires_in = expires_in; } public String getErrcode() { return errcode; } public void setErrcode(String errcode) { this.errcode = errcode; } public String getErrmsg() { return errmsg; } public void setErrmsg(String errmsg) { this.errmsg = errmsg; } public String getTicket() { return ticket; } public void setTicket(String ticket) { this.ticket = ticket; } }
需要分享的页面的开发,按道理整个活动过程中的每个页面,都要按如下方法来开发,达到自定义分享【抬头+描述+图片+链接】的效果。
在页面的head头部加入以下代码
<head> <!-- 微信分享依赖js --> <script> var contextPath = "${rc.contextPath}"; </script> <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script src="${Application["trans.static.resource.url"]}js/jquery-1.11.1.min.js"></script> <script src="${Application["trans.static.resource.url"]}js/wx-share.js"></script> </head>