JSSDK曾經引爆前端以及後端的工程師,其魔性的力量毋庸置疑,在咱們的技術眼裏它的實現原理和根本是不可以被改變的,這篇文章就不對其js的實現作任何評價和解說了(由於我也不是很懂,哈哈),這裏要說的是它的config配置實現,參考文檔:http://mp.weixin.qq.com/wiki/11/74ad127cc054f6b80759c40f77ec03db.html !javascript
微信JS-SDK是微信公衆平臺面向網頁開發者提供的基於微信內的網頁開發工具包,經過使用微信JS-SDK,網頁開發者可藉助微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時能夠直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,爲微信用戶提供更優質的網頁體驗;本篇將面向網頁開發者介紹微信JS-SDK如何使用及相關注意事項!JSSDK使用步驟:html
步驟一:在微信公衆平臺綁定安全域名前端
步驟二:後端接口實現JS-SDK配置須要的參數java
步驟三:頁面實現JS-SDk中config的注入配置,並實現對成功和失敗的處理jquery
先登陸微信公衆平臺進入「公衆號設置」的「功能設置」裏填寫「JS接口安全域名」(以下圖),若是須要使用支付類接口,須要確保支付目錄在支付的安全域名下,不然將沒法完成支付!(注:登陸後可在「開發者中心」查看對應的接口權限),由於我用的是測試號,因此登陸之後界面就以下圖:web
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就是咱們生成的簽名!ajax
生成簽名以前必須先了解一下jsapi_ticket,jsapi_ticket是公衆號用於調用微信JS接口的臨時票據。正常狀況下,jsapi_ticket的有效期爲7200秒,經過access_token來獲取。因爲獲取jsapi_ticket的api調用次數很是有限,頻繁刷新jsapi_ticket會致使api調用受限,影響自身業務,開發者必須在本身的服務全局緩存jsapi_ticket ,因此這裏咱們將jsapi_ticket的獲取放到定時任務中,由於它和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會有所變化,spring
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 + "×tamp=" + 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 }
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類,代碼以下:json
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 }
到這裏咱們就開始寫前端界面,來響應咱們的方法。
這裏在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>
個人瀏覽器是火狐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的配置就基本完成了。