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

 

posted @ 2020-07-20 01:37  IT民工郑小江  阅读(1276)  评论(0编辑  收藏  举报