SpringBoot中企业微信的API调用

说明

企业微信官方提供的均为API接口,没有提供集成SDK。因此无需引入Maven依赖,直接以Https方式请求即可。

有些第三方提供了集成的Java SDK,可根据需求自行选用。

本文采用直接调用官方API的方式。

基础配置

企业微信注册后,可得到corpIdagentIdcorpSecret的信息。

而企业微信的所有接口均以https://qyapi.weixin.qq.com/cgi-bin开头。

综上,在yml中定义配置:

yml 复制代码
qywx:
  endpoint: https://qyapi.weixin.qq.com/cgi-bin
  corpId: wx00000000000000ba
  agentId: 1000000
  corpSecret: V0000000000_00000000000000000000000000000wc

然后定义一个配置类:

java 复制代码
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;


@Component
@Configuration
@ConfigurationProperties(prefix = QywxConfig.prefix)
@Data
public class QywxConfig {

    public final static String prefix = "qywx";

    /**
     * 企业微信请求地址
     */
    private String endpoint;
	
    /**
     * 企业id
     */
    private String corpId;

    private String agentId;

    private String corpSecret;
}

这样即可在容器类中引用配置。

发送请求

服务端需要向企业微信发送请求。这里使用Forest来进行请求。

首先引入依赖:

xml 复制代码
<!-- forest -->
<dependency>
    <groupId>com.dtflys.forest</groupId>
    <artifactId>forest-spring-boot-starter</artifactId>
    <version>1.5.32</version>
</dependency>

考虑到所有的请求都需拼接共同的企业微信请求地址,因此为Forest添加拦截器来统一处理:

java 复制代码
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.interceptor.Interceptor;
import com.dtflys.forest.reflection.ForestMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class QywxForestInterceptor implements Interceptor<String> {

    @Autowired
    private QywxConfig qywxConfig;

    @Override
    public void onInvokeMethod(ForestRequest req, ForestMethod method, Object[] args) {
        req.setBasePath(qywxConfig.getEndpoint());
    }
}

然后定义请求的接口类:

java 复制代码
import com.cosmoplat.hyida.core.result.Result;
import com.cosmoplat.qingyin.safety.qywx.controller.model.dto.MessageTextDto;
import com.cosmoplat.qingyin.safety.qywx.controller.model.dto.QyWxUserDetailDto;
import com.cosmoplat.qingyin.safety.qywx.inteceptor.SafetyForestInterceptor;
import com.dtflys.forest.annotation.*;

import java.util.Map;

@BaseRequest(interceptor = QywxForestInterceptor.class, headers = {"Accept: */*", "Content-Type: application/json"})
public interface QywxForestClient {

    /**
     * 获取access_token
     * @param corpId
     * @param corpSecret
     * @return
     */
    @Get(url = "/gettoken?corpid={corpId}&corpsecret={corpSecret}")
    Map<String,Object> getToken(@Var("corpId") String corpId, @Var("corpSecret") String corpSecret);

}

当调用时,引入QywxConfigQywxForestClient

@Resource
private QywxConfig qywxConfig;

@Resource
private QywxForestClient qywxForestClient;

private String getAccessToken() {
    // 根据corpId和corpSecret获取 access_token
    String corpId = qywxConfig.getCorpId();
    String corpSecret = qywxConfig.getCorpSecret();
    
    Map<String, Object> tokenResult = qywxForestClient.getToken(corpId, corpSecret);
	
	if (!result.get("errcode").equals(0) || StringUtils.isEmpty(result.get("access_token"))) {
        System.out.println("获取企业微信access_token失败!" + result.get("errmsg"));            
    }
	
    return String.valueOf(result.get("access_token"));
}

关于access_token

access_token的官方文档地址:

https://developer.work.weixin.qq.com/document/path/91039

里面明确提到了3个注意事项:

  • 为了安全考虑,开发者 请勿 将 access_token 返回给前端,需要开发者保存在后台,所有访问企业微信api的请求由后台发起。
  • 开发者需要缓存access_token,用于后续接口的调用(注意:不能频繁调用gettoken接口,否则会受到频率拦截)。当access_token失效或过期时,需要重新获取。
  • access_token的有效期通过返回的expires_in来传达,正常情况下为7200秒(2小时),有效期内重复获取返回相同结果,过期后获取会返回新的access_token。

因此,最佳实践应使用Redis缓存access_token。当获取access_token时先从Redis中取。若取不到,则向企业微信发起请求获取,并写入到Redis中。

携带参数

以发送应用消息为例,现在要发送一个文本消息。

参考官方文档:

请求方式:POST(HTTPS)

请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN

参数示例为:

js 复制代码
{
   "touser" : "UserID1|UserID2|UserID3",
   "toparty" : "PartyID1|PartyID2",
   "totag" : "TagID1 | TagID2",
   "msgtype" : "text",
   "agentid" : 1,
   "text" : {
       "content" : "你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看<a href=\"http://work.weixin.qq.com\">邮件中心视频实况</a>,聪明避开排队。"
   },
   "safe":0,
   "enable_id_trans": 0,
   "enable_duplicate_check": 0,
   "duplicate_check_interval": 1800
}

返回示例为:

js 复制代码
{
  "errcode" : 0,
  "errmsg" : "ok",
  "invaliduser" : "userid1|userid2",
  "invalidparty" : "partyid1|partyid2",
  "invalidtag": "tagid1|tagid2",
  "unlicenseduser" : "userid3|userid4",
  "msgid": "xxxx",
  "response_code": "xyzxyz"
}

现在根据文档的信息来添加接口。

首先定义一个MessageTextDto对象来承载发送时的参数。其中text属性又是一个对象。

java 复制代码
import io.swagger.annotations.ApiModel;
import lombok.Data;

@Data
public class MessageTextDto {

    /**
     * 指定接收消息的成员,成员ID列表(多个接收者用'|'分隔,最多支持1000个)。
     * 特殊情况:指定为"@all",则向该企业应用的全部成员发送
     */
    private String touser;

    /**
     * 指定接收消息的部门,部门ID列表,多个接收者用'|'分隔,最多支持100个。
     * 当touser为"@all"时忽略本参数
     */
    private String toparty;

    /**
     * 指定接收消息的标签,标签ID列表,多个接收者用'|'分隔,最多支持100个。
     * 当touser为"@all"时忽略本参数
     */
    private String totag;

    /**
     * 消息类型,此时固定为:text
     * 必填
     */
    private String msgtype = "text";

    /**
     * 企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
     * 必填
     */
    private String agentid;

    /**
     * 消息内容,最长不超过2048个字节,超过将截断(支持id转译)
     * 必填
     */
    private MessageText text = new MessageText();

    /**
     * 表示是否是保密消息,0表示可对外分享,1表示不能分享且内容显示水印,默认为0
     */
    private String safe;

    /**
     * 表示是否开启id转译,0表示否,1表示是,默认0。仅第三方应用需要用到,企业自建应用可以忽略。
     */
    private String enable_id_trans;

    /**
     * 	表示是否开启重复消息检查,0表示否,1表示是,默认0
     */
    private String enable_duplicate_check;

    /**
     * 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
     */
    private String duplicate_check_interval;
}

MessageText对象:

java 复制代码
import lombok.Data;

@Data
public class MessageText {

    /**
     * 消息内容,最长不超过2048个字节,超过将截断(支持id转译)
     * 必填
     */
    private String content;
}

然后在QywxForestClient中添加接口:

java 复制代码
@BaseRequest(interceptor = QywxForestInterceptor.class, headers = {"Accept: */*", "Content-Type: application/json"})
public interface QywxForestClient {

    /**
     * 获取访问用户敏感信息
     * @param messageTextDto
     * @param accessToken
     * @return
     */
    @Post(url = "/message/send?access_token={accessToken}")
    Map<String, Object> messageSend(@Body MessageTextDto messageTextDto, @Var("accessToken") String accessToken);
}

这样即可进行调用:

java 复制代码
private Map<String, Object> sendMessage(String touser, String content) {
    if (StrUtil.isEmpty(touser)) {
		// 消息接收者为空
		return Maps.newHashMap();
    }

    MessageTextDto messageTextDto = new MessageTextDto();
    messageTextDto.setAgentid(safetyConfig.getAgentId());
    messageTextDto.setTouser(touser);
    messageTextDto.getText().setContent(content);

    String accessToken = getAccessToken();

    Map<String, Object> result = qywxForestClient.messageSend(messageTextDto, accessToken);

    return result;
}

其中getAccessToken()调用了前面封装的getAccessToken方法。

相关推荐
kylinxjd5 分钟前
spring boot发送邮件
java·spring boot·后端·发送email邮件
杨荧15 分钟前
【JAVA开源】基于Vue和SpringBoot的旅游管理系统
java·vue.js·spring boot·spring cloud·开源·旅游
2401_857439693 小时前
Spring Boot新闻推荐系统:用户体验优化
spring boot·后端·ux
进击的女IT4 小时前
SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
java·spring boot·后端
杨半仙儿还未成仙儿5 小时前
Spring框架:Spring Core、Spring AOP、Spring MVC、Spring Boot、Spring Cloud等组件的基本原理及使用
spring boot·spring·mvc
一 乐5 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
IT学长编程7 小时前
计算机毕业设计 二手图书交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·二手图书交易系统
艾伦~耶格尔8 小时前
Spring Boot 三层架构开发模式入门
java·spring boot·后端·架构·三层架构
man20178 小时前
基于spring boot的篮球论坛系统
java·spring boot·后端
Java探秘者9 小时前
Maven下载、安装与环境配置详解:从零开始搭建高效Java开发环境
java·开发语言·数据库·spring boot·spring cloud·maven·idea