企业微信-内部应用api的调用与实现
文章目录
前言
在企业管理方面,企业微信提供了许多方便的api接口,调用也非常简单。接下来本章就重点介绍如何快捷的接入企业微信并且调用企业微信的相关功能。(个人学习使用并不全面,如有错误欢迎指正。绝对听劝!)
一、获取access_token
调用企业微信api必传参数access_token上一章也简单说了下,大家可以通过access_token工具 来获取access_token。参数不明白的朋友请看上一章的第一点。域名与ip白名单
大家注意红圈的两个参数,这是企业微信统一返回参数中比较常用的两个,请看表
参数名 | 中文 | 描述 |
---|---|---|
errcode | 错误码 | 0是成功,非0码时来这个文档里搜一下即可命中80%的错误 全局错误码 |
errmsg | 错误提示 | ok是成功, errcode非0码时,这个参数会包含基本错误信息已经错误码的描述链接 |
重点:access_token获取过来只有两个小时有效,并且不能频繁获取,所以后端服务这边需要做一个缓存,切记不能频繁获取。
二、通过Apifox调用测试
成功获取access_token的朋友们,可以使用apifox工具调用企业微信的api,建议大家接某个api时都用apifox先调用一遍,这样编写后端代码时会轻松很多。这里我们通过获取员工基本信息接口来做个测试。企业微信-读取成员官方文档入口
该接口的第二个参数userid,文档中有简单说明就不过多赘述了,开发者可以去企业管理的通讯录里获取,看图账号就是这个用户的userid
1.apifox请求成功示例
该接口能获取到用户非私密的数据,如果想要获取用户私密数据比如头像,地址等需要用户手动授权,有兴趣的朋友可以去研究一下或者艾特我出一版。
2.apifox请求失败示例
如果出现如下提示,根据本章第一点表中的排查方式,排查一下就明确问题了。当然你也可以直接点errmsg中的链接 https://open.work.weixin.qq.com/devtool/query?e=60020
3.apifox请求失败60020解决方案
ip白名单的问题非常好解决,提示也说明了,not allow to access from your ip “报错中的ip”,你就把这个ip放到应用白名单里就行了。这里可以看到errmsg消息中有个 hint 数据,这个数据看本章第三节的yml配置。
不知道这个界面在哪的,请恶补第一章。
值得注意的是不要搞错应用,调用api的access_token是通过哪个应用的corpsecret生成的就将报错ip填到哪个应用(ps:应用多了确实会弄错,要细心一点)
4.其它错误
如果获取access_token遇到其它错误大概率是45009被禁ip或者接口了(调用太频繁以及corpsecret错误次数太多都会被禁ip)
一共就两个参数,确保两个参数正确包成功的。
三、后端代码与实现
本节使用springboot框架实现。
1. yml全局配置
qywx:
url: https://qyapi.weixin.qq.com #企业微信api出口根路径
#如果嫌public-path麻烦可以舍弃这个配置url用:https://qyapi.weixin.qq.com/cgi-bin代替
public-path: cgi-bin #接口目录,最终会拼接在url后面,
debug-mode: false #是否开启api的debug-mode模式
corpId: 你的企业ID
secret: 你的应用密钥
debug-mode这个配置要注意了!!
上文有个引子的就是hint这个参数,这里重点介绍。
有些接口报错后返回的提示信息不足以定位到错误就需要看hint参数了,该参数的值只有在调用接口时url上携带debug=1才会神效。debug模式相关文档
debug-mode配置就是判断是否开启debug调用,如果开启那么该api会被限制为每分钟不能超过5次!!
2.服务层代码实现
示例代码没有用feign,后续用feign调用更方便。当然也取决于项目的技术选型就不过多赘述了,看代码!
业务逻辑代码
public class CallCase {
@Value("${qywx.url}")
private String url;
@Value("${qywx.public-path}")
private String publicPath;
@Value("${qywx.debug-mode}")
private boolean debugMode;
@Value("${qywx.corpId}")
private String corpId;
@Value("${qywx.secret}")
private String secret;
@Resource
private RestTemplate restTemplate;
public static AccessTokenCache accessTokenCache = new AccessTokenCache();
@Test
public void CallCaseUserGet(){
//先获取access_token
String token;
//判断是否需要获取新token
//后续accessTokenCache的相关代码建议移到redis中储存
if (accessTokenCache.getExpiresIn()==null||System.currentTimeMillis()>=accessTokenCache.getExpiresIn()){
token = getToken();
//token缓存7000秒
accessTokenCache.setAccess_token(token);
accessTokenCache.setExpiresIn(System.currentTimeMillis()+7000*1000);
}else {
token = accessTokenCache.getAccess_token();
}
//获取用户数据
User user = getUser(token, "企业微信对应用户的userid");
System.out.println(0);
}
private String getToken(){
//处理企业微信根路径
String practicalUrl = url+"/"+publicPath;
if (debugMode){
practicalUrl+="debug=1";
}
practicalUrl+="/gettoken?corpid={corpid}&corpsecret={corpsecret}";//拼接获取token的api路径
ResponseEntity<Map> response = restTemplate.getForEntity(practicalUrl, Map.class, corpId, secret);
Map date = response.getBody();
Integer errCode = (Integer) date.get("errcode");
if (errCode!=0){
throw new RuntimeException("获取企微access_token失败,企微反馈:"+date.get("errmsg"));
}
return (String) date.get("access_token");
}
private User getUser(String access_token, String userid){
//处理企业微信根路径
String practicalUrl = url+"/"+publicPath;
if (debugMode){
practicalUrl+="debug=1";
}
practicalUrl+="/user/get?access_token={access_token}&userid={userid}";//拼接获取用户数据的api路径
ResponseEntity<User> response = restTemplate.getForEntity(practicalUrl, User.class, access_token, userid);
User user = response.getBody();
if (user==null){
throw new RuntimeException("请求异常:"+response.getStatusCode());
}
if (user.getErrcode()!=0){
throw new RuntimeException("获取企微access_token失败,企微反馈:"+user.getErrmsg());
}
return user;
}
}
token缓存实体类
//token缓存实体类
public static class AccessTokenCache{
//token
private String access_token;
//过期时间
private Long expiresIn;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public Long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn;
}
}
企业微信用户数据实体类
//企业微信用户数据实体类(数据不全,正式使用请按照企业微信的json进行配置)
public class User{
private Integer errcode;
private String errmsg;
private String userid;
private String name;
private String alias;
private String mobile;
public Integer getErrcode() {
return errcode;
}
public void setErrcode(Integer errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
总结
企业微信api调用并不复杂,成功获取的access_token就成功大半了,获取access_token要注意的是应用密钥和应用白名单,确保配置的ip白名单是密钥对应的应用就行了。希望这篇文章能帮到大家,后续也会陆续出一些接企业微信的文章,有错的地方欢迎指正。