1. 程式人生 > >Java微信公眾平臺開發(十一)--微信JSSDK中Config配置

Java微信公眾平臺開發(十一)--微信JSSDK中Config配置

JSSDK曾經引爆前端以及後端的工程師,其魔性的力量毋庸置疑,在我們的技術眼裡它的實現原理和根本是不能夠被改變的,這篇文章就不對其js的實現做任何評價和解說了(因為我也不是很懂,哈哈),這裡要說的是它的config配置實現,參考文件:http://mp.weixin.qq.com/wiki/11/74ad127cc054f6b80759c40f77ec03db.html  !

微信JS-SDK是微信公眾平臺面向網頁開發者提供的基於微信內的網頁開發工具包,通過使用微信JS-SDK,網頁開發者可藉助微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信使用者提供更優質的網頁體驗;本篇將面向網頁開發者介紹微信JS-SDK如何使用及相關注意事項!JSSDK使用步驟:

  • 步驟一:在微信公眾平臺繫結安全域名

  • 步驟二:後端介面實現JS-SDK配置需要的引數

  • 步驟三:頁面實現JS-SDk中config的注入配置,並實現對成功和失敗的處理

(一)在微信公眾平臺繫結安全域名

先登入微信公眾平臺進入“公眾號設定”的“功能設定”裡填寫“JS介面安全域名”(如下圖),如果需要使用支付類介面,需要確保支付目錄在支付的安全域名下,否則將無法完成支付!(注:登入後可在“開發者中心”檢視對應的介面許可權),因為我用的是測試號,所以登入以後介面就如下圖:

(二)後端介面實現JS-SDK配置需要的引數 

1 wx.config({
2     debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
3     appId: '', // 必填,公眾號的唯一標識
4     timestamp: , // 必填,生成簽名的時間戳
5     nonceStr: '', // 必填,生成簽名的隨機串
6     signature: '',// 必填,簽名,見附錄1
7     jsApiList: [] // 必填,需要使用的JS介面列表
8 });

我們檢視js-sdk的配置文件和以上的程式碼可以發現config的配置需要4個必不可少的引數appId、timestamp、nonceStr、signature,這裡的signature就是我們生成的簽名!

生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號用於呼叫微信JS介面的臨時票據。正常情況下,jsapi_ticket的有效期為7200秒,通過access_token來獲取。由於獲取jsapi_ticket的api呼叫次數非常有限,頻繁重新整理jsapi_ticket會導致api呼叫受限,影響自身業務,開發者必須在自己的服務全域性快取jsapi_ticket ,所以這裡我們將jsapi_ticket的獲取放到定時任務中,因為它和token的生命週期是一致的,所以在這裡我們將他們放到一起。

①將原有的定時任務WeChatTask中獲取token的程式碼做如下修改:

 1 package com.gede.wechat.common;
 2 import java.text.SimpleDateFormat;
 3 import java.util.Date;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 
 7 import com.gede.web.util.GlobalConstants;
 8 import com.gede.wechat.util.HttpUtils;
 9 
10 import net.sf.json.JSONObject;
11 /**
12 * @author gede
13 * @version date:2019年5月26日 下午7:50:38
14 * @description :
15 */
16 public class WeChatTask {
17     /**
18      * @Description: 任務執行體
19      * @param @throws Exception
20      */
21     public void getToken_getTicket() throws Exception {
22          Map<String, String> params = new HashMap<String, String>();
23          //獲取token執行體
24          params.put("grant_type", "client_credential");
25          params.put("appid", GlobalConstants.getInterfaceUrl("appid"));
26          params.put("secret", GlobalConstants.getInterfaceUrl("AppSecret"));
27          String jstoken = HttpUtils.sendGet(
28                  GlobalConstants.getInterfaceUrl("tokenUrl"), params);
29      
30          String access_token = JSONObject.fromObject(jstoken).getString(
31                  "access_token"); // 獲取到token並賦值儲存
32          GlobalConstants.interfaceUrlProperties.put("access_token", access_token);
33    
34          //獲取jsticket的執行體
35          params.clear();
36          params.put("access_token", access_token);
37          params.put("type", "jsapi");
38          String jsticket = HttpUtils.sendGet(
39                  GlobalConstants.getInterfaceUrl("ticketUrl"), params);
40          String jsapi_ticket = JSONObject.fromObject(jsticket).getString(
41                  "ticket"); 
42          GlobalConstants.interfaceUrlProperties.put("jsapi_ticket", jsapi_ticket); // 獲取到js-SDK的ticket並賦值儲存
43           
44          System.out.println("jsapi_ticket================================================" + jsapi_ticket);
45          System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"token為=============================="+access_token);
46     }
47 }

然後我們根據【JS-SDK使用許可權簽名演算法】對引數進行簽名得到signature,這裡的url必須採用前端傳遞到後端,因為每次的url會有所變化,

②所以我們自定義一個許可權簽名演算法JSSDK_Config類,如下:

 1 package com.gede.wechat.common;
 2 
 3 import java.security.MessageDigest;
 4 import java.util.Formatter;
 5 import java.util.HashMap;
 6 import java.util.UUID;
 7 import com.gede.web.util.GlobalConstants;
 8 
 9 /**
10 * @author gede
11 * @version date:2019年5月30日 下午2:52:57
12 * @description :
13 */
14 public class JSSDK_Config {
15      
16     /**
17      * @Description: 前端jssdk頁面配置需要用到的配置引數
18      * @param @return hashmap {appid,timestamp,nonceStr,signature}
19      * @param @throws Exception   
20      * @author gede
21      */
22     public static HashMap<String, String> jsSDK_Sign(String url) throws Exception {
23         String nonce_str = create_nonce_str();
24         String timestamp=GlobalConstants.getInterfaceUrl("timestamp");
25         String jsapi_ticket=GlobalConstants.getInterfaceUrl("jsapi_ticket");
26         // 注意這裡引數名必須全部小寫,且必須有序
27         String  string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str
28                 + "&timestamp=" + timestamp  + "&url=" + url;
29         MessageDigest crypt = MessageDigest.getInstance("SHA-1");
30         crypt.reset();
31         crypt.update(string1.getBytes("UTF-8"));
32         String signature = byteToHex(crypt.digest());
33         HashMap<String, String> jssdk=new HashMap<String, String>();
34         jssdk.put("appId", GlobalConstants.getInterfaceUrl("appid"));
35         jssdk.put("timestamp", timestamp);
36         jssdk.put("nonceStr", nonce_str);
37         jssdk.put("signature", signature);
38         return jssdk;
39  
40     }
41      
42     private static String byteToHex(final byte[] hash) {
43         Formatter formatter = new Formatter();
44         for (byte b : hash) {
45             formatter.format("%02x", b);
46         }
47         String result = formatter.toString();
48         formatter.close();
49         return result;
50     }
51      
52     private static String create_nonce_str() {
53         return UUID.randomUUID().toString();
54     }
55  
56 }

③編寫使用JSSDK的controller類。新增JssdkController,程式碼如下:

 1 package com.gede.wechat.controller;
 2 
 3 import java.util.Map;
 4 import org.springframework.stereotype.Controller;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.RequestMethod;
 7 import org.springframework.web.bind.annotation.RequestParam;
 8 import org.springframework.web.bind.annotation.ResponseBody;
 9 
10 
11 /**
12 * @author gede
13 * @version date:2019年5月30日 下午3:03:31
14 * @description :
15 */
16 @Controller
17 @RequestMapping("/jssdk")
18 public class JssdkController {
19     /**
20      * @Description: 前端獲取微信JSSDK的配置引數
21      * @param @param response
22      * @param @param request
23      * @param @param url
24      * @param @throws Exception
25      */
26     @RequestMapping(value="config",method=RequestMethod.POST)
27     @ResponseBody
28     public Message JSSDK_config(
29             @RequestParam(value = "url", required = true) String url) {
30         try {
31             System.out.println(url);
32             Map<String, String> configMap = JSSDK_Config.jsSDK_Sign(url);
33             return Message.success(configMap);
34         } catch (Exception e) {
35             System.out.println("error happened!!!");
36             return Message.error();
37         }
38  
39     }
40 }

到這裡我們後端對jssdk的簽名引數的封裝就基本完成了,其中用到了我們自己寫的Message類,程式碼如下:

  1 package com.gede;
  2 
  3 import com.gede.Code;
  4 
  5 /**
  6 * @author gede
  7 * @version date:2019年5月30日 下午3:09:35
  8 * @description :用於訊息回覆
  9 */
 10 public class Message {
 11     private int code;
 12     private String msg;
 13     private Object data;
 14     public Message() {
 15         
 16     }
 17     
 18     public int getCode() {
 19         return code;
 20     }
 21 
 22     public void setCode(int code) {
 23         this.code = code;
 24     }
 25 
 26     public String getMsg() {
 27         return msg;
 28     }
 29 
 30     public void setMsg(String msg) {
 31         this.msg = msg;
 32     }
 33 
 34     public Object getData() {
 35         return data;
 36     }
 37 
 38     public void setData(Object data) {
 39         this.data = data;
 40     }
 41     
 42     public Message(int code,String msg) {
 43         this.code=code;
 44         this.msg=msg;
 45     }
 46 
 47     public Message(int code,String msg,Object data) {
 48         this.code=code;
 49         this.msg=msg;
 50         this.data=data;
 51     }
 52     /**
 53      * 返回成功訊息
 54      * @param content 內容
 55      * @return 成功訊息
 56      */
 57     public static Message success(String content, Object data) {
 58         return new Message(Code.SUCCESS, content, data);
 59     }
 60     /**
 61      * 返回成功訊息
 62      * @param content 內容
 63      * @return 成功訊息
 64      */
 65     public static Message success(String content) {
 66         return new Message(Code.SUCCESS, content);
 67     }
 68     /**
 69      * 返回成功訊息
 70      * @param content 內容
 71      * @return 成功訊息
 72      */
 73     public static Message success(Object data) {
 74         System.out.println(Code.SUCCESS);
 75         return new Message(Code.SUCCESS, "操作成功",data);
 76     }
 77     /**
 78      * 返回成功訊息
 79      * @param content 內容
 80      * @return 成功訊息
 81      */
 82     public static Message success() {
 83         return new Message(Code.SUCCESS, "操作成功");
 84     }
 85     /**
 86      * 返回失敗訊息
 87      * @param content 內容
 88      * @return 成功訊息
 89      */
 90     public static Message error(int code,String content, Object data) {
 91         return new Message(code, content, data);
 92     }
 93     /**
 94      * 返回失敗訊息
 95      * @param content 內容
 96      * @return 成功訊息
 97      */
 98     public static Message error(String content, Object data) {
 99         return new Message(Code.FAIL, content, data);
100     }
101     
102     /**
103      * 返回失敗訊息
104      * @param content 內容
105      * @return 成功訊息
106      */
107     public static Message error(String content) {
108         return new Message(Code.FAIL, content);
109     }
110     /**
111      * 返回失敗訊息
112      * @param content 內容
113      * @return 成功訊息
114      */
115     public static Message error() {
116         return new Message(Code.FAIL, "操作失敗");
117     }
118 
119 }

code類程式碼為:

 1 package com.gede;
 2 /**
 3 * @author gede
 4 * @version date:2019年5月30日 下午3:10:34
 5 * @description :狀態碼
 6 */
 7 public class Code {
 8     public static final int SUCCESS = 200; //成功
 9     public static final int PARAMATER = 400; //引數錯誤
10     public static final int FAIL =500; //系統異常
11 }

到這裡我們就開始寫前端介面,來響應我們的方法。

(三)頁面實現JS-SDk中config的注入配置,並實現對成功和失敗的處理

這裡在web目錄下新建jssdkconfig.jsp,在jsp頁面用ajax方式獲取並進行配置,並開啟debug模式,開啟之後就可以看到配置是否成功的提示,簡單程式碼如下:

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <!DOCTYPE html >
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 7 <meta name="viewport" content="width=device-width" />
 8 <title>JSSDk配置</title>
 9 <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
10 <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
11 <script type="text/javascript">
12     function jssdk() {
13         $.ajax({
14             url : "http://zqfbk.iok.la/wechat/wechatconfig/jssdk",
15             type : 'post',
16             dataType : 'json',
17             contentType : "http://zqfbk.iok.la/mychat/jssdk/config",
18             data : {
19                 'url' : location.href.split('#')[0]
20             },
21             success : function(data) {
22                 wx.config({
23                     debug : true,
24                     appId : data.data.appId,
25                     timestamp : data.data.timestamp,
26                     nonceStr : data.data.nonceStr,
27                     signature : data.data.signature,
28                     jsApiList : [ 'checkJsApi', 'onMenuShareTimeline',
29                             'onMenuShareAppMessage', 'onMenuShareQQ',
30                             'onMenuShareWeibo', 'hideMenuItems',
31                             'showMenuItems', 'hideAllNonBaseMenuItem',
32                             'showAllNonBaseMenuItem', 'translateVoice',
33                             'startRecord', 'stopRecord', 'onRecordEnd',
34                             'playVoice', 'pauseVoice', 'stopVoice',
35                             'uploadVoice', 'downloadVoice', 'chooseImage',
36                             'previewImage', 'uploadImage', 'downloadImage',
37                             'getNetworkType', 'openLocation', 'getLocation',
38                             'hideOptionMenu', 'showOptionMenu', 'closeWindow',
39                             'scanQRCode', 'chooseWXPay',
40                             'openProductSpecificView', 'addCard', 'chooseCard',
41                             'openCard' ]
42                 });
43             }
44         });
45     }
46  
47     function isWeiXin5() {
48         var ua = window.navigator.userAgent.toLowerCase();
49         var reg = /MicroMessenger\/[5-9]/i;
50         return reg.test(ua);
51     }
52  
53     window.onload = function() {
54         //     if (isWeiXin5() == false) {
55         //           alert("您的微信版本低於5.0,無法使用微信支付功能,請先升級!");
56         //         }
57         jssdk();
58     };
59 </script>
60 </head>
61 <body>
62     <h1>nihao</h1>
63 </body>
64 </html>

 (四)pc端進行測試

我的瀏覽器是火狐developer版的,其他的也都差不多,開啟瀏覽器按F12,找到一個叫網路的視窗,也有的瀏覽器叫network像我的就是network。

①執行專案後,開啟瀏覽器輸入訪問地址http://zqfbk.iok.la/mychat/;點選Jssdk這裡需要設定一下超連結,因為懶得從檢視控制器返回了,超連結程式碼:

 

 <h1>Welcome to Mychat</h1>
    <a href="<c:url value="/userinfo" />">UserInfo</a>
    <a href="<c:url value="/jssdkconfig.jsp" />">Jssdk</a>

 

  

②在我麼點選Jssdk的時候,先按f12 開啟network檢視視窗。,然後再點選,效果圖如下:

③如果你看到你的狀態碼中沒有404,那你多半成功了,我們找對對應的檔名為config的那一行點選一下,進行檢視,此時後臺也會做出成功提示,上圖:

如果提示是這樣,那麼標識我們的配置是成功的,那麼到這裡微信jssdk的配置就基本完成了。

&n