企业微信的网址:https://work.weixin.qq.com
我们开发的程序在这里,企业微信里自建一个应用,相当于在微信里新建一个微信公众号
应用相关的信息在这里,后台需要配置 网页授权及JS-SDK、接收消息
网页授权及JS-SDK的URL是后台的回调地址,具体怎么实现后面讲
接收消息里面设置 Token和 EncodingAESKey ,这2参数需要在URL中用到
首先看一遍官方文档,然后操作。
配置回调服务,需要有三个配置项,分别是:URL, Token, EncodingAESKey 就是上面配置的
这三个应用的具体介绍见文档 https://work.weixin.qq.com/api/doc#90000/90135/90930
在验证回调地址的时候,微信服务器会根据我们之前写的URL地址生成url请求
我们的后台需要根据请求地址传过来的数据,解密后,获得echostr 并返回,同时微信后台会显示配置完成
具体代码如下,当然还要在文档里下载demo simple才行
/**
* 企业微信号验证回调URL
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "/workWxCallback")
public void workWxcheck(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException {
boolean isGet = request.getMethod().toLowerCase().equals("get");
PrintWriter print;
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WxApiUtil.TOKEN, WxApiUtil.EncodingAESKey, WxApiUtil.CORPID);
if(isGet){
// 微信加密签名
String sVerifyMsgSig = request.getParameter("msg_signature");
// 时间戳
String sVerifyTimeStamp = request.getParameter("timestamp");
// 随机数
String sVerifyNonce = request.getParameter("nonce");
// 随机字符串
String sVerifyEchoStr = request.getParameter("echostr");
String sEchoStr; //需要返回的明文
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
try {
sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
sVerifyNonce, sVerifyEchoStr);
System.out.println("verifyurl echostr: " + sEchoStr);
// 验证URL成功,将sEchoStr返回
print = response.getWriter();
print.write(sEchoStr);
print.flush();
} catch (Exception e) {
//验证URL失败,错误原因请查看异常
e.printStackTrace();
}
}
}
/**
* 获得登录者的userId( 在这个应用中userId 等于 staffId )
* 1.取得请求过来的地址中的code
* 2.向微信服务器 获得 accessToken
* 3.通过WxApiUtil.getUserId(accessToken, code) 获得userId
* @param request
* @param response
* @param session
*/
@RequestMapping(value = "/checkUser")
@ResponseBody
public void checkUser(HttpServletRequest request, HttpServletResponse response, HttpSession session){
//获得code
String code = request.getParameter("code");
AccessToken accessTokenBean = null;
try {
if (session.getAttribute("accessToken") == null) {
//获得access_token
accessTokenBean = WxApiUtil.getAccessToken();
session.setAttribute("accessToken", accessTokenBean.getAccess_token());
}
String accessToken = session.getAttribute("accessToken").toString();
//获得userId
String userId = WxApiUtil.getUserId(accessToken, code);
//打印log
logger.info(">>>>>>>>>>>>>>accessToken: {}",accessToken);
logger.info(">>>>>>>>>>>>>>userId: {}",userId);
Integer status = projectStatusService.getNowProjectStatus("xxx");
//如果在维护中
if (status == 0){
//userId是否在白名单里
Integer integer = projectWhitelistService.checkUserId(userId);
if (integer != null){
//将userId作为staffId存进session
session.setAttribute("staffId", userId);
//进入测试页面
response.sendRedirect("http://xxx");
}
}else {
//将userId作为staffId存进session
session.setAttribute("staffId", userId);
response.sendRedirect("http://xxx");
}
} catch (IOException e) {
e.getMessage();
}
}
这里的userId作为员工工号,存进session,这么一来,后续就水到渠成了
需要注意的几个点是:
在上面的代码里我加入了项目状态和白名单的业务判断
有一个地方需要注意的是 WxApiUtil 这个工具类
类源码:
public class WxApiUtil {
private final static Logger logger = LoggerFactory.getLogger(WxApiUtil.class);
/**
* 企业ID
*/
public static String CORPID = "xxx";
/**
* 应用ID
*/
public static Integer AGENTID = xxx;
/**
* 应用密码
*/
public static String SECRET = "xxx";
/**
* //后台应用配置的API接收Token
*/
public static String TOKEN = "xxx";
/**
* //后台应用配置的API接收EncodingAESKey
*/
public static String EncodingAESKey = "xxx";
/**
* 获得ACCESS_TOKEN的请求地址
*/
public static String GET_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET";
//js api
// public static String JS_API = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=%s";
public static String GET_USERID_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE";
/**
* 获取access token
* @return
*/
public static AccessToken getAccessToken(){
// 拼接请求地址
String requestUrl = WxApiUtil.GET_ACCESS_TOKEN_URL;
requestUrl = requestUrl.replace("ID", CORPID);
requestUrl = requestUrl.replace("SECRET", SECRET);
// 获取传回的信息
JSONObject jsonObject = HttpCommonUtil.httpsRequest(requestUrl, "GET", null);
if (jsonObject == null){
new Exception("token内容为空");
}
AccessToken accessToken = new AccessToken();
if (jsonObject.getInteger("errcode") == 0) {
logger.info("accessToken {}",jsonObject);
logger.debug("accessToken {}",jsonObject);
accessToken.setErrcode(jsonObject.getInteger("errcode"));
accessToken.setAccess_token(jsonObject.getString("access_token"));
accessToken.setErrmsg(jsonObject.getString("errmsg"));
accessToken.setExpires_in(jsonObject.getInteger("expires_in"));
return accessToken;
} else {
logger.error("{} get access error,msg:{}", jsonObject.toString());
}
return null;
}
/**
* 获取userId
* @return
*/
public static String getUserId(String accessToken,String code){
String requestUrl = GET_USERID_URL;
// 拼接请求地址
requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken);
requestUrl = requestUrl.replace("CODE", code);
// 获取传回的信息
JSONObject jsonObject = HttpCommonUtil.httpsRequest(requestUrl, "GET", null);
if (jsonObject.getInteger("errcode") == 0){
//企业成员授权时返回 userId 非企业成员openId
String userId = jsonObject.getString("UserId");
return userId;
}
if ( jsonObject.getInteger("errcode") == 42001){
String newAccessToken = getAccessToken().getAccess_token();
getUserId(newAccessToken,code);
} else {
logger.error("{} get userId error,msg:{}", jsonObject.toString());
}
return null;
}
}
这里面的属性都是根据自己企业微信填写的,这个类比较重要,有2个核心方法 getAccessToken和getUserId
在方法里有个工具类比较重要 就是HttpCommonUtil,这是一个http请求统一处理的工具类
代码:
public class HttpCommonUtil {
/**
* 发送https请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
// log.error("连接超时:{}", ce);
} catch (Exception e) {
// log.error("https请求异常:{}", e);
}
return jsonObject;
}
}