SpringBoot JS-SDK自定义微信分享的实现
前言
在介绍使用微信自定义分享前,我们来先了解一下什么是自定义分享?
访问自定义微信外链地址页面,点击红色框位置进行分享给朋友或者朋友圈,具体操作如下图所示:
分享后图文消息如下图所示:
我们要做的就是自定义下图所示中红框中的信息。
闲话少说,接下来就正式开始自定义分享实战环节!
自定义分享实战
第一步需要先申请接口测试号并进行JS接口安全域名设置
访问如下链接进行接口测试号申请。点击访问选择接口测试号申请,如下图所示:
或者直接访问 :申请测试账号页面 如下图所示:
点击登录进行扫码登录,如下图所示:
登录后如下图所示:
windows系统在 hosts 文件中配置回环地址的域名
第二步是下载微信web开发者工具,可以在PC 进行测试。
点击访问下载页面如下图所示:
傻瓜式一步一步安装即可。
第三步 看微信操作教程并完成代码实现
点击访问微信JS-SDK说明文档 如下图所示:
JSSDK使用步骤
步骤一:绑定域名(上面已经操作了)
步骤二:引入JS文件(下面实战代码中会介绍到如何使用)
步骤三:通过config接口注入权限验证配置(下面实战代码中会介绍到如何使用)
步骤四:通过ready接口处理成功验证(这里就不详细介绍了具体内容请参看微信文档查看)
步骤五:通过error接口处理失败验证(这里就不详细介绍了具体内容请参看微信文档查看)
上面步骤步骤三中的 signature是一个重要的参数,生成它需要获取 jsapi_ticket,而生成 jsapi_ticket 需要通过 access_token
。
获取signature流程如下:
- 获取 access_token 然后根据 access_token 获取 jsapi_ticket 。
- 排序 noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳),url(当前网页的URL,不包含#及其后面部分)4个参数拼接例如:noncestr=XX&jsapi_ticket=XX&jtimestamp=XX&jurl=XX
- 然后通过sha1加密拼接的4个参数获取到signature
可能你对操作流程还是看不懂,没有关系可以直接参考代码实现,接下来就是代码实现:
初始化微信JSSDK配置信息 Controller 内容如下:
@RestController @RequestMapping("/weixin") public class WeiXinDemoController { @Autowired private WeiXinService weiXinService; /** * 初始化微信JSSDK配置信息 * @param request * @param response * @return * @throws Exception */ @RequestMapping("/initWXJSSDKConfigInfo") public String initWXJSConfig (HttpServletRequest request,HttpServletResponse response) throws Exception{ String shareUrl = request.getParameter("shareUrl");//分享的URL Map map = weiXinService.initJSSDKConfigInfo(shareUrl); String json = weiXinService.mapToJson(map); return json; } }
初始化JSSDK配置信息,配置信息有:noncestr(随机字符串)、有效的jsapi_ticket、timestamp(时间戳)、shareUrl(当前网页的URL,不包含#及其后面部分)appid(公众号 appid)。
/** * 初始化JSSDK配置信息 * @param shareUrl * @return * @throws Exception */ public Map initJSSDKConfigInfo(String shareUrl) throws Exception { String accessToken = this.getJSSDKAccessToken(); String jsapiTicket = this.getJSSDKJsapiTicket(accessToken); String timestamp = Long.toString(System.currentTimeMillis() / 1000); String nonceStr = UUID.randomUUID().toString(); String signature = this.buildJSSDKSignature(jsapiTicket,timestamp,nonceStr,shareUrl); Map<String,String> map = new HashMap<String,String>(); map.put("shareUrl", shareUrl); map.put("jsapi_ticket", jsapiTicket); map.put("nonceStr", nonceStr); map.put("timestamp", timestamp); map.put("signature", signature); map.put("appid", weiXinConfig.getAppID()); return map; }
获取 JSSDK access_token 方法。
public String getJSSDKAccessToken() { String token = null; String url = JSSDK_ACCESSTOKEN.replaceAll("APPID", weiXinConfig.getAppID()).replaceAll("APPSECRET", weiXinConfig.getAppsecret()); String json = postRequestForWeiXinService(url); Map map = jsonToMap(json); if (map != null) { token = (String) map.get("access_token"); } return token; }
获取 JSSDK jsapi_ticket 方法。
public String getJSSDKJsapiTicket(String token) { String url = JSSDK_GETTICKET.replaceAll("ACCESS_TOKEN", token); String json = postRequestForWeiXinService(url); Map map = jsonToMap(json); String jsapi_ticket = null; if (map != null) { jsapi_ticket = (String) map.get("ticket"); } return jsapi_ticket; }
拼接 noncestr(随机字符串), 有效的jsapi_ticket、 timestamp(时间戳)、url(当前网页的URL,不包含#及其后面部分)并通过sha1进行加密。
/** * 构建分享链接的签名。 * @param ticket * @param nonceStr * @param timeStamp * @param url * @return * @throws Exception */ public static String buildJSSDKSignature(String ticket,String timestamp,String nonceStr ,String url) throws Exception { String orderedString = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url; return sha1(orderedString); } /** * sha1 加密JSSDK微信配置参数获取签名。 * * @param signature * @param timestamp * @param nonce * @return */ public static String sha1(String orderedString) throws Exception { String ciphertext = null; MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] digest = md.digest(orderedString.getBytes()); ciphertext = byteToStr(digest); return ciphertext.toLowerCase(); } /** * 将字节数组转换为十六进制字符串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 将字节转换为十六进制字符串 * * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; }
基础工具方法如下:
public String mapToJson(Map map){ Gson gson = new Gson(); String json = gson.toJson(map); return json; } private Map jsonToMap(String json) { Gson gons = new Gson(); Map map = gons.fromJson(json, new TypeToken<Map>(){}.getType()); return map; } private String postRequestForWeiXinService(String getAccessTokenUrl) { ResponseEntity<String> postForEntity = restTemplate.postForEntity(getAccessTokenUrl, null, String.class); String json = postForEntity.getBody(); return json; } private String getRequestForWeiXinService(String getUserInfoUrl) { ResponseEntity<String> postForEntity = restTemplate.getForEntity(getUserInfoUrl.toString(), String.class); String json = postForEntity.getBody(); return json; }
wxShare.js 主要是获取JSSDK配置信息并定义分享功能处理。具体代码如下:
//alert(window.location.href.split('#')[0]);/***用于获得当前连接url用**/ /***用户点击分享到微信圈后加载接口接口*******/ $.post("/weixin/initWXJSSDKConfigInfo",{"shareUrl":window.location.href.split('#')[0]},function(data,status){ data=eval("("+data+")"); wx.config({ debug: false, appId: data.appid, timestamp:data.timestamp, nonceStr:data.nonceStr, signature:data.signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'hideOptionMenu', ] }); var shareTitle = $("#wx_share_span").data("shareTitle"); if(!shareTitle){ shareTitle = $("title").html(); } var shareImg = $("#wx_share_span").data("shareImg"); if(!shareImg){ //shareImg = common.bp()+'/m_images/shareImg.jpg'; } var shareLink = $("#wx_share_span").data("shareLink"); if(!shareLink){ shareLink = window.location.href.split('#')[0]; } var shareDesc = $("#wx_share_span").data("shareDesc"); if(!shareDesc){ shareDesc = $("meta[name=description]").attr("content"); } wx.ready(function(){ // alert("准备分享"); wx.onMenuShareTimeline({ title : shareTitle, // 分享标题 link : shareLink, // 分享链接 imgUrl : shareImg, // 分享图标 success : function() { // 用户确认分享后执行的回调函数 //alert("分享成功"); }, cancel : function() { // 用户取消分享后执行的回调函数 //alert("分享取消"); } }); //wx.hideOptionMenu();/***隐藏分享菜单****/ wx.onMenuShareAppMessage({ title: shareTitle, // 分享标题 desc: shareDesc, // 分享描述 link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: shareImg, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareQQ({ title: shareTitle, // 分享标题 desc: shareDesc, // 分享描述 link: shareLink, // 分享链接 imgUrl: shareImg, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareWeibo({ title: shareTitle, // 分享标题 desc: shareDesc, // 分享描述 link: shareLink, // 分享链接 imgUrl: shareImg, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareQZone({ title: shareTitle, // 分享标题 desc: shareDesc, // 分享描述 link: shareLink, // 分享链接 imgUrl: shareImg, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); }); });
分享页面该页面需要引入wxShare.js和jweixin-1.2.0.js,并且通过在隐藏的span标签上定义自定义分享的内容,具体代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script src="/jquery-1.8.3.min.js" type="text/javascript" ></script> </head> <body> <span id="wx_share_span" style="display: none"></span> <script type="text/javascript"> $(document).ready(function(){ $("#wx_share_span").data("shareTitle", "桌前明月教你玩微信公众号自定义分享"); $("#wx_share_span").data("shareDesc", "保证学会哈!"); //$("#wx_share_span").data("shareLink", "/weixinshare.html"); //$("#wx_share_span").data("shareImg", "/banner.jpg"); }); </script> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <script type="text/javascript" src="/wxShare.js"></script> </body> </html>
测试
访问:http://www.zhuoqianmingyue.com:8090/weixinshare.html 未引入 wxShare.js 的测试结果如下:
引入 wxShare.js 的测试结果如下:
一般情况下我们通过接口测试号配置成测试环境域名,上述测试通过后就可以在正式服务号上配置JS接口安全域名,顺便在把我们项目配置的 appid 换成服务号的 appid 即可。具体操作如下:
小结
微信自定义分享具体操作步骤如下:
- 定义获取JS-SDK配置信息接口
- 定义页面初始化调用JS-SDK配置信息接口 js 代码和定义分享接口js代码
- 分享页面引入 jweixin-1.2.0.js和 调用JS-SDK配置信息的js文件
三步中最为总要的就是第一步:定义获取JS-SDK配置信息接口,这个接口需要获取jsapi_ticket 并通过和配置信息参数一起生成签名 signature。
在这里再三强调一下,微信提供操作文档一定要多看几篇,因为很多细节都在文档中进行了说明。当你把微信提供操作文档看透,你就会觉得其实就是个API 调用而已。
代码示例
具体代码示例请查看我的GitHub 仓库 springbootexamples 中的 spring-boot-2.x-weixin 查看。
GitHub:https://github.com/zhuoqianmingyue/springbootexamples
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。