跳至内容
wiki
用户工具
登录
站点工具
工具
显示页面
修订记录
反向链接
最近更改
媒体管理器
网站地图
登录
最近更改
媒体管理器
网站地图
您的足迹:
分享:技术:微信:微信分享实现
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
====== 微信分享实现 ====== ===== 需求 ===== 在微信客户端中打开页面,点击右上角**分享到朋友圈**或者**分享给朋友**时候,希望可以自定义【抬头+描述+图片+链接】,而不是微信去截取当前页面的链接地址(有可能带一堆参数,而且每个整个活动中每个页面的地址可能都不一样),截取当前页面的title等。 示意图,如下:(上半部分为**分享给朋友**的样式,下半部分为**分享到朋友圈**的样式) {{:分享:技术:微信:1.png?500|}} ===== 准备 ===== - 服务号账号:cinvestors@tebon.com.cn - 登录微信服务号后台,查看基础设置中,获得:AppID(应用ID)+AppSecret(应用密钥) - 确认已经申请以下接口 - 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 - 获取“分享给朋友”按钮点击状态及自定义分享内容接口 ===== 基础开发 ===== ==== wx-share.js ==== 这个js将被需要的页面依赖,上线前可以修改这个js中的【抬头+描述+图片+链接】 <file js wx-share.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(); </file> ==== AwardWxShareController.java ==== 微信要求,生成签名,需要在服务端生成,所以这个服务端类的用途是用于生成签名。 逻辑如下: - 如果缓存中有ticket,而且没有过期,则直接用ticket - 否则获取token - 再根据token获取ticket - 设置ticket缓存,设置失效的毫秒数,当前时间+7200-100秒,以免正好差个几秒钟的误差 - 生成签名,返回前端 <file java AwardWxShareController.java> /* * @(#)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; } } </file> ===== 分享页开发 ===== 需要分享的页面的开发,按道理整个活动过程中的每个页面,都要按如下方法来开发,达到自定义分享【抬头+描述+图片+链接】的效果。 在页面的head头部加入以下代码 <file html> <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> </file> ===== 效果 ===== ==== 分享给朋友 ==== {{:分享:技术:微信:3.jpg?400|}} {{:分享:技术:微信:2.jpg?400|}} ==== 分享到朋友圈 ==== {{:分享:技术:微信:4.jpg?400|}} {{:分享:技术:微信:5.jpg?400|}}
分享/技术/微信/微信分享实现.txt
· 最后更改: 2016/01/29 10:34 由
gxx
页面工具
显示页面
修订记录
反向链接
回到顶部