前言
我们需要实现企业微信的需求,当公司员工如果超过了多少次,我们就定时的发送消息给他
比如: 某某迟到打卡多少次,请及时补卡,忘记打卡,请补发打卡流程的功能
在查看了企业微信的开发者文档发现,企微是提供了对应的消息api来给到开发者去调用的具体请看官网
https://developer.work.weixin.qq.com/document/path/90235 官网地址
企业微信开放了消息发送接口,企业可以使用这些接口让自定义应用与企业微信后台或用户间进行双向通信。
企业微信提供了二种发送消息,一种是发送应用消息,一种是发送群聊消息,很显然,我们只需要调用发送应用消息就可以满足
我们的需求了.
流程图
官方的流程图看起来好像是有点复杂,但是,其实我们要实现上面的需求只需要请求2个接口就好了,里面的细节以及全部被封装好了
发送应用消息
接口定义:
应用支持推送文本、图片、视频、文件、图文等类型。
**请求方式:**POST(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
参数说明:
参数 | 是否必须 | 说明 |
access_token | 是 | 调用接口凭证 |
获取access_token
获取access_token是调用企业微信API接口的第一步,相当于创建了一个登录凭证,其它的业务API接口,都需要依赖于access_token来鉴权调用者身份。
因此开发者,在使用业务接口前,要明确access_token的颁发来源,使用正确的access_token。
请求方式: GET(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
参数说明:
参数 | 必须 | 说明 |
corpid | 是 | 企业ID,获取方式参考:术语说明-corpid |
corpsecret | 是 | 应用的凭证密钥,获取方式参考:术语说明-secret |
具体请看官方文档: https://developer.work.weixin.qq.com/document/path/91039
注意的点:
开发者需要缓存access_token,用于后续接口的调用(注意:不能频繁调用gettoken接口,否则会受到频率拦截)。当access_token失效或过期时,需要重新获取。
access_token的有效期通过返回的expires_in来传达,正常情况下为7200秒(2小时),有效期内重复获取返回相同结果,过期后获取会返回新的access_token。
由于企业微信每个应用的access_token是彼此独立的,所以进行缓存时需要区分应用来进行存储。
access_token至少保留512字节的存储空间。
企业微信可能会出于运营需要,提前使access_token失效,开发者应实现access_token失效时重新获取的逻辑。
接下来代码实现企业微信发送应用消息:
代码实现:
创建一个springboot 项目增加对应的依赖:
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.15</version>
</dependency>
</dependencies>
yml文件配置:
server:
port: 8081
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://139.196.140.243/data-story-oa?serverTimezone=GMT%2B8&useSSL=false&allowMultiQueries=true
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml,
type-aliases-package: com.datastory.bean
logging:
level:
com.example.springbootmybatisplusintegrat: debug
wx:
corpid:
corpsecret:
配置主要加入了mybatis 的配置以及 日志配置,.不过注意的是 wx 里面的配置对应调用获取access_token的 企业ID和 应用的凭证密钥获取方式请看api官网.
代码实现
获取 getAccessToken
由于上面说的AccessToken 是有时间限制,并且没天有请求次数,所以我这里创建了一张表来保存AccessToken 并且加入了过期时间,
每次请求接口的时候查询数据库,然后对比时间判断token是否过期,没有过期贼继续使用,过期贼请求接口,然后更新数据库的token.
@Override
public String getToken(String type) {
//请求数据库查询
AuthorizeToken authorizeToken = iAuthorizeTokenService.getAuthorizeToken(type);
String access_token = null;
long createTime = System.currentTimeMillis();
if (Objects.nonNull(authorizeToken)) {
access_token = authorizeToken.getAccessToken();
//当前token过期时间少于或者等于当前调用时间,那就重新调用接口,并且更新
if (authorizeToken.getEndTime() <= createTime) {
access_token = getAccessToken(new AuthorizeToken(authorizeToken.getId(),
createTime,
type));
}
} else {
access_token = getAccessToken(new AuthorizeToken(
createTime,
type));
}
return access_token;
}
public String getAccessToken(AuthorizeToken authorizeToken) {
Map<String, Object> map = new HashMap<>(2);
map.put("corpid", corpid);
map.put("corpsecret", corpsecret);
Gson gson = new Gson();
Map<String, Object> dataMap = gson.fromJson(HttpUtil.get(GETTOKEN, map), Map.class);
String access_token = dataMap.get("access_token").toString();
log.info("调用token请求-->" + new Gson().toJson(dataMap));
authorizeToken.setAccessToken(access_token);
Long endTime = authorizeToken.getCreateTime() +
Double.valueOf(dataMap.get("expires_in").toString()).longValue() * 1000;
authorizeToken.setEndTime(endTime);
iAuthorizeTokenService.saveOrUpdate(authorizeToken);
return access_token;
}
GETTOKEN 常量: private static final String GETTOKEN = “https://qyapi.weixin.qq.com/cgi-bin/gettoken”;
以上代码就实现了获取AccessToken的部分了,接下来我们发送消息的时候会使用到对应的token.
发送消息 wxSend
public String wxSend(String userId, String content) {
Gson gson = new Gson();
Map<String, Object> map = new HashMap<>(5);
map.put("touser", userId);
map.put("totag", "测试发消息");
map.put("msgtype", "text");
map.put("agentid", "1000019");
Map<String, Object> contentMap = new HashMap<>(1);
contentMap.put("content", content);
map.put("text", contentMap);
String url = MESSAGESEND + "?access_token=" + getToken("dk");
String data = HttpUtil.post(url, gson.toJson(map));
return data;
}
测试发送消息:
String wxSend(String userId){
String content = "亲爱的"+userId+",你今天忘记打卡了,请及时发起补打卡流程。";
String contentData = "亲爱的"+userId+",你今天忘记打卡了,请及时发起补打卡流程。你本月的漏打卡次数已达3次,若再漏打卡,将视为迟到处理,请注意。";
wxService.wxSend(userId, content);
return wxService.wxSend(userId, contentData);
}
注意userid就是企业员工的唯一id,这个可以从接口中获取,也可以通过企业微信后台导出,发送成功的话,那么你会看到在企微上面会有人发送对应的消息给你.