首先申请一个测试号,然后进行配置。
话不多说,直接上图:
其中这里的url和token是需要自己定义的,url要确保能跟外网能访问,是一个地址,微信后台能进行访问和验证,确保能跟外网联通。其实就是一个你自己后台写的接口,不过这个接口参数要根据微信定义。
我的url是:http://xxx.xxx/sanbox
RequestParam结构如下:
@Data
public class RequestParam {
private String signature;
private String timestamp;
private String nonce;
private String echostr;
}
wechatService.checkSourceIsFromWiki()的逻辑如下:
@Override
public boolean checkSourceIsFromWiki(RequestParam requestParam) {
/*
* 1)将token、timestamp、nonce三个参数进行字典序排序
* 2)将三个参数字符串拼接成一个字符串进行sha1加密
* 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
*/
// 这里的token需要跟上面填写的token必须一样
String[] strs= new String[] {TOKEN,requestParam.getTimestamp(),requestParam.getNonce()};
Arrays.sort(strs);
String str = strs[0]+strs[1]+strs[2];
String sig = SecureUtil.sha1(str);
System.out.println(requestParam.getSignature());
System.out.println(sig);
return requestParam.getSignature().equals(sig);
}
上面的代码可以直接拷贝,只需要修改token。
填写的URL:必须是能通过外网访问的!!
可以使用内网穿透服务,当然不怕麻烦的话可以直接放到服务器进行调试。
推荐使用natapp,官网地址:https://natapp.cn/
具体细节下载配置官网上有,如果是前后端分离的项目需要弄两个隧道(可以一个收费一个免费,收费的给后台用,免费的给前端用)
内网穿透配置好了之后可以通过,上面的地址进行访问测试。
测试没问题之后保存上面的URL和TOKEN就可以通过了,如果不是可以尝试多几次(确定能通过外网地址访问到本地服务情况下)。
配置好上面的部分之后配置js接口安全域名
这部分同样不能出错,如果这部分没配置好,获取签名的时候前端会给你报签名错误,不能通过验证。
其实这里的意思通俗讲就是:只允许在这个域名下的网页或网站验证js-sdk配置信息,否则一律不通过验证。
如果你web和后台是在同一个端口服务的话直接使用上面代理的域名,如果是前后端分离的项目,比如vue,需要额外配置一个服务地址给前端运行,这个运行的端口也是需要进行 外网映射 的。
上面也配置好了之后,可以写获取签名的代码了:
@Override
public JsSDKConfig getJsSDKConfig(String url) {
String ticket = this.jsapiTicket.getTicket();
String noncestr = UUID.randomUUID().toString().replace("-","");
Long timestamp = System.currentTimeMillis() / 1000;
if (!(ticket != null && this.jsapiTicket.getExpires_time() > System.currentTimeMillis() / 1000)){
// 获取access_token
String accToken = getAccToken();
// 根据access_token获取jsapi_ticket
ticket = getTicket(accToken);
// 生成noncestr
this.jsapiTicket.setExpires_time(System.currentTimeMillis()/1000 + 7200);
this.jsapiTicket.setTicket(ticket);
}
StringBuffer strb = new StringBuffer();
strb.append("jsapi_ticket=").append(ticket).append("&")
.append("noncestr=").append(noncestr).append("&")
.append("timestamp=").append(timestamp).append("&")
.append("url=").append(url);
String signature = SecureUtil.sha1(strb.toString());
JsSDKConfig config = new JsSDKConfig();
config.setAppId(appId);
config.setNonceStr(noncestr);
config.setTimestamp(timestamp);
config.setSignature(signature);
System.out.println(signature);
return config;
}
public String getAccToken(){
Map ac_token_params = new HashMap<>();
ac_token_params.put("grant_type","client_credential");
ac_token_params.put("appid",appId);
ac_token_params.put("secret",appSecret);
String acc_token_res = HttpUtil.get(getAccessTokenUrl, ac_token_params);
Map map = GsonUtil.formJson(acc_token_res, Map.class);
String access_token = (String)map.get("access_token");
return access_token;
}
public String getTicket(String accToken){
Map tick_params = new HashMap();
tick_params.put("access_token",accToken);
tick_params.put("type","jsapi");
String ticket_res = HttpUtil.get(getTicketUrl, tick_params);
String ticket = (String)GsonUtil.formJson(ticket_res, Map.class).get("ticket");
return ticket;
}
有几个点需要注意一下
1、access_token和jsapi_ticket是不能每次请求都获取,需要保存jsapi_ticket,我将这些信息和过期时间封装成一个对象,在Springboot启动的时候注入IOC每次请求调用,为空的时候或者过期再进行请求获取新的jsapi_ticket
2、参数的url是网页的url可以使用location.href.split(’#’)[0]
3、签名前的字符串拼接是有顺序的,而且timestamp是秒级别而不是毫秒级别(java默认毫秒级别)
这些准备工作都做好了之后就可以测试了,js代码如下:
httpGet('getConfig', {url: location.href.split('#')[0]}).then(res => {
let config = res.data.data
config.debug = true
config.jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData', 'chooseImage', 'onMenuShareAppMessage']
Vue.wechat.config(config)
})
上面代码是我用vue 和 axios经过封装的,如果是不使用vue的朋友可以直接拷贝官网的。
运行程序你会看到输出台打印这些字段就代表成功了!!!
美滋滋,话说微信开发真的很坑,特别是官网的文档。。。