企业微信后端开发获取用户信息时必须对接企业微信,开发者初期一定会遇到的问题:
token失效、返回值不正确。获取access_token是调用企业微信API接口的第一步,相当于创建了一个登录凭证,其它的业务API接口,都需要依赖于access_token来鉴权调用者身份。可以用别人写好的企业微信工具,我推荐weixin-java-cp.jar:
com.github.binarywang
weixin-java-cp
${weixin-java-cp}
官方地址是:
https://developer.work.weixin.qq.com/document/path/91039
这个往往是因为缓存原因造成。企业微信官方明确的给出了,要缓存access_token。官方明确表示:不能频繁调用gettoken接口,否则会遭到频率拦截。这里有必要说一下:
在企业微信开发时,后端程序一定要打印调用access_token的请求日志,包括:请求、返回、解析。只有看日志和单步调试,我们才能知道错误到底在哪里,靠猜是没有意义的,这看起来是题外话。但是务必记住,只要涉及到多个系统对接的时候,一定要打日志,我开发过程中的经验是:几个系统对接的点,往往是出错最频繁的地方。言归正传,给大家看看获取access_token的代码:
/**
* 企业号,此方法是企业号获取access_token
* @param corpid
* @param secret
* @return
*/
public static TokenResponse token(String corpid, String secret) {
//获取token如果存在,取出;不存在时重新获取
String completeUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret="+ secret;
try {
String backJsonString = HttpRequest.sendGet(completeUrl, null);
TokenResponse token = JSON.parseObject(backJsonString, TokenResponse.class);
if (token.success()) {
return token;
} else {
logger.debug("accsesstoken获取失败,errcode:"+token.getErrCode()+",errmsg:"+token.getMessage());
return null;
}
} catch (Exception e) {
logger.debug("--------获取token报错message:" + e.getMessage());
logger.debug("--------获取token报错cause" + e.getCause());
e.printStackTrace();
return null;
}
}
是获取access_token并且转换成为实体,实体情况,实体中的属性为:errcode、errmsg、access_token、expires_in,具体是:
https://developer.work.weixin.qq.com/document/path/91039
见下图:
这里使用的是redis缓存,在红色方框内:
务必注意access_token被覆盖、过期的问题,缓存要加过期时间,redisUtils.set(key, token, 60 * 60); 获取access_token之前要判断缓存中是否存在。
这里说一下,一定要搞清楚,corpId、secret,如果这两个没错,要么是过期,要么是access_token缓存出了问题。过期情况的处理,这里就不赘述了。
还有,要注意缓存的key,千万别因为应用过多、造成缓存的key太多,造成混淆。
出现获取不到用户的情况,首先要考虑用户问题,别人的用户信息能不能获取到?
处理方式是:
/**
* 企业号,获取用户详细信息
* @param token
* @param userId
* @return
*/
public static WxCpUser getUserDetailByUserId(String token, String userId) {
String completeUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=" + token + "&userid=" + userId;
String backJsonString = HttpRequest.sendGet(completeUrl, null);
JSONObject jsonObj = JSON.parseObject(backJsonString);
if(jsonObj.getString("errcode").equals("0")) {
WxCpUser userInfo = JSONObject.parseObject(backJsonString, WxCpUser.class);
return userInfo;
}else {
logger.debug("获取用户详情失败,返回信息:" + backJsonString);
return null;
}
}
但是出了错,这要分情况:
(1)access_token失效,缓存问题;返回1.1里面排查;
(2)有些人一直都可以获取到用户信息,有些人就是获取不到用户信息,那得去看企业微信通讯录
https://work.weixin.qq.com/wework_admin/frame#contacts
再看看自己的业务系统的数据信息,跟企业微信通讯录里面的成员详情-》账号到底是否一致!
这种情况,大概率是access_token不对造成的!或者是2 企业微信构造链接、code问题里面说的,获取code方式有问题。
参考代码:
/**
* 企业号,获取用户详细信息
* @param token
* @param userId
* @return
*/
public static WxCpUser getUserDetailByUserId(String token, String userId) {
String completeUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=" + token + "&userid=" + userId;
String backJsonString = HttpRequest.sendGet(completeUrl, null);
JSONObject jsonObj = JSON.parseObject(backJsonString);
if(jsonObj.getString("errcode").equals("0")) {
WxCpUser userInfo = JSONObject.parseObject(backJsonString, WxCpUser.class);
return userInfo;
}else {
logger.debug("获取用户详情失败,返回信息:" + backJsonString);
return null;
}
}
这个问题非常厉害,处理起来,往往是前端难受、后端也难受。官方文档:
https://developer.work.weixin.qq.com/document/path/91022
前后端分离主流做法:要在hear中带token来访问后端接口。前后端分离的系统后端不用硬编码跳转页面;springmvc可以通过response重定向解决跳转和传参问题。前后端分离系统的处理方式、基于session实现mvc系统的方式是不一样的。所以我分为两类,总结问题如下:
构造链接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE&agentid=AGENTID#wechat_redirect
按照微信官方要求,把参数检查好!这里有人会有疑惑:如果是vue项目前端的路由中带#会影响构造,如何解决?即REDIRECT_URI中带#号怎么办?
给个参考代码:
window.location.href =
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}
&redirect_uri=${encodeURIComponent(window.location.href.split('#')[0])}
&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;
appid: 服务号/企业号的openid
redirect_uri: 当前前端域名,跳回微信会携带code,然后前端拿到code去后台
这种方式,在企业微信中配应用直接是应用的地址:
这种方式,前端做的比较复杂,思路是这个。
如果有问题,好好检查参数!检查参数!
好了之后,记得把code、其他参数之类传到后端处理,后端代码在2.2 手动处理好构造链接中。
你也可以在企业微信中按照这么配应用:
如果你是运用了开头说的weixin-java-cp.jar可以参考我写的这篇博客:
手把手教你企业微信开发(二)
这是前后端不分离的情况。当然,如果你是在接盘别人的代码,而且没法用weixin-java-cp.jar,那就在后端:
/**
* 企业号,通过code获取微信返回值
* @param corpCode 应用Id
* @param corpKey 应用的Secret
* @param code 用户获取的code
* @return
*/
public static QYAcessToken getQyUserIdAndAppId(String access_token , String code) {
String completeUrlOpenid = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=" + access_token + "&code="+ code;
try {
String backJsonString = HttpRequest.sendGet(completeUrlOpenid, null);
QYAcessToken responseEntity = JSON.parseObject(backJsonString, QYAcessToken.class);
return responseEntity;
} catch (Exception e) {
logger.debug("返回xml有误 Xm:" + e.getMessage());
return null;
}
}
暂时总结问题如上。如果你在企业微信开发过程中遇到了除了上面之外,不好解决的困难,可以联系我。我们一起讨论。