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: '',// 必填,签名,见附录17 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 packagecom.gede.wechat.common;2 importjava.text.SimpleDateFormat;3 importjava.util.Date;4 importjava.util.HashMap;5 importjava.util.Map;6
7 importcom.gede.web.util.GlobalConstants;8 importcom.gede.wechat.util.HttpUtils;9
10 importnet.sf.json.JSONObject;11 /**
12 *@authorgede13 *@versiondate:2019年5月26日 下午7:50:3814 * @description :15 */
16 public classWeChatTask {17 /**
18 * @Description: 任务执行体19 *@param @throwsException20 */
21 public void getToken_getTicket() throwsException {22 Map params = new HashMap();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 packagecom.gede.wechat.common;2
3 importjava.security.MessageDigest;4 importjava.util.Formatter;5 importjava.util.HashMap;6 importjava.util.UUID;7 importcom.gede.web.util.GlobalConstants;8
9 /**
10 *@authorgede11 *@versiondate:2019年5月30日 下午2:52:5712 * @description :13 */
14 public classJSSDK_Config {15
16 /**
17 * @Description: 前端jssdk页面配置需要用到的配置参数18 *@param @returnhashmap {appid,timestamp,nonceStr,signature}19 *@param @throwsException20 *@authorgede21 */
22 public static HashMap jsSDK_Sign(String url) throwsException {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_str28 + "×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 jssdk=new HashMap();34 jssdk.put("appId", GlobalConstants.getInterfaceUrl("appid"));35 jssdk.put("timestamp", timestamp);36 jssdk.put("nonceStr", nonce_str);37 jssdk.put("signature", signature);38 returnjssdk;39
40 }41
42 private static String byteToHex(final byte[] hash) {43 Formatter formatter = newFormatter();44 for (byteb : hash) {45 formatter.format("%02x", b);46 }47 String result =formatter.toString();48 formatter.close();49 returnresult;50 }51
52 private staticString create_nonce_str() {53 returnUUID.randomUUID().toString();54 }55
56 }
③编写使用JSSDK的controller类。新增JssdkController,代码如下:
1 packagecom.gede.wechat.controller;2
3 importjava.util.Map;4 importorg.springframework.stereotype.Controller;5 importorg.springframework.web.bind.annotation.RequestMapping;6 importorg.springframework.web.bind.annotation.RequestMethod;7 importorg.springframework.web.bind.annotation.RequestParam;8 importorg.springframework.web.bind.annotation.ResponseBody;9
10
11 /**
12 *@authorgede13 *@versiondate:2019年5月30日 下午3:03:3114 * @description :15 */
16 @Controller17 @RequestMapping("/jssdk")18 public classJssdkController {19 /**
20 * @Description: 前端获取微信JSSDK的配置参数21 *@param @paramresponse22 *@param @paramrequest23 *@param @paramurl24 *@param @throwsException25 */
26 @RequestMapping(value="config",method=RequestMethod.POST)27 @ResponseBody28 publicMessage JSSDK_config(29 @RequestParam(value = "url", required = true) String url) {30 try{31 System.out.println(url);32 Map configMap =JSSDK_Config.jsSDK_Sign(url);33 returnMessage.success(configMap);34 } catch(Exception e) {35 System.out.println("error happened!!!");36 returnMessage.error();37 }38
39 }40 }
到这里我们后端对jssdk的签名参数的封装就基本完成了,其中用到了我们自己写的Message类,代码如下:
1 packagecom.gede;2
3 importcom.gede.Code;4
5 /**
6 *@authorgede7 *@versiondate:2019年5月30日 下午3:09:358 * @description :用于消息回复9 */
10 public classMessage {11 private intcode;12 privateString msg;13 privateObject data;14 publicMessage() {15
16 }17
18 public intgetCode() {19 returncode;20 }21
22 public void setCode(intcode) {23 this.code =code;24 }25
26 publicString getMsg() {27 returnmsg;28 }29
30 public voidsetMsg(String msg) {31 this.msg =msg;32 }33
34 publicObject getData() {35 returndata;36 }37
38 public voidsetData(Object data) {39 this.data =data;40 }41
42 public Message(intcode,String msg) {43 this.code=code;44 this.msg=msg;45 }46
47 public Message(intcode,String msg,Object data) {48 this.code=code;49 this.msg=msg;50 this.data=data;51 }52 /**
53 * 返回成功消息54 *@paramcontent 内容55 *@return成功消息56 */
57 public staticMessage success(String content, Object data) {58 return newMessage(Code.SUCCESS, content, data);59 }60 /**
61 * 返回成功消息62 *@paramcontent 内容63 *@return成功消息64 */
65 public staticMessage success(String content) {66 return newMessage(Code.SUCCESS, content);67 }68 /**
69 * 返回成功消息70 *@paramcontent 内容71 *@return成功消息72 */
73 public staticMessage success(Object data) {74 System.out.println(Code.SUCCESS);75 return new Message(Code.SUCCESS, "操作成功",data);76 }77 /**
78 * 返回成功消息79 *@paramcontent 内容80 *@return成功消息81 */
82 public staticMessage success() {83 return new Message(Code.SUCCESS, "操作成功");84 }85 /**
86 * 返回失败消息87 *@paramcontent 内容88 *@return成功消息89 */
90 public static Message error(intcode,String content, Object data) {91 return newMessage(code, content, data);92 }93 /**
94 * 返回失败消息95 *@paramcontent 内容96 *@return成功消息97 */
98 public staticMessage error(String content, Object data) {99 return newMessage(Code.FAIL, content, data);100 }101
102 /**
103 * 返回失败消息104 *@paramcontent 内容105 *@return成功消息106 */
107 public staticMessage error(String content) {108 return newMessage(Code.FAIL, content);109 }110 /**
111 * 返回失败消息112 *@paramcontent 内容113 *@return成功消息114 */
115 public staticMessage error() {116 return new Message(Code.FAIL, "操作失败");117 }118
119 }
code类代码为:
1 packagecom.gede;2 /**
3 *@authorgede4 *@versiondate:2019年5月30日 下午3:10:345 * @description :状态码6 */
7 public classCode {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
2 pageEncoding="UTF-8"%>
3
4
5
6
7
8
JSSDk配置9
10
11
12 functionjssdk() {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 functionisWeiXin5() {48 varua=window.navigator.userAgent.toLowerCase();49 varreg= /MicroMessenger\/[5-9]/i;50 returnreg.test(ua);51 }52
53 window.οnlοad= function() {54 //if (isWeiXin5() == false) {
55 //alert("您的微信版本低于5.0,无法使用微信支付功能,请先升级!");
56 //}
57 jssdk();58 };59
60
61
62
nihao
63
64
(四)pc端进行测试
我的浏览器是火狐developer版的,其他的也都差不多,打开浏览器按F12,找到一个叫网络的窗口,也有的浏览器叫network像我的就是network。
①运行项目后,打开浏览器输入访问地址http://zqfbk.iok.la/mychat/;点击Jssdk这里需要设置一下超链接,因为懒得从视图控制器返回了,超链接代码:
Welcome to Mychat
②在我么点击Jssdk的时候,先按f12 打开network视图窗口。,然后再点击,效果图如下:
③如果你看到你的状态码中没有404,那你多半成功了,我们找对对应的文件名为config的那一行点击一下,进行查看,此时后台也会做出成功提示,上图:
如果提示是这样,那么标识我们的配置是成功的,那么到这里微信jssdk的配置就基本完成了。