From 957245ed99a511617ddc237c867c01cf5b89b7cb Mon Sep 17 00:00:00 2001 From: xueye Date: Sat, 3 Jul 2021 01:05:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=92=89=E9=92=89?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E9=80=9A=E7=9F=A5=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/cicdi/notify/DefaultNotifyType.java | 3 +- notify-dingtalk/pom.xml | 45 ++++++ .../dingtalk/DingTalkMessageTemplate.java | 123 +++++++++++++++++ .../notify/dingtalk/DingTalkNotifier.java | 130 ++++++++++++++++++ .../dingtalk/DingTalkNotifierProvider.java | 65 +++++++++ .../notify/dingtalk/DingTalkProperties.java | 29 ++++ .../notify/dingtalk/DingTalkProvider.java | 30 ++++ .../cicdi/notify/dingtalk/DingTalkTest.java | 67 +++++++++ pom.xml | 1 + 9 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 notify-dingtalk/pom.xml create mode 100644 notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkMessageTemplate.java create mode 100644 notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifier.java create mode 100644 notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifierProvider.java create mode 100644 notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProperties.java create mode 100644 notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProvider.java create mode 100644 notify-dingtalk/src/test/java/com/cicdi/notify/dingtalk/DingTalkTest.java diff --git a/notify-core/src/main/java/com/cicdi/notify/DefaultNotifyType.java b/notify-core/src/main/java/com/cicdi/notify/DefaultNotifyType.java index a61a3dd..ac34440 100644 --- a/notify-core/src/main/java/com/cicdi/notify/DefaultNotifyType.java +++ b/notify-core/src/main/java/com/cicdi/notify/DefaultNotifyType.java @@ -9,7 +9,8 @@ public enum DefaultNotifyType implements NotifyType { email("邮件"), sms("短信"), - wechat("微信"); + wechat("微信"), + dingTalk("钉钉"); private final String name; diff --git a/notify-dingtalk/pom.xml b/notify-dingtalk/pom.xml new file mode 100644 index 0000000..a3c0da9 --- /dev/null +++ b/notify-dingtalk/pom.xml @@ -0,0 +1,45 @@ + + + + notify + com.cicdi + 1.0-SNAPSHOT + + 4.0.0 + + notify-dingtalk + + + 8 + 8 + + + + + com.cicdi + notify-core + 1.0-SNAPSHOT + + + com.alibaba + fastjson + 1.2.73 + compile + + + org.apache.httpcomponents + httpclient + 4.5.12 + compile + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkMessageTemplate.java b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkMessageTemplate.java new file mode 100644 index 0000000..678fa91 --- /dev/null +++ b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkMessageTemplate.java @@ -0,0 +1,123 @@ +package com.cicdi.notify.dingtalk; + +import com.alibaba.fastjson.JSONObject; +import com.cicdi.notify.template.Template; + +import java.util.Collections; +import java.util.Map; + +/** + * 钉钉消息通知模板 + * + * @author xueye + */ +public class DingTalkMessageTemplate implements Template { + + /** + * 应用ID + */ + private String agentId; + + private String userIdList; + + private String departmentIdList; + + private boolean toAllUser; + + private String message; + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public String getUserIdList() { + return userIdList; + } + + public void setUserIdList(String userIdList) { + this.userIdList = userIdList; + } + + public String getDepartmentIdList() { + return departmentIdList; + } + + public void setDepartmentIdList(String departmentIdList) { + this.departmentIdList = departmentIdList; + } + + public boolean isToAllUser() { + return toAllUser; + } + + public void setToAllUser(boolean toAllUser) { + this.toAllUser = toAllUser; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String createFormInserter(Map context) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("agent_id", this.getAgentId()); + jsonObject.put("to_all_user", this.toAllUser); + jsonObject.put("msg", createMessage(context)); + + if (null != userIdList && !"".equals(userIdList)) { + jsonObject.put("userid_list", createUserIdList(context)); + } + if (null != departmentIdList && !"".equals(departmentIdList)) { + jsonObject.put("dept_id_list", createDepartmentIdList(context)); + } + return jsonObject.toJSONString(); + } + +// public UriComponentsBuilder createUriParameter(UriComponentsBuilder builder, Map context) { +// builder.queryParam("agent_id", this.getAgentId()) +// .queryParam("to_all_user", String.valueOf(toAllUser)) +// .queryParam("msg", this.createMessage(context)); +// if (StringUtils.hasText(userIdList)) { +// builder.queryParam("userid_list", this.createUserIdList(context)); +// } +// if (StringUtils.hasText(departmentIdList)) { +// builder.queryParam("dept_id_list", this.createDepartmentIdList(context)); +// } +// return builder; +// } + + public String createUserIdList(Map context) { + if (null == userIdList || "".equals(userIdList)) { + return userIdList; + } +// return ExpressionUtils.analytical(userIdList, context, "spel"); + return userIdList; + } + + public String createDepartmentIdList(Map context) { + if (null == departmentIdList || "".equals(departmentIdList)) { + return departmentIdList; + } + return departmentIdList; +// return ExpressionUtils.analytical(departmentIdList, context, "spel"); + } + + public JSONObject createMessage(Map context) { + JSONObject json = new JSONObject(); + json.put("msgtype", "text"); + json.put("text", Collections.singletonMap("content", message)); +// json.put("text", Collections.singletonMap("content", ExpressionUtils.analytical(message, context.getAllValues(), "spel"))); + String s = json.toJSONString(); +// return json.toJSONString(); + return json; + } + +} diff --git a/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifier.java b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifier.java new file mode 100644 index 0000000..abe311a --- /dev/null +++ b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifier.java @@ -0,0 +1,130 @@ +package com.cicdi.notify.dingtalk; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +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.apache.http.NameValuePair; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +public class DingTalkNotifier extends AbstractNotifier { + + private final AtomicReference accessToken = new AtomicReference<>(); + + private long refreshTokenTime; + + private final long tokenTimeOut = Duration.ofSeconds(7000).toMillis(); + + private static final String tokenApi = "https://oapi.dingtalk.com/gettoken"; + + private static final String notifyApi = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"; + + private final DingTalkProperties properties; + + private final String notifierId; + + @Override + public String getNotifierId() { + return notifierId; + } + + public DingTalkNotifier(String id, DingTalkProperties properties, TemplateManager templateManager) { + super(templateManager); + this.properties = properties; + this.notifierId = id; + } + + @Override + public NotifyType getType() { + return DefaultNotifyType.dingTalk; + } + + @Override + public Provider getProvider() { + return DingTalkProvider.dingTalkMessage; + } + + @Override + public void send(DingTalkMessageTemplate template, Map context) { + CloseableHttpClient httpClient = HttpClientBuilder.create().build(); + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("access_token", getToken())); + + try { + HttpPost httpPost = new HttpPost(new URIBuilder(notifyApi).setParameters(params).build()); + String formInserter = template.createFormInserter(context); + StringEntity entity = new StringEntity(template.createFormInserter(context)); + httpPost.setEntity(entity); + CloseableHttpResponse response = httpClient.execute(httpPost); + JSONObject responseJson = JSON.parseObject(EntityUtils.toString(response.getEntity())); + System.out.println(responseJson); + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + } + } + + private void checkResult(String msg) { + if ("0".equals(msg)) { +// 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() { + CloseableHttpClient httpClient = HttpClientBuilder.create().build(); + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("appkey", properties.getAppKey())); + params.add(new BasicNameValuePair("appsecret", properties.getAppSecret())); + try { + HttpGet httpGet = new HttpGet(new URIBuilder(tokenApi).setParameters(params).build()); + CloseableHttpResponse response = httpClient.execute(httpGet); + JSONObject responseJson = JSON.parseObject(EntityUtils.toString(response.getEntity())); + if (responseJson.containsKey("access_token")) { + String access_token = responseJson.get("access_token").toString(); + refreshTokenTime = System.currentTimeMillis(); + accessToken.set(access_token); + return access_token; + } else { + // throw new BusinessException("获取Token失败:" + map.get("errmsg"), String.valueOf(map.get("errcode"))); + } + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void close() { + accessToken.set(null); + refreshTokenTime = 0; + } +} diff --git a/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifierProvider.java b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifierProvider.java new file mode 100644 index 0000000..f44f3f1 --- /dev/null +++ b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkNotifierProvider.java @@ -0,0 +1,65 @@ +package com.cicdi.notify.dingtalk; + +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.Objects; + + +public class DingTalkNotifierProvider implements NotifierProvider, TemplateProvider { + + private final TemplateManager templateManager; + + public DingTalkNotifierProvider(TemplateManager templateManager) { + this.templateManager = templateManager; + } + +// public static final DefaultConfigMetadata notifierConfig = new DefaultConfigMetadata("通知配置", "") +// .add("appKey", "appKey", "", new StringType().expand(ConfigMetadataConstants.required.value(true))) +// .add("appSecret", "appSecret", "", new StringType()); +// +// public static final DefaultConfigMetadata templateConfig = new DefaultConfigMetadata("模版配置", "") +// .add("agentId", "应用ID", "", new StringType().expand(ConfigMetadataConstants.required.value(true))) +// .add("userIdList", "收信人ID", "与部门ID不能同时为空", new StringType()) +// .add("departmentIdList", "收信部门ID", "与收信人ID不能同时为空", new StringType()) +// .add("toAllUser", "全部用户", "推送到全部用户", new BooleanType()) +// .add("message", "内容", "最大不超过500字", new StringType().expand(ConfigMetadataConstants.maxLength.value(500L))); + + @Override + public NotifyType getType() { + return DefaultNotifyType.dingTalk; + } + + @Override + public Provider getProvider() { + return DingTalkProvider.dingTalkMessage; + } + + @Override + public DingTalkMessageTemplate createTemplate(TemplateProperties properties) { +// return ValidatorUtils.tryValidate(JSON.parseObject(properties.getTemplate(), DingTalkMessageTemplate.class)); + return JSON.parseObject(properties.getTemplate(), DingTalkMessageTemplate.class); + } + + @Override + public DingTalkNotifier createNotifier(NotifierProperties properties) { + DingTalkProperties dingTalkProperties = new DingTalkProperties(); + dingTalkProperties.setAppKey((String) Objects.requireNonNull(properties.getConfiguration().get("appKey"), "appKey不能为空")); + dingTalkProperties.setAppSecret((String) Objects.requireNonNull(properties.getConfiguration().get("appSecret"), "appSecret不能为空")); + return new DingTalkNotifier(properties.getId(), dingTalkProperties, templateManager); +// return new DingTalkNotifier(properties.getId(), ValidatorUtils.tryValidate(dingTalkProperties), templateManager); + } + +// @Override +// public ConfigMetadata getNotifierConfigMetadata() { +// return notifierConfig; +// } +// +// @Override +// public ConfigMetadata getTemplateConfigMetadata() { +// return templateConfig; +// } +} diff --git a/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProperties.java b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProperties.java new file mode 100644 index 0000000..00d3990 --- /dev/null +++ b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProperties.java @@ -0,0 +1,29 @@ +package com.cicdi.notify.dingtalk; + +/** + * 钉钉通知属性 + * + * @author xueye + */ +public class DingTalkProperties { + + private String appKey; + + private String appSecret; + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } + + public String getAppSecret() { + return appSecret; + } + + public void setAppSecret(String appSecret) { + this.appSecret = appSecret; + } +} diff --git a/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProvider.java b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProvider.java new file mode 100644 index 0000000..d7017d0 --- /dev/null +++ b/notify-dingtalk/src/main/java/com/cicdi/notify/dingtalk/DingTalkProvider.java @@ -0,0 +1,30 @@ +package com.cicdi.notify.dingtalk; + +import com.cicdi.notify.Provider; + +/** + * 钉钉通知提供商 + * + * @author xueye + */ +public enum DingTalkProvider implements Provider { + + dingTalkMessage("钉钉消息通知"); + + private final String name; + + DingTalkProvider(String name) { + this.name = name; + } + + @Override + public String getId() { + return name(); + } + + @Override + public String getName() { + return name; + } + +} diff --git a/notify-dingtalk/src/test/java/com/cicdi/notify/dingtalk/DingTalkTest.java b/notify-dingtalk/src/test/java/com/cicdi/notify/dingtalk/DingTalkTest.java new file mode 100644 index 0000000..85c15d8 --- /dev/null +++ b/notify-dingtalk/src/test/java/com/cicdi/notify/dingtalk/DingTalkTest.java @@ -0,0 +1,67 @@ +package com.cicdi.notify.dingtalk; + +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 java.util.HashMap; +import java.util.Map; + +/** + * @author xueye + */ +public class DingTalkTest { + @Test + public void test() { + // 通知器配置管理器 + NotifyConfigManager notifyConfigManager = (notifyType, configId) -> { + NotifierProperties notifierProperties = new NotifierProperties(); + notifierProperties.setType(DefaultNotifyType.dingTalk.getId()); + notifierProperties.setProvider(DingTalkProvider.dingTalkMessage.getId()); + notifierProperties.setId("12"); + + Map config = new HashMap<>(); + config.put("appKey", "dinga5vkkpbrwqc0fmni"); + config.put("appSecret", "ARsEfA8CQ7RxJabEW1TecTeEItTamK3GQ8-TfWTHAydF7gQK16N23UuN9y2E9raq"); + + notifierProperties.setConfiguration(config); + + return notifierProperties; + }; + + // 模板管理器 + TemplateManager templateManager = new AbstractTemplateManager() { + @Override + protected TemplateProperties getProperties(NotifyType type, String id) { + TemplateProperties templateProperties = new TemplateProperties(); + templateProperties.setType(DefaultNotifyType.dingTalk.getId()); + templateProperties.setProvider(DingTalkProvider.dingTalkMessage.getId()); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("agentId", "1211676948"); + jsonObject.put("userIdList", "manager276"); + jsonObject.put("departmentIdList", ""); + jsonObject.put("toAllUser", "false"); + jsonObject.put("message", "Hello World!"); + + templateProperties.setTemplate(jsonObject.toJSONString()); + + return templateProperties; + } + }; + + NotifierManager notifierManager = new DefaultNotifierManager(notifyConfigManager); + + // register + DingTalkNotifierProvider provider = new DingTalkNotifierProvider(templateManager); + notifierManager.registerProvider(provider); + templateManager.register(provider); + + Notifier