个人理解
首先拥有一个可以用于测试的企业微信,获取到
企业的id 【cropID】
企业应用的id【agentID】
管理组的凭证秘钥【corpSecret】
其次是创建用于发送请求的封装类,详细的字段及说明请参考 官方文档
建立封装类后需要做的只有两步 —>
1.发起指定 URL 的 GET 请求来获取token
https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid= " 输入你的企业ID “&corpsecret=” 管理组的凭证秘钥 "
2.将GET请求获取到的 token 取出,放入到指定 URL 的 PSET 请求中 发送需要推送的消息和接受消息的企业微信成员账号
https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token= “GET请求获取到的 token”
实作范例
配置 application.yml
weixin: # 这组是测试用的配置, 用户要加入 luce 的企业微信群组才能正常使用
url: https://qyapi.weixin.qq.com
corpid: wwda5771bac49cd769 # 企业ID
corpsecret: WCtyURlQUa91EjxMb4cc9axpaam40hXkXBf3m_INi_0 # 凭证秘钥
agentid: 1000002 # 应用ID
Dto类
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
@ApiModel(description = "消息创建DTO")
public class MessageCreateDto {
@ApiModelProperty(value = "成员ID列表(消息接收者,最多支持1000个)。每个元素的格式为: corpid/userid,其中,corpid为该互联成员所属的企业,userid为该互联成员所属企业中的帐号。如果是本企业的成员,则直接传userid即可")
private String toUser;
@NotBlank
@ApiModelProperty(value = "消息内容,最长不超过2048个字节", required = true)
private String content;
public String getToUser() {
return toUser;
}
public void setToUser(String toUser) {
this.toUser = toUser;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Servuce层
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.ione.base.exception.IllegalApiUsageException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* 企业微信API. QyApi stand for 企業 API
*/
@Service
public class QyApiService {
private Logger logger = LoggerFactory.getLogger(QyApiService.class);
private String url;
private String corpid;
private String corpsecret;
private String agentid;
private LoadingCache<String,String> tokenCache = CacheBuilder.newBuilder()
.maximumSize(1)
.expireAfterWrite(3600,TimeUnit.SECONDS) // weixin token expire in 7200 sec
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
return getToken();
}
});
/**
* ${ione.weixin.url} 用来获取配置中的固定值
*
*/
@Value(value = "${ione.weixin.url}")
public void setUrl(String url) {
this.url = url;
}
@Value(value = "${ione.weixin.corpid}")
public void setCorpid(String corpid) {
this.corpid = corpid;
}
@Value(value = "${ione.weixin.corpsecret}")
public void setCorpsecret(String corpsecret) {
this.corpsecret = corpsecret;
}
@Value(value = "${ione.weixin.agentid}")
public void setAgentid(String agentid) {
this.agentid = agentid;
}
/**
*获取token 的方法
*
*/
protected String getToken() {
String apiUrl = String.format("%s/cgi-bin/gettoken?corpid=%s&corpsecret=%s", url, corpid, corpsecret);
RestTemplate template = new RestTemplate();
Map<String, Object> result = template.getForObject(apiUrl, Map.class);
String token = (String) result.get("access_token");
logger.debug("[QY] token url: {}", apiUrl);
logger.info("[QY] token result: {}", result);
int errcode = (int) result.getOrDefault("errcode", 0);
String errmsg = (String) result.getOrDefault("errmsg", 0);
if (errcode != 0) {
throw new IllegalApiUsageException(errmsg);
}
return token;
}
/**
* 发送消息. https://open.work.weixin.qq.com/api/doc/90000/90135/90250
*
* @param toUser 成员ID列表(消息接收者,最多支持1000个)。每个元素的格式为: corpid/userid,其中,corpid为该互联成员所属的企业,userid为该互联成员所属企业中的帐号。如果是本企业的成员,则直接传userid即可
* @param content 消息内容,最长不超过2048个字节
* @return
*/
public Map<String, Object> sendMessage(String toUser, String content) {
String token = "";
try {
token = this.tokenCache.get("TOKEN");
} catch (ExecutionException e) {
logger.error("get token from cache fail", e);
}
String apiUrl = String.format("%s/cgi-bin/message/send?access_token=%s", url, token);
Map<String, Object> params = new HashMap<>();
params.put("touser", toUser);
params.put("msgtype", "text");
params.put("agentid", agentid);
params.put("safe", 0);
params.put("text", Map.of("content", content));
RestTemplate template = new RestTemplate();
logger.debug("[QY] send message url: {}", url);
logger.info("[QY] send message param: {}", params);
Map<String, Object> result = template.postForObject(apiUrl, params, Map.class);
logger.info("[QY] send message result: {}", result);
return result;
}
}
Controller层
import com.ione.weixin.domain.dto.MessageCreateDto;
import com.ione.weixin.service.QyApiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Map;
@Api(tags = "企业微信API")
@RestController
public class WeixinController {
private QyApiService service;
@Autowired
public void setService(QyApiService service) {
this.service = service;
}
@ApiOperation(value = "发送消息. https://open.work.weixin.qq.com/api/doc/90000/90135/90250")
@PostMapping("weixin/messages")
Map<String, Object> sendMessage(@RequestBody @Valid MessageCreateDto dto) {
return service.sendMessage(dto.getToUser(), dto.getContent());
}
}
调用示范
/**
* 企业微信推送:内容
*/
private final StringBuffer content = new StringBuffer();
/**
* 企业微信推送:账号
*/
private final StringBuffer userNo = new StringBuffer();
/**
* 在业务逻辑中通过 StringBuffer 的 append() 方法添加需要通知的用户账号和通知内容
*/
//发送企业微信通知
if (content.length() > 0 && !StringUtils.isEmpty(userNo)) {
weixinClient.sendMessage(Map.of("toUser", userNo, "content", content));
}
//清除字符缓存
content.delete(0, content.length());
userNo.delete(0, userNo.length());