SpringBoot JS-SDK自定義微信分享的實現(xiàn)
前言
在介紹使用微信自定義分享前,我們來先了解一下什么是自定義分享?
訪問自定義微信外鏈地址頁面,點擊紅色框位置進行分享給朋友或者朋友圈,具體操作如下圖所示:
分享后圖文消息如下圖所示:
我們要做的就是自定義下圖所示中紅框中的信息。
閑話少說,接下來就正式開始自定義分享實戰(zhàn)環(huán)節(jié)!
自定義分享實戰(zhàn)
第一步需要先申請接口測試號并進行JS接口安全域名設(shè)置
訪問如下鏈接進行接口測試號申請。點擊訪問 選擇接口測試號申請,如下圖所示:
或者直接訪問 :申請測試賬號頁面 如下圖所示:
點擊登錄進行掃碼登錄,如下圖所示:
登錄后如下圖所示:
windows系統(tǒng)在 hosts 文件中配置回環(huán)地址的域名
第二步是下載微信web開發(fā)者工具,可以在PC 進行測試。
點擊訪問下載頁面 如下圖所示:
傻瓜式一步一步安裝即可。
第三步 看微信操作教程并完成代碼實現(xiàn)
點擊訪問微信JS-SDK說明文檔 如下圖所示:
JSSDK使用步驟
步驟一:綁定域名(上面已經(jīng)操作了)
步驟二:引入JS文件(下面實戰(zhàn)代碼中會介紹到如何使用)
步驟三:通過config接口注入權(quán)限驗證配置(下面實戰(zhàn)代碼中會介紹到如何使用)
步驟四:通過ready接口處理成功驗證(這里就不詳細介紹了具體內(nèi)容請參看微信文檔查看)
步驟五:通過error接口處理失敗驗證(這里就不詳細介紹了具體內(nèi)容請參看微信文檔查看)
上面步驟步驟三中的 signature是一個重要的參數(shù),生成它需要獲取 jsapi_ticket,而生成 jsapi_ticket 需要通過 access_token
。
獲取signature流程如下:
- 獲取 access_token 然后根據(jù) access_token 獲取 jsapi_ticket 。
- 排序 noncestr(隨機字符串), 有效的jsapi_ticket, timestamp(時間戳),url(當前網(wǎng)頁的URL,不包含#及其后面部分)4個參數(shù)拼接例如:noncestr=XX&jsapi_ticket=XX&jtimestamp=XX&jurl=XX
- 然后通過sha1加密拼接的4個參數(shù)獲取到signature
可能你對操作流程還是看不懂,沒有關(guān)系可以直接參考代碼實現(xiàn),接下來就是代碼實現(xiàn):
初始化微信JSSDK配置信息 Controller 內(nèi)容如下:
@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(當前網(wǎng)頁的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(當前網(wǎng)頁的URL,不包含#及其后面部分)并通過sha1進行加密。
/** * 構(gòu)建分享鏈接的簽名。 * @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微信配置參數(shù)獲取簽名。 * * @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(); } /** * 將字節(jié)數(shù)組轉(zhuǎn)換為十六進制字符串 * * @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; } /** * 將字節(jié)轉(zhuǎn)換為十六進制字符串 * * @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; }
基礎(chǔ)工具方法如下:
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() { // 用戶確認分享后執(zhí)行的回調(diào)函數(shù) //alert("分享成功"); }, cancel : function() { // 用戶取消分享后執(zhí)行的回調(diào)函數(shù) //alert("分享取消"); } }); //wx.hideOptionMenu();/***隱藏分享菜單****/ wx.onMenuShareAppMessage({ title: shareTitle, // 分享標題 desc: shareDesc, // 分享描述 link: shareLink, // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應(yīng)的公眾號JS安全域名一致 imgUrl: shareImg, // 分享圖標 success: function () { // 用戶確認分享后執(zhí)行的回調(diào)函數(shù) }, cancel: function () { // 用戶取消分享后執(zhí)行的回調(diào)函數(shù) } }); wx.onMenuShareQQ({ title: shareTitle, // 分享標題 desc: shareDesc, // 分享描述 link: shareLink, // 分享鏈接 imgUrl: shareImg, // 分享圖標 success: function () { // 用戶確認分享后執(zhí)行的回調(diào)函數(shù) }, cancel: function () { // 用戶取消分享后執(zhí)行的回調(diào)函數(shù) } }); wx.onMenuShareWeibo({ title: shareTitle, // 分享標題 desc: shareDesc, // 分享描述 link: shareLink, // 分享鏈接 imgUrl: shareImg, // 分享圖標 success: function () { // 用戶確認分享后執(zhí)行的回調(diào)函數(shù) }, cancel: function () { // 用戶取消分享后執(zhí)行的回調(diào)函數(shù) } }); wx.onMenuShareQZone({ title: shareTitle, // 分享標題 desc: shareDesc, // 分享描述 link: shareLink, // 分享鏈接 imgUrl: shareImg, // 分享圖標 success: function () { // 用戶確認分享后執(zhí)行的回調(diào)函數(shù) }, cancel: function () { // 用戶取消分享后執(zhí)行的回調(diào)函數(shù) } }); }); });
分享頁面該頁面需要引入wxShare.js和jweixin-1.2.0.js,并且通過在隱藏的span標簽上定義自定義分享的內(nèi)容,具體代碼如下:
<!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 的測試結(jié)果如下:
引入 wxShare.js 的測試結(jié)果如下:
一般情況下我們通過接口測試號配置成測試環(huán)境域名,上述測試通過后就可以在正式服務(wù)號上配置JS接口安全域名,順便在把我們項目配置的 appid 換成服務(wù)號的 appid 即可。具體操作如下:
小結(jié)
微信自定義分享具體操作步驟如下:
- 定義獲取JS-SDK配置信息接口
- 定義頁面初始化調(diào)用JS-SDK配置信息接口 js 代碼和定義分享接口js代碼
- 分享頁面引入 jweixin-1.2.0.js和 調(diào)用JS-SDK配置信息的js文件
三步中最為總要的就是第一步:定義獲取JS-SDK配置信息接口,這個接口需要獲取jsapi_ticket 并通過和配置信息參數(shù)一起生成簽名 signature。
在這里再三強調(diào)一下,微信提供操作文檔一定要多看幾篇,因為很多細節(jié)都在文檔中進行了說明。當你把微信提供操作文檔看透,你就會覺得其實就是個API 調(diào)用而已。
代碼示例
具體代碼示例請查看我的GitHub 倉庫 springbootexamples 中的 spring-boot-2.x-weixin 查看。
GitHub:https://github.com/zhuoqianmingyue/springbootexamples
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java使用Collections工具類對List集合進行排序
這篇文章主要介紹了Java使用Collections工具類對List集合進行排序,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-10-10SpringBoot升級3.2報錯Invalid value type for
這篇文章給大家介紹了SpringBoot升級3.2報錯Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String的解決方案,文中有詳細的原因分析,需要的朋友可以參考下2023-12-12Spring學習之開發(fā)環(huán)境搭建的詳細步驟
本篇文章主要介紹了Spring學習之開發(fā)環(huán)境搭建的詳細步驟,具有一定的參考價值,有興趣的可以了解一下2017-07-07SpringCloud之熔斷監(jiān)控Hystrix Dashboard的實現(xiàn)
這篇文章主要介紹了SpringCloud之熔斷監(jiān)控Hystrix Dashboard的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09