第一次用到JS-SDK,前前后后还是踩了不少坑(包括微信API文档的坑),总结下这段搞配置的艰辛历程,提升自己的同时,希望能帮到有需要的朋友。不足之处各路大神望提出。
- 首先还是得看回官方文档API,要是网上随便搜现成的还是不建议,用了也不知道其所以然,到下次有什么问题或者需求变更之后让你抓狂不止,所以还是乖乖看文档吧。企业微信JS-SDK链接
- 最重要的第一步,企业微信的管理后台- - ->应用与小程序- - ->网页授权及JS-SDK- - ->设置可信域名。这里最好还是用备案过的域名,我也尝试过内网穿透生成的临时域名,因为当时服务器购买和域名备案赶不及,期间操作起来比较麻烦,这里就长篇大论了,建议还是用正式的域名吧。
注意这里在企业微信后台的的可信域的配置是需要放微信提供的一个文件在自己的服务器端的,如何验证放得对不对,只要用浏览器访问去验证即可,能访问到这个文件的话说明放得正确。我是直接认在docker容器的根目录下。 - 大致上刷一下,大概的配置思路是这样的:
access_token - - - > jsapi_ticket - - - > signature
package com.mint.springboot.controller;
import com.mint.springboot.component.WXConnection;
import com.mint.springboot.vo.ConfigDataVo;
import com.mint.springboot.vo.UserIdVo;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Date;
@Controller
@RequestMapping("/")
public class WXConfigController {
@Autowired
private WXConnection wxConnection;
@ResponseBody
@GetMapping("/getAutograph")
public ConfigDataVo getAutograph(String postUrl){
ConfigDataVo configDataVo = new ConfigDataVo();
//appId是固定值(虽然微信官方提倡用前端传参的方式后端来动态获取,不过写死也不影响)
String appId = "XXXXXXXXXXXXX";
try {
//第一步:获取得到token
//corpid和corpsecret在企业微信管理后台直接查看赋值即可
String tokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=XXXXXXXXXX&corpsecret=XXXXXXXXXXXXXX";
String key = "access_token";
String access_token = wxConnection.sendGetRequest(tokenUrl,key);
//第二步:获取企业的jsapi_ticket
String ticketUrl = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token="+access_token+"&type=agent_config";
String jsapi_ticket = wxConnection.sendGetRequest(ticketUrl,"ticket");
//第三步:生成签名
String nonceStr = RandomStringUtils.randomAlphanumeric(10);//生成随机字符串
String timestamp = String.valueOf((new Date().getTime())/1000);//生成时间戳
String url = "XXX.html";//微信可以访问到的前端html文件的路径地址
String signature = "jsapi_ticket="+jsapi_ticket+"&noncestr="+nonceStr+"×tamp="+timestamp+"&url="+url;
configDataVo.setAccess_token(access_token);
configDataVo.setNonceStr(nonceStr);
configDataVo.setTimestamp(timestamp);
configDataVo.setSignature(signature);
configDataVo.setAppId(appId);
} catch (IOException e) {
e.printStackTrace();
}
return configDataVo;
}
}
复制粘贴的小伙伴报红不要急,给你们要的Vo类和wxConnection类:
package com.mint.springboot.vo;
/**
* 获取前端配置需要的数据
* */
public class ConfigDataVo {
//随机字符串
private String nonceStr;
//时间戳
private String timestamp;
//签名
private String signature;
//appId
private String appId;
//access_token(用于获取当前用户ID)
private String access_token;
public ConfigDataVo() {
}
public ConfigDataVo(String nonceStr, String timestamp, String signature, String appId, String access_token) {
this.nonceStr = nonceStr;
this.timestamp = timestamp;
this.signature = signature;
this.appId = appId;
this.access_token = access_token;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
@Override
public String toString() {
return "ConfigDataVo{" +
"nonceStr='" + nonceStr + '\'' +
", timestamp='" + timestamp + '\'' +
", signature='" + signature + '\'' +
", appId='" + appId + '\'' +
", access_token='" + access_token + '\'' +
'}';
}
}
package com.mint.springboot.component;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class WXConnection {
public static String sendGetRequest(String url,String key) throws IOException {
String encoding = "UTF-8";
String result = "";
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Content-type", "application/json");
CloseableHttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.OK.value()) {
result = EntityUtils.toString(response.getEntity(), encoding);
JSONObject jsonObject = JSONObject.parseObject(result);
return jsonObject.getString(key);
} else {
System.out.println("请求失败");
}
response.close();
return null;
}
}
- OK,现在后台搭建基本已经搭起来了,那么就用前端写个ajax请求去检验,记得检验的时候不要用谷歌或者火狐等浏览器,直接用微信提供的(微信开发者工具- - - >公众号网页)去测试,因为用普通的浏览器你真的测试不出你的配置的准确性。
//获取企业微信JS-SDK配置信息
$(function(){
getData();//执行函数
});
//前端发起ajax请求加载配置需要的数据
function getData() {
$.ajax({
type: "Get",
url: "XXXXXXXXXXX/getAutograph",
dataType: "json",
success: function (data) {
window.timestamp = data.timestamp;
window.nonceStr = data.nonceStr;
window.signature = data.signature;
window.appId = data.appId;
window.access_token = data.access_token;
},
error: function () {
}
});
}
//微信配置
setTimeout(function () {
wx.config({
beta: true,
debug: true,
appId: window.appId,
timestamp:window.timestamp,
nonceStr: window.nonceStr,
signature: CryptoJS.SHA1(window.signature).toString(CryptoJS.enc.Hex),
jsApiList: ['getLocation']
});
wx.ready(function(){
wx.checkJsApi({
jsApiList: ['getLocation'],
success: function (res) {
}
});
<!--获取地理位置接口-->
wx.getLocation({
type: 'gcj02',//不要用默认的wgs84
success: function (res) {
window.latitude = res.latitude;
window.longitude = res.longitude;
}
});
});
wx.error(function(res){
});
}, 1000);
这里的JS代码注意了,这里我在前端项目导入了第三方的sha1.js,微信官方要求signature值是要进行sha1加密的,这也是我遇到的一个比较大的坑之一,微信官方只说要进行sha1加密但是sha1怎么实现并没有给出,后台对sha1的加密实现百度一搜一堆。好了,有多一个思路,微信这边给出一个检验工具,也就说你最终得到的signature的值和这个检验工具得到的值相等的时候,证明你用对了sha1的实现。检测工具链接
刚好在百度sha1在线加密解密的网站上有说明:
来得也是时候,所以在网上找了个Crypto-JS的第三方js文件。把加密的工作放在前端实现了。
- 所有工作准备完毕,用微信开发中工具服务前端html文件
如果显示"config:ok",说明配置成功,反之有地方配置项还是有问题。
好了,总结下几个必要容易引起配置错误的地方: - 首先可信域名是先要配置好的,这一步没配置好后面都进行不下去;
- 获取token,ticket的步骤不不难,最终前面老是失败的原因大多都是因为传入的url错误。
- 前端访问后台的时候,很多时候会报跨域。这个贴上一个解决的类。
package com.mint.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L);
}
}
大致上就这些了吧,OK!
学无止境,不断进步!