springboot 基於JS-SDK實現微信分享(一)


本文主要介紹了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_tickettimestamp(時間戳)、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("&timestamp=").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.jsjweixin-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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM