feat: 添加企业微信通知器
This commit is contained in:
parent
a088d6440e
commit
f69eeb502c
@ -8,8 +8,8 @@ package com.cicdi.notify;
|
||||
public enum DefaultNotifyType implements NotifyType {
|
||||
|
||||
email("邮件"),
|
||||
sms("短信")
|
||||
;
|
||||
sms("短信"),
|
||||
wechat("微信");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
44
notify-wechat/pom.xml
Normal file
44
notify-wechat/pom.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>notify</artifactId>
|
||||
<groupId>com.cicdi</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>notify-wechat</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.cicdi</groupId>
|
||||
<artifactId>notify-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<version>2.3.11.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.73</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,24 @@
|
||||
package com.cicdi.notify.wechat;
|
||||
|
||||
public class WechatCorpProperties {
|
||||
|
||||
private String corpId;
|
||||
|
||||
private String corpSecret;
|
||||
|
||||
public String getCorpId() {
|
||||
return corpId;
|
||||
}
|
||||
|
||||
public void setCorpId(String corpId) {
|
||||
this.corpId = corpId;
|
||||
}
|
||||
|
||||
public String getCorpSecret() {
|
||||
return corpSecret;
|
||||
}
|
||||
|
||||
public void setCorpSecret(String corpSecret) {
|
||||
this.corpSecret = corpSecret;
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
package com.cicdi.notify.wechat;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cicdi.notify.template.Template;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class WechatMessageTemplate implements Template {
|
||||
|
||||
/**
|
||||
* 应用ID
|
||||
*/
|
||||
private String agentId;
|
||||
|
||||
private String toUser;
|
||||
|
||||
private String toParty;
|
||||
|
||||
private String toTag;
|
||||
|
||||
private String message;
|
||||
|
||||
public String getAgentId() {
|
||||
return agentId;
|
||||
}
|
||||
|
||||
public void setAgentId(String agentId) {
|
||||
this.agentId = agentId;
|
||||
}
|
||||
|
||||
public String getToUser() {
|
||||
return toUser;
|
||||
}
|
||||
|
||||
public void setToUser(String toUser) {
|
||||
this.toUser = toUser;
|
||||
}
|
||||
|
||||
public String getToParty() {
|
||||
return toParty;
|
||||
}
|
||||
|
||||
public void setToParty(String toParty) {
|
||||
this.toParty = toParty;
|
||||
}
|
||||
|
||||
public String getToTag() {
|
||||
return toTag;
|
||||
}
|
||||
|
||||
public void setToTag(String toTag) {
|
||||
this.toTag = toTag;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public BodyInserters.FormInserter<String> createFormInserter(BodyInserters.FormInserter<String> inserter, Map<String, Object> context) {
|
||||
inserter.with("agentid", this.getAgentId())
|
||||
.with("msgtype","text")
|
||||
.with("text",this.createMessage(context));
|
||||
if (StringUtils.hasText(toUser)) {
|
||||
inserter.with("touser", this.createUserIdList(context));
|
||||
}
|
||||
if (StringUtils.hasText(toParty)) {
|
||||
inserter.with("toparty", this.createDepartmentIdList(context));
|
||||
}
|
||||
return inserter;
|
||||
|
||||
}
|
||||
|
||||
public String createJsonRequest(Map<String, Object> context){
|
||||
JSONObject json=new JSONObject();
|
||||
json.put("agentid",getAgentId());
|
||||
json.put("msgtype","text");
|
||||
// TODO
|
||||
// json.put("text",Collections.singletonMap("content",ExpressionUtils.analytical(message, context.getAllValues(), "spel")));
|
||||
json.put("text",Collections.singletonMap("content", message));
|
||||
|
||||
if (StringUtils.hasText(toUser)) {
|
||||
json.put("touser", this.createUserIdList(context));
|
||||
}
|
||||
if (StringUtils.hasText(toParty)) {
|
||||
json.put("toparty", this.createDepartmentIdList(context));
|
||||
}
|
||||
|
||||
return json.toJSONString();
|
||||
}
|
||||
|
||||
|
||||
public UriComponentsBuilder createUriParameter(UriComponentsBuilder builder, Map<String, Object> context){
|
||||
builder.queryParam("agentid", this.getAgentId())
|
||||
.queryParam("msgtype","text")
|
||||
.queryParam("text",this.createMessage(context));
|
||||
if (StringUtils.hasText(toUser)) {
|
||||
builder.queryParam("touser", this.createUserIdList(context));
|
||||
}
|
||||
if (StringUtils.hasText(toParty)) {
|
||||
builder.queryParam("toparty", this.createDepartmentIdList(context));
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String createUserIdList(Map<String, Object> context) {
|
||||
if (StringUtils.isEmpty(toUser)) {
|
||||
return toUser;
|
||||
}
|
||||
return toUser;
|
||||
// return ExpressionUtils.analytical(toUser, context.getAllValues(), "spel");
|
||||
}
|
||||
|
||||
public String createDepartmentIdList(Map<String, Object> context) {
|
||||
if (StringUtils.isEmpty(toParty)) {
|
||||
return toParty;
|
||||
}
|
||||
return toParty;
|
||||
// return ExpressionUtils.analytical(toParty, context.getAllValues(), "spel");
|
||||
}
|
||||
|
||||
public String createMessage(Map<String, Object> context) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("content", message);
|
||||
// json.put("content", ExpressionUtils.analytical(message, context.getAllValues(), "spel"));
|
||||
return json.toJSONString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.cicdi.notify.wechat;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.cicdi.notify.*;
|
||||
import com.cicdi.notify.template.TemplateManager;
|
||||
import com.cicdi.notify.template.TemplateProperties;
|
||||
import com.cicdi.notify.template.TemplateProvider;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WechatNotifierProvider implements NotifierProvider, TemplateProvider {
|
||||
|
||||
private final TemplateManager templateManager;
|
||||
|
||||
public WechatNotifierProvider(TemplateManager templateManager) {
|
||||
this.templateManager = templateManager;
|
||||
}
|
||||
|
||||
// public static final DefaultConfigMetadata notifierConfig = new DefaultConfigMetadata("通知配置", "")
|
||||
// .add("corpId", "corpId", "", new StringType().expand(ConfigMetadataConstants.required.value(true)))
|
||||
// .add("corpSecret", "corpSecret", "", new StringType());
|
||||
//
|
||||
// public static final DefaultConfigMetadata templateConfig = new DefaultConfigMetadata("模版配置", "")
|
||||
// .add("agentId", "应用ID", "", new StringType().expand(ConfigMetadataConstants.required.value(true)))
|
||||
// .add("toUser", "收信人ID", "与部门ID不能同时为空", new StringType())
|
||||
// .add("toParty", "收信部门ID", "与收信人ID不能同时为空", new StringType())
|
||||
// .add("toTag", "按标签推送", "", new StringType())
|
||||
// .add("message", "内容", "最大不超过500字", new StringType().expand(ConfigMetadataConstants.maxLength.value(500L)));
|
||||
|
||||
@Override
|
||||
public NotifyType getType() {
|
||||
return DefaultNotifyType.wechat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider getProvider() {
|
||||
return WechatProvider.corpMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WechatMessageTemplate createTemplate(TemplateProperties properties) {
|
||||
return JSON.parseObject(properties.getTemplate(), WechatMessageTemplate.class);
|
||||
// return Mono.fromSupplier(() -> ValidatorUtils.tryValidate(JSON.parseObject(properties.getTemplate(), org.jetlinks.community.notify.wechat.WechatMessageTemplate.class)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinCorpNotifier createNotifier(NotifierProperties properties) {
|
||||
// WechatCorpProperties wechatCorpProperties = FastBeanCopier.copy(properties.getConfiguration(), new WechatCorpProperties());
|
||||
Map<String, Object> config = properties.getConfiguration();
|
||||
WechatCorpProperties wechatCorpProperties = new WechatCorpProperties();
|
||||
wechatCorpProperties.setCorpId((String) config.get("corpId"));
|
||||
wechatCorpProperties.setCorpSecret((String) config.get("corpSecret"));
|
||||
return new WeixinCorpNotifier(properties.getId(), wechatCorpProperties, templateManager);
|
||||
// return Mono.just(new WeixinCorpNotifier(properties.getId(), client, ValidatorUtils.tryValidate(wechatCorpProperties), templateManager));
|
||||
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public ConfigMetadata getNotifierConfigMetadata() {
|
||||
// return notifierConfig;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ConfigMetadata getTemplateConfigMetadata() {
|
||||
// return templateConfig;
|
||||
// }
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.cicdi.notify.wechat;
|
||||
|
||||
import com.cicdi.notify.Provider;
|
||||
|
||||
public enum WechatProvider implements Provider {
|
||||
corpMessage("微信企业消息通知");
|
||||
|
||||
private final String name;
|
||||
|
||||
WechatProvider(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
package com.cicdi.notify.wechat;
|
||||
|
||||
|
||||
import com.cicdi.notify.AbstractNotifier;
|
||||
import com.cicdi.notify.DefaultNotifyType;
|
||||
import com.cicdi.notify.NotifyType;
|
||||
import com.cicdi.notify.Provider;
|
||||
import com.cicdi.notify.template.TemplateManager;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class WeixinCorpNotifier extends AbstractNotifier<WechatMessageTemplate> {
|
||||
|
||||
private final AtomicReference<String> accessToken = new AtomicReference<>();
|
||||
|
||||
private long refreshTokenTime;
|
||||
|
||||
private final long tokenTimeOut = Duration.ofSeconds(7000).toMillis();
|
||||
|
||||
private static final String tokenApi = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
|
||||
|
||||
private static final String notify = "https://qyapi.weixin.qq.com/cgi-bin/message/send";
|
||||
|
||||
private final WechatCorpProperties properties;
|
||||
|
||||
private final String notifierId;
|
||||
|
||||
@Override
|
||||
public String getNotifierId() {
|
||||
return notifierId;
|
||||
}
|
||||
|
||||
|
||||
public WeixinCorpNotifier(String id, WechatCorpProperties properties, TemplateManager templateManager) {
|
||||
super(templateManager);
|
||||
this.properties = properties;
|
||||
this.notifierId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotifyType getType() {
|
||||
return DefaultNotifyType.wechat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider getProvider() {
|
||||
return WechatProvider.corpMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(WechatMessageTemplate template, Map<String, Object> context) {
|
||||
String token1 = getToken();
|
||||
WebClient.create().post()
|
||||
.uri(UriComponentsBuilder.fromUriString(notify).queryParam("access_token", token1).toUriString())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(BodyInserters.fromValue(template.createJsonRequest(context)))
|
||||
.exchange()
|
||||
.flatMap(clientResponse -> clientResponse.bodyToMono(HashMap.class))
|
||||
.as(this::checkResult)
|
||||
.then();
|
||||
}
|
||||
|
||||
private Mono<HashMap> checkResult(Mono<HashMap> msg) {
|
||||
return msg.doOnNext(map -> {
|
||||
String code = String.valueOf(map.get("errcode"));
|
||||
if ("0".equals(code)) {
|
||||
// log.info("发送微信企业通知成功");
|
||||
} else {
|
||||
// log.warn("发送微信企业通知失败:{}", map);
|
||||
// throw new BusinessException("发送微信企业通知失败:" + map.get("errmsg"), code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getToken() {
|
||||
if (System.currentTimeMillis() - refreshTokenTime > tokenTimeOut || accessToken.get() == null) {
|
||||
return requestToken();
|
||||
}
|
||||
return accessToken.get();
|
||||
}
|
||||
|
||||
private String requestToken() {
|
||||
Mono<ClientResponse> responseMono = WebClient.create().get()
|
||||
.uri(UriComponentsBuilder.fromUriString(tokenApi)
|
||||
.queryParam("corpId", properties.getCorpId())
|
||||
.queryParam("corpSecret", properties.getCorpSecret())
|
||||
.build().toUri())
|
||||
.exchange();
|
||||
|
||||
responseMono.flatMap(resp -> {
|
||||
System.out.println(resp);
|
||||
return resp.bodyToMono(HashMap.class);
|
||||
})
|
||||
.map(map -> {
|
||||
if (map.containsKey("access_token")) {
|
||||
return map.get("access_token");
|
||||
}
|
||||
// TODO 自定义异常
|
||||
// throw new BusinessException("获取Token失败:" + map.get("errmsg"), String.valueOf(map.get("errcode")));
|
||||
return Mono.empty();
|
||||
})
|
||||
.cast(String.class)
|
||||
.doOnNext(r -> {
|
||||
refreshTokenTime = System.currentTimeMillis();
|
||||
accessToken.set(r);
|
||||
});
|
||||
return accessToken.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
accessToken.set(null);
|
||||
refreshTokenTime = 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.cicdi.notify.wechat;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cicdi.notify.*;
|
||||
import com.cicdi.notify.template.AbstractTemplateManager;
|
||||
import com.cicdi.notify.template.Template;
|
||||
import com.cicdi.notify.template.TemplateManager;
|
||||
import com.cicdi.notify.template.TemplateProperties;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Hooks;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author xueye
|
||||
*/
|
||||
public class WechatTest {
|
||||
@Test
|
||||
public void test() {
|
||||
Hooks.onOperatorDebug();
|
||||
// 通知器配置管理器
|
||||
NotifyConfigManager notifyConfigManager = new NotifyConfigManager() {
|
||||
@Override
|
||||
public NotifierProperties getNotifyConfig(NotifyType notifyType, String configId) {
|
||||
NotifierProperties notifierProperties = new NotifierProperties();
|
||||
notifierProperties.setType(DefaultNotifyType.wechat.getId());
|
||||
notifierProperties.setProvider(WechatProvider.corpMessage.getId());
|
||||
notifierProperties.setId("12");
|
||||
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("corpId", "wwbd49ae2419a55a9f");
|
||||
config.put("corpSecret", "TXDRQw_H8gpVKX0E01EmwMXJ4VooXmj65I-mDe0wQ1k");
|
||||
|
||||
notifierProperties.setConfiguration(config);
|
||||
|
||||
return notifierProperties;
|
||||
}
|
||||
};
|
||||
|
||||
// 模板管理器
|
||||
TemplateManager templateManager = new AbstractTemplateManager() {
|
||||
@Override
|
||||
protected TemplateProperties getProperties(NotifyType type, String id) {
|
||||
TemplateProperties templateProperties = new TemplateProperties();
|
||||
templateProperties.setType(DefaultNotifyType.wechat.getId());
|
||||
templateProperties.setProvider(WechatProvider.corpMessage.getId());
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("agentId", "3010084");
|
||||
jsonObject.put("toUser", "XueYe");
|
||||
jsonObject.put("toParty", "");
|
||||
jsonObject.put("toTag", "");
|
||||
jsonObject.put("message", "Hello");
|
||||
|
||||
templateProperties.setTemplate(jsonObject.toJSONString());
|
||||
|
||||
return templateProperties;
|
||||
}
|
||||
};
|
||||
|
||||
NotifierManager notifierManager = new DefaultNotifierManager(notifyConfigManager);
|
||||
|
||||
// register
|
||||
WechatNotifierProvider provider = new WechatNotifierProvider(templateManager);
|
||||
notifierManager.registerProvider(provider);
|
||||
templateManager.register(provider);
|
||||
|
||||
Notifier<Template> notifier = notifierManager.getNotifier(DefaultNotifyType.wechat, "123");
|
||||
notifier.send(templateManager.getTemplate(DefaultNotifyType.wechat, "124"), new HashMap<>());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user