本文主要介紹了SpringBoot 基於JS-SDK實現自定義微信分享,並通過本地測試的方式進行調試,文中通過微信實現分享流程及示例代碼進行非常詳細的介紹,希望本文對開發愛好者學習或者工作具有一定的參考學習價值,需要的朋友們下面隨着小編來一起學習學習吧!
一 准備工作
1.微信公眾平台appID和appsecret
2.微信開發文檔(相當爛,但一定要看)
3.微信web開發者工具
二 開發步驟
1.申請接口測試號並進行JS接口安全域名設置
接口測試號申請。點擊訪問 ,選擇接口測試號申請,如下圖所示:
或者直接訪問 :申請測試賬號頁面 如下圖所示:
點擊登錄進行掃碼登錄,如下圖所示:
登錄后如下圖所示:
配置JS接口安全域名
2.windows下配置本地回環地址
找到windows系統中 hosts 文件,配置回環地址的域名,C:\Windows\System32\drivers\etc
配置回環地址
3. 下載微信web開發者工具,可以在PC 進行測試
下載微信web開發者工具,點擊訪問下載頁面 如下圖所示:
下載完成之后,安裝微信web開發者工具,一步一步傻瓜式安裝。
4.參照微信開發文檔實現
點擊訪問微信JS-SDK說明文檔 如下圖所示:
JSSDK使用步驟
步驟一:綁定域名(上面已經操作了)
步驟二:引入JS文件(下面實戰代碼中會介紹到如何使用)
步驟三:通過config接口注入權限驗證配置(下面實戰代碼中會介紹到如何使用)
步驟四:通過ready接口處理成功驗證
步驟五:通過error接口處理失敗驗證
接口調用說明
5.代碼實現
上面步驟步驟三中的 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配置信息
1 @Controller 2 @RequestMapping("/weixin") 3 public class WeiXinDemoController { 4 5 @Autowired 6 private WeiXinService weiXinService; 7 @Autowired 8 private WXConfig weiXinConfig; 9 10 11 /** 12 * 初始化微信JSSDK配置信息 13 * @param request 14 * @param response 15 * @param shareUrl 分享地址 16 * @return 17 * @throws Exception 18 */ 19 @RequestMapping("/initWXJSSDKConfigInfo") 20 @ResponseBody 21 public String initWXJSConfig (HttpServletRequest request, HttpServletResponse response, String shareUrl) throws Exception{ 22 Map map = weiXinService.initJSSDKConfigInfo(shareUrl); 23 String json = weiXinService.mapToJson(map); 24 return json; 25 } 26 }
初始化JSSDK配置信息,配置信息有:noncestr(隨機字符串)、有效的jsapi_ticket、timestamp(時間戳)、shareUrl(當前網頁的URL,不包含#及其后面部分)appid(公眾號 appid)
1 /** 2 * @description 初始化JSSDK配置信息 3 * @param shareUrl 分享的url地址 4 * @return 5 * @throws Exception 6 */ 7 public Map initJSSDKConfigInfo(String shareUrl) throws Exception { 8 String accessToken = this.getJSSDKAccessToken(); 9 String jsapiTicket = this.getJSSDKJsapiTicket(accessToken); 10 String timestamp = Long.toString(System.currentTimeMillis() / 1000); 11 String nonceStr = UUID.randomUUID().toString(); 12 String signature = this.buildJSSDKSignature(jsapiTicket,timestamp,nonceStr,shareUrl); 13 Map<String,String> map = new HashMap<String,String>(); 14 map.put("shareUrl", shareUrl); 15 map.put("jsapi_ticket", jsapiTicket); 16 map.put("nonceStr", nonceStr); 17 map.put("timestamp", timestamp); 18 map.put("signature", signature); 19 map.put("appid", weiXinConfig.getAppID()); 20 return map; 21 }
獲取 JSSDK access_token
1 /** 2 * @description 獲取JSSDK的認證token 3 * @return 返回JSSDK的認證token 4 */ 5 public String getJSSDKAccessToken() { 6 String token = null; 7 String url = WXContants.JSSDK_ACCESSTOKEN.replaceAll(WXContants.REPLACE_FEILD_APPID, 8 weiXinConfig.getAppID()).replaceAll(WXContants.REPLACE_FEILD_APPSECRET, 9 weiXinConfig.getAppsecret()); 10 String json = postRequestForWeiXinService(url); 11 Map map = jsonToMap(json); 12 if (map != null) { 13 token = (String) map.get("access_token"); 14 } 15 return token; 16 }
獲取 JSSDK jsapi_ticket
1 /** 2 * @description 獲取JSSDK的ticket 3 * @param token JSSDK的認證token 4 * @return 返回JSSDK的ticket 5 */ 6 public String getJSSDKJsapiTicket(String token) { 7 String url = WXContants.JSSDK_TICKET.replaceAll(WXContants.REPLACE_FEILD_ACCESS_TOKEN, token); 8 String json = postRequestForWeiXinService(url); 9 Map map = jsonToMap(json); 10 String ticket = null; 11 if (map != null) { 12 ticket = (String) map.get("ticket"); 13 } 14 return ticket; 15 }
拼接 noncestr(隨機字符串), 有效的jsapi_ticket、 timestamp(時間戳)、url(當前網頁的URL,不包含#及其后面部分)並通過sha1進行加密
1 /** 2 * @description 構建分享鏈接的簽名 3 * @param ticket 4 * @param nonceStr 5 * @param timestamp 6 * @param url 7 * @return 8 * @throws Exception 9 */ 10 public static String buildJSSDKSignature(String ticket,String timestamp,String nonceStr ,String url) throws Exception { 11 StringBuffer signaStr = new StringBuffer(); 12 signaStr.append("jsapi_ticket=").append(ticket); 13 signaStr.append("&noncestr=").append(nonceStr); 14 signaStr.append("×tamp=").append(timestamp); 15 signaStr.append("&url=").append(url); 16 return sha1(signaStr.toString()); 17 } 18 19 /** 20 * @description sha1 加密JSSDK微信配置參數獲取簽名 21 * @param signaStr 構建分享鏈接的簽名 22 * @return 返回加密簽名 23 */ 24 public static String sha1(String signaStr) throws Exception { 25 MessageDigest md = MessageDigest.getInstance("SHA-1"); 26 byte[] digest = md.digest(signaStr.getBytes()); 27 return byteToStr(digest).toLowerCase(); 28 } 29 /** 30 * @description 將字節數組轉換為十六進制字符串 31 * @param byteArray 待轉換的字節數組 32 * @return 33 */ 34 private static String byteToStr(byte[] byteArray) { 35 String strDigest = ""; 36 for (int i = 0; i < byteArray.length; i++) { 37 strDigest += byteToHexStr(byteArray[i]); 38 } 39 return strDigest; 40 } 41 42 /** 43 * @description 將字節轉換為十六進制字符串 44 * @param mByte 45 * @return 46 */ 47 private static String byteToHexStr(byte mByte) { 48 char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 49 char[] tempArr = new char[2]; 50 tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; 51 tempArr[1] = Digit[mByte & 0X0F]; 52 String s = new String(tempArr); 53 return s; 54 }
基礎工具方法
1 /** 2 * @description 將map轉換成json字符串 3 * @param map map對象 4 * @return json字符串 5 */ 6 public String mapToJson(Map map){ 7 Gson gson = new Gson(); 8 String json = gson.toJson(map); 9 return json; 10 } 11 12 /** 13 * @description 將json字符串轉換成map字符串 14 * @param json json字符串 15 * @return map對象 16 */ 17 private Map jsonToMap(String json) { 18 Gson gons = new Gson(); 19 Map map = gons.fromJson(json, new TypeToken<Map>(){}.getType()); 20 return map; 21 } 22 23 24 private String postRequestForWeiXinService(String accessTokenUrl) { 25 ResponseEntity<String> postForEntity = restTemplate.postForEntity(accessTokenUrl, null, String.class); 26 String json = postForEntity.getBody(); 27 return json; 28 } 29 30 private String getRequestForWeiXinService(String getUserInfoUrl) { 31 ResponseEntity<String> postForEntity = restTemplate.getForEntity(getUserInfoUrl.toString(), String.class); 32 String json = postForEntity.getBody(); 33 return json; 34 }
wxShare.js 主要是獲取JSSDK配置信息並定義分享功能處理。具體代碼如下:
1 /***用戶點擊分享到微信圈后加載接口接口*******/ 2 $.post("/weixin/initWXJSSDKConfigInfo",{"shareUrl":window.location.href.split('#')[0]},function(data,status){ 3 data=eval("("+data+")"); 4 wx.config({ 5 debug: false, 6 appId: data.appid, 7 timestamp:data.timestamp, 8 nonceStr:data.nonceStr, 9 signature:data.signature, 10 jsApiList: [ 11 'checkJsApi', 12 'onMenuShareTimeline', 13 'onMenuShareAppMessage', 14 'onMenuShareQQ', 15 'onMenuShareWeibo', 16 'onMenuShareQZone', 17 //'updateAppMessageShareData', 18 //'updateTimelineShareData', 19 //'hideOptionMenu', 20 ] 21 }); 22 var shareTitle = $("#wx_share_span").data("shareTitle"); 23 if(!shareTitle){ 24 shareTitle = $("title").html(); 25 } 26 var shareImg = $("#wx_share_span").data("shareImg"); 27 if(!shareImg){ 28 //shareImg = common.bp()+'/m_images/shareImg.jpg'; 29 } 30 var shareLink = $("#wx_share_span").data("shareLink"); 31 if(!shareLink){ 32 shareLink = window.location.href.split('#')[0]; 33 } 34 var shareDesc = $("#wx_share_span").data("shareDesc"); 35 if(!shareDesc){ 36 shareDesc = $("meta[name=description]").attr("content"); 37 } 38 wx.ready(function(){ 39 // alert("准備分享"); 40 wx.onMenuShareTimeline({ 41 title : shareTitle, // 分享標題 42 link : shareLink, // 分享鏈接 43 imgUrl : shareImg, // 分享圖標 44 success : function() { 45 // 用戶確認分享后執行的回調函數 46 //alert("分享成功"); 47 }, 48 cancel : function() { 49 // 用戶取消分享后執行的回調函數 50 //alert("分享取消"); 51 } 52 }); 53 //wx.hideOptionMenu();/!***隱藏分享菜單****!/ 54 wx.onMenuShareAppMessage({ 55 title: shareTitle, // 分享標題 56 desc: shareDesc, // 分享描述 57 link: shareLink, // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應的公眾號JS安全域名一致 58 imgUrl: shareImg, // 分享圖標 59 success: function () { 60 // 用戶確認分享后執行的回調函數 61 }, 62 cancel: function () { 63 // 用戶取消分享后執行的回調函數 64 } 65 }); 66 wx.onMenuShareQQ({ 67 title: shareTitle, // 分享標題 68 desc: shareDesc, // 分享描述 69 link: shareLink, // 分享鏈接 70 imgUrl: shareImg, // 分享圖標 71 success: function () { 72 // 用戶確認分享后執行的回調函數 73 }, 74 cancel: function () { 75 // 用戶取消分享后執行的回調函數 76 } 77 }); 78 wx.onMenuShareQZone({ 79 title: shareTitle, // 分享標題 80 desc: shareDesc, // 分享描述 81 link: shareLink, // 分享鏈接 82 imgUrl: shareImg, // 分享圖標 83 success: function () { 84 // 用戶確認分享后執行的回調函數 85 }, 86 cancel: function () { 87 // 用戶取消分享后執行的回調函數 88 } 89 }); 90 Wx.checkJsApi({ 91 jsApiList: ['updateAppMessageShareData','updateTimelineShareData','onMenuShareWeibo'], // 需要檢測的JS接口列表,所有JS接口列表見附錄2, 92 success: function(res) { 93 // 以鍵值對的形式返回,可用的api值true,不可用為false 94 // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} 95 } 96 }); 97 //wx.hideOptionMenu();/!***隱藏分享菜單****!/ 98 wx.updateAppMessageShareData({ 99 title: shareTitle, // 分享標題 100 desc: shareDesc, // 分享描述 101 link: shareLink, // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應的公眾號JS安全域名一致 102 imgUrl: shareImg, // 分享圖標 103 success: function () { 104 // 用戶確認分享后執行的回調函數 105 }, 106 cancel: function () { 107 // 用戶取消分享后執行的回調函數 108 } 109 }); 110 wx.updateTimelineShareData({ 111 title: shareTitle, // 分享標題 112 link: shareLink, // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應的公眾號JS安全域名一致 113 imgUrl: shareImg, // 分享圖標 114 success: function () { 115 // 用戶確認分享后執行的回調函數 116 }, 117 cancel: function () { 118 // 用戶取消分享后執行的回調函數 119 } 120 }); 121 wx.onMenuShareWeibo({ 122 title: shareTitle, // 分享標題 123 desc: shareDesc, // 分享描述 124 link: shareLink, // 分享鏈接 125 imgUrl: shareImg, // 分享圖標 126 success: function () { 127 // 用戶確認分享后執行的回調函數 128 }, 129 cancel: function () { 130 // 用戶取消分享后執行的回調函數 131 } 132 }); 133 }); 134 });
分享頁面該頁面需要引入wxShare.js和jweixin-1.6.0.js,並且通過在隱藏的span標簽上定義自定義分享的內容,具體代碼如下:
1 <!DOCTYPE html> 2 <html xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>微信JS-SDK分享</title> 6 <script type="text/javascript" th:src="@{/js/jquery-1.8.3.min.js}" ></script> 7 <script type="text/javascript" th:src="@{/js/wxShare.js}"></script> 8 <script type="text/javascript" src="http://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script> 9 </head> 10 <body> 11 <span id="wx_share_span" style="display: none"></span> 12 <h1>SpringMVC + Thymeleaf Hello World example</h1> 13 <p th:text="${content}"></p> <!-- ${...}變量表達式 --> 14 <script type="text/javascript"> 15 $(document).ready(function(){ 16 $("#wx_share_span").data("shareTitle", "微信JS-SDK分享"); 17 $("#wx_share_span").data("shareDesc", "一個簡單的基於微信JS-SDK分享的demo"); 18 //$("#wx_share_span").data("shareLink", "/wxShare"); 19 $("#wx_share_span").data("shareImg", "http://www.zcg.com:8090/img/img.png"); 20 }); 21 </script> 22 </body> 23 </html>
6.測試
打開微信開發者工具,在地址欄輸入http://www.zcg.com:8090/weixin/wxShare,點擊分享,能夠出現以下界面,說明已經可以實現分享了!
gitee源碼地址:https://gitee.com/zcgxj/zxj-boot-wx-share.git