Showing
10 changed files
with
219 additions
and
11 deletions
1 | +package org.thingsboard.server.common.data.yunteng.config.enterpriseWeChat; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import org.thingsboard.server.common.data.yunteng.config.message.MessageProviderConfiguration; | |
5 | +import org.thingsboard.server.common.data.yunteng.enums.MessageProviderTypeEnum; | |
6 | + | |
7 | +@Data | |
8 | +public class EnterpriseWeChatConfiguration implements MessageProviderConfiguration { | |
9 | + | |
10 | + /** 企业id */ | |
11 | + private String corpId; | |
12 | + | |
13 | + /** 应用id */ | |
14 | + private Long agentId; | |
15 | + | |
16 | + /** 企业微信应用Secret */ | |
17 | + private String corpSecret; | |
18 | + | |
19 | + @Override | |
20 | + public MessageProviderTypeEnum getType() { | |
21 | + return MessageProviderTypeEnum.ENTERPRISE_WECHAT; | |
22 | + } | |
23 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.config.enterpriseWeChat; | |
2 | +import com.fasterxml.jackson.databind.JsonNode; | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.apache.commons.lang3.StringUtils; | |
5 | +import org.thingsboard.server.common.data.yunteng.config.message.AbstractMessageSender; | |
6 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
7 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
8 | +import org.thingsboard.server.common.data.yunteng.enums.ResponseCodeEnum; | |
9 | +import org.thingsboard.server.common.data.yunteng.utils.HttpClientUtils; | |
10 | +import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; | |
11 | +import java.util.ArrayList; | |
12 | +import java.util.Date; | |
13 | +import java.util.LinkedHashMap; | |
14 | +import java.util.List; | |
15 | + | |
16 | +@Slf4j | |
17 | +public class EnterpriseWeChatSmsSender extends AbstractMessageSender { | |
18 | + | |
19 | + /** 钉钉参数配置 */ | |
20 | + private final EnterpriseWeChatConfiguration config; | |
21 | + | |
22 | + private String accessToken; | |
23 | + | |
24 | + private String url = "https://qyapi.weixin.qq.com/cgi-bin"; | |
25 | + | |
26 | + private Long expirationTime; | |
27 | +// | |
28 | +// private static final String smsText="{\n" + | |
29 | +// " \"touser\": \"%s\",\n" + | |
30 | +// " \"msgtype\": \"textcard\",\n" + | |
31 | +// " \"agentid\": %s,\n" + | |
32 | +// " \"textcard\": {\n" + | |
33 | +// "\"title\": \"平台告警通知\",\n" + | |
34 | +// "\"description\": \"<div class=\\\"normal\\\">设备所属组织:%s</div>" + | |
35 | +// "<div class=\\\"normal\\\">设备名称:%s</div>" + | |
36 | +// "<div class=\\\"normal\\\">告警等级:%s</div>" + | |
37 | +// "<div class=\\\"normal\\\">告警类型:%s</div>" + | |
38 | +// "<div class=\\\"normal\\\">触发值:%s</div>" + | |
39 | +// "<div class=\\\"normal\\\">告警时间:%s</div>\",\n" + | |
40 | +// " \"url\": \" \",\n" + | |
41 | +// " \"btntxt\": \"详情\"\n" + | |
42 | +// " },\n" + | |
43 | +// " \"enable_id_trans\": 0,\n" + | |
44 | +// " \"enable_duplicate_check\": 0,\n" + | |
45 | +// " \"duplicate_check_interval\": 1800\n" + | |
46 | +// "}"; | |
47 | + | |
48 | + private static final String smsText="{\n" + | |
49 | + " \"touser\" : \"%s\",\n" + | |
50 | + " \"msgtype\" : \"text\",\n" + | |
51 | + " \"agentid\" : %s,\n" + | |
52 | + " \"text\" : {\n" + | |
53 | + " \"content\" : \"平台告警通知\n设备所属组织:%s\n设备名称:%s\n告警等级:%s\n告警类型:%s\n触发值:%s\n告警时间:%s\n\"\n" + | |
54 | + " },\n" + | |
55 | + " \"safe\":0,\n" + | |
56 | + " \"enable_id_trans\": 0,\n" + | |
57 | + " \"enable_duplicate_check\": 0,\n" + | |
58 | + " \"duplicate_check_interval\": 1800\n" + | |
59 | + "}"; | |
60 | + | |
61 | + | |
62 | + | |
63 | + public EnterpriseWeChatSmsSender(EnterpriseWeChatConfiguration config) { | |
64 | + if (StringUtils.isEmpty(config.getCorpId()) | |
65 | + || StringUtils.isEmpty(config.getCorpSecret())) { | |
66 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
67 | + } | |
68 | + this.config = config; | |
69 | + getAccessToken(); | |
70 | + } | |
71 | + | |
72 | + /** 初始化token */ | |
73 | + private void getAccessToken() { | |
74 | + if(expirationTime!=null){ | |
75 | + Date now = new Date(); | |
76 | + if(now.getTime()>expirationTime){ | |
77 | + getAccessTokenByUrl(); | |
78 | + } | |
79 | + }else{ | |
80 | + getAccessTokenByUrl(); | |
81 | + } | |
82 | + } | |
83 | + private void getAccessTokenByUrl() { | |
84 | + try { | |
85 | + String response = HttpClientUtils.sendGet(url+"/gettoken?"+"corpid="+config.getCorpId()+"&corpsecret="+config.getCorpSecret()); | |
86 | + JsonNode jsonNode = JacksonUtil.toJsonNode(response); | |
87 | + this.accessToken = jsonNode.path("access_token").asText(); | |
88 | + this.expirationTime = new Date().getTime()+5400*1000; | |
89 | + } catch (Exception e) { | |
90 | + e.printStackTrace(); | |
91 | + throw new TkDataValidationException(ErrorMessage.OPERATION_FAILED.getMessage()); | |
92 | + } | |
93 | + } | |
94 | + | |
95 | + | |
96 | + private String getUserId(String phone) { | |
97 | + List<String> numbers = new ArrayList<>(); | |
98 | + String [] phones = phone.split(","); | |
99 | + for(String onePhone: phones){ | |
100 | + try { | |
101 | + String payload ="{\"mobile\":\""+onePhone+"\"}"; | |
102 | + String response = HttpClientUtils.sendPOST(url+"/user/getuserid?access_token="+accessToken,payload); | |
103 | + JsonNode jsonNode = JacksonUtil.toJsonNode(response); | |
104 | + if(jsonNode.path("userid").asText().isEmpty()){ | |
105 | + continue; | |
106 | + } | |
107 | + numbers.add(jsonNode.path("userid").asText()); | |
108 | + } catch (Exception e) { | |
109 | + e.printStackTrace(); | |
110 | + } | |
111 | + } | |
112 | + return String.join("|",numbers); | |
113 | + } | |
114 | + | |
115 | + @Override | |
116 | + public String sendSms( | |
117 | + String phone, String templateCode, LinkedHashMap<String, Object> param, String signName) { | |
118 | + try{ | |
119 | + getAccessToken(); | |
120 | + String payload = String.format(smsText,getUserId(phone),config.getAgentId(),param.get("organization"),param.get("deviceName"), | |
121 | + param.get("severity"),param.get("type"),param.get("triggerValue"),param.get("createTime")); | |
122 | + String response = HttpClientUtils.sendPOST( | |
123 | + url +"/message/send?"+"access_token="+accessToken,payload); | |
124 | + JsonNode jsonNode = JacksonUtil.toJsonNode(response); | |
125 | + return jsonNode.path("error-msg").asText().equalsIgnoreCase(ResponseCodeEnum.OK.name()) | |
126 | + ? ResponseCodeEnum.SUCCESS.name() | |
127 | + : jsonNode.path("error-msg").asText(); | |
128 | + } catch (Exception e) { | |
129 | + e.printStackTrace(); | |
130 | + return e.getMessage(); | |
131 | + } | |
132 | + } | |
133 | +} | ... | ... |
... | ... | @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; |
3 | 3 | import com.fasterxml.jackson.annotation.JsonSubTypes; |
4 | 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo; |
5 | 5 | import org.thingsboard.server.common.data.yunteng.config.dingtalk.DingTalkSmsProviderConfiguration; |
6 | +import org.thingsboard.server.common.data.yunteng.config.enterpriseWeChat.EnterpriseWeChatConfiguration; | |
6 | 7 | import org.thingsboard.server.common.data.yunteng.config.message.ali.AliSmsProviderConfiguration; |
7 | 8 | import org.thingsboard.server.common.data.yunteng.config.message.tencent.TencentSmsProviderConfiguration; |
8 | 9 | import org.thingsboard.server.common.data.yunteng.config.voice.AliVoiceSmsProviderConfiguration; |
... | ... | @@ -13,7 +14,8 @@ import org.thingsboard.server.common.data.yunteng.enums.MessageProviderTypeEnum; |
13 | 14 | @JsonSubTypes.Type(value = AliSmsProviderConfiguration.class, name = "ALI_CLOUD"), |
14 | 15 | @JsonSubTypes.Type(value = TencentSmsProviderConfiguration.class, name = "TENCENT_CLOUD"), |
15 | 16 | @JsonSubTypes.Type(value = DingTalkSmsProviderConfiguration.class, name = "DING_TALK"), |
16 | - @JsonSubTypes.Type(value = AliVoiceSmsProviderConfiguration.class, name = "ALI_VOICE") | |
17 | + @JsonSubTypes.Type(value = AliVoiceSmsProviderConfiguration.class, name = "ALI_VOICE"), | |
18 | + @JsonSubTypes.Type(value = EnterpriseWeChatConfiguration.class, name = "ENTERPRISE_WECHAT") | |
17 | 19 | }) |
18 | 20 | public interface MessageProviderConfiguration { |
19 | 21 | ... | ... |
... | ... | @@ -3,6 +3,8 @@ package org.thingsboard.server.common.data.yunteng.config.message; |
3 | 3 | import org.springframework.stereotype.Component; |
4 | 4 | import org.thingsboard.server.common.data.yunteng.config.dingtalk.DingTalkSmsProviderConfiguration; |
5 | 5 | import org.thingsboard.server.common.data.yunteng.config.dingtalk.DingTalkSmsSender; |
6 | +import org.thingsboard.server.common.data.yunteng.config.enterpriseWeChat.EnterpriseWeChatConfiguration; | |
7 | +import org.thingsboard.server.common.data.yunteng.config.enterpriseWeChat.EnterpriseWeChatSmsSender; | |
6 | 8 | import org.thingsboard.server.common.data.yunteng.config.message.ali.AliSmsProviderConfiguration; |
7 | 9 | import org.thingsboard.server.common.data.yunteng.config.message.ali.AliSmsSender; |
8 | 10 | import org.thingsboard.server.common.data.yunteng.config.message.tencent.TencentSmsProviderConfiguration; |
... | ... | @@ -42,6 +44,11 @@ public class TkDefaultMessageSenderFactory implements MessageSenderFactory { |
42 | 44 | (DingTalkSmsProviderConfiguration) config); |
43 | 45 | smsSenderMap.put(key,dingTalkSmsSender); |
44 | 46 | return dingTalkSmsSender; |
47 | + case ENTERPRISE_WECHAT: | |
48 | + EnterpriseWeChatSmsSender enterpriseWeChatSmsSender = new EnterpriseWeChatSmsSender( | |
49 | + (EnterpriseWeChatConfiguration) config); | |
50 | + smsSenderMap.put(key,enterpriseWeChatSmsSender); | |
51 | + return enterpriseWeChatSmsSender; | |
45 | 52 | case ALI_VOICE: |
46 | 53 | return new AliVoiceSmsSender( |
47 | 54 | (AliVoiceSmsProviderConfiguration) config); | ... | ... |
... | ... | @@ -48,14 +48,5 @@ public class HttpClientUtils { |
48 | 48 | |
49 | 49 | } |
50 | 50 | |
51 | - public static void main(String[] args) throws IOException { | |
52 | -// String url = "https://open.ys7.com/api/lapp/token/get?appKey=0cf3f1753e6941e3b5dfe3c00162924e&appSecret=cbe2f41bebee529fde568143109a9903"; | |
53 | -// String param = "{\"appKey\":\"0cf3f1753e6941e3b5dfe3c00162924e\",\"appSecret\":\"cbe2f41bebee529fde568143109a9903\"}"; | |
54 | -// String response = sendPOST(url,param);System.out.println(response); | |
55 | - String url2 = "https://open.ys7.com/api/lapp/v2/live/address/get?accessToken=at.cm82uxq261a7ji0xcf32z4su2f5vc066-2krkymy3is-1of7jb5-v1jamwzxw" + | |
56 | - "&deviceSerial=E53165567&protocol=4"; | |
57 | - String response = sendPOST(url2,""); | |
58 | - System.out.println(response); | |
59 | - } | |
60 | 51 | |
61 | 52 | } | ... | ... |
... | ... | @@ -102,6 +102,12 @@ public class TkMessageServiceImpl implements TkMessageService { |
102 | 102 | || null == configJsonNode.get("clientSecret"))) { |
103 | 103 | isMatch = false; |
104 | 104 | } |
105 | + else if (platForm.equals(MessageProviderTypeEnum.ENTERPRISE_WECHAT.name()) | |
106 | + && (null == configJsonNode.get("corpId") | |
107 | + || null == configJsonNode.get("agentId") | |
108 | + || null == configJsonNode.get("corpSecret"))) { | |
109 | + isMatch = false; | |
110 | + } | |
105 | 111 | else if (platForm.equals(MessageProviderTypeEnum.ALI_VOICE.name()) |
106 | 112 | && (null == configJsonNode.get("accessKeyId") |
107 | 113 | || null == configJsonNode.get("accessKeySecret"))) { |
... | ... | @@ -117,6 +123,12 @@ public class TkMessageServiceImpl implements TkMessageService { |
117 | 123 | keyList.add(configJsonNode.get("clientSecret").toString()); |
118 | 124 | keyList.add(messageConfig.getTenantId()); |
119 | 125 | } |
126 | + else if(isMatch&&platForm.equals(MessageProviderTypeEnum.ENTERPRISE_WECHAT.name())){ | |
127 | + keyList.add(configJsonNode.get("corpId").toString()); | |
128 | + keyList.add(configJsonNode.get("agentId").toString()); | |
129 | + keyList.add(configJsonNode.get("corpSecret").toString()); | |
130 | + keyList.add(messageConfig.getTenantId()); | |
131 | + } | |
120 | 132 | MessageProviderConfiguration smsProviderConfiguration = |
121 | 133 | JacksonUtil.convertValue(configObjectNode, MessageProviderConfiguration.class); |
122 | 134 | if (null != smsProviderConfiguration) { | ... | ... |
... | ... | @@ -153,6 +153,14 @@ public class TkNoticeServiceImpl implements TkNoticeService { |
153 | 153 | organization, |
154 | 154 | contacts); |
155 | 155 | } |
156 | + if (messageCode.contains(MessageTypeEnum.ENTERPRISE_WECHAT_MESSAGE.name()) | |
157 | + && templatesMap.containsKey(MessageTypeEnum.ENTERPRISE_WECHAT_MESSAGE.name())) { | |
158 | + enterpriseWeChat4Alarm( | |
159 | + alarmInfo, | |
160 | + templatesMap.get(MessageTypeEnum.ENTERPRISE_WECHAT_MESSAGE.name()), | |
161 | + organization, | |
162 | + contacts); | |
163 | + } | |
156 | 164 | if (messageCode.contains(MessageTypeEnum.VOICE_MESSAGE.name()) |
157 | 165 | && templatesMap.containsKey(MessageTypeEnum.VOICE_MESSAGE.name())) { |
158 | 166 | aLiVoice4Alarm( |
... | ... | @@ -268,6 +276,37 @@ public class TkNoticeServiceImpl implements TkNoticeService { |
268 | 276 | smsService.sendSms(info); |
269 | 277 | } |
270 | 278 | |
279 | + /** | |
280 | + * 企业微信通知设备告警信息 | |
281 | + * | |
282 | + * @param alarmInfo 告警信息 | |
283 | + * @param templateId 告警模板主键 | |
284 | + * @param organization 设备所属组织 | |
285 | + */ | |
286 | + private void enterpriseWeChat4Alarm( | |
287 | + AlarmInfoDTO alarmInfo, | |
288 | + String templateId, | |
289 | + TkOrganizationEntity organization, | |
290 | + List<TkAlarmContactEntity> contacts) { | |
291 | + // TODO 推送企业微信通知 | |
292 | + SmsReqDTO info = new SmsReqDTO(); | |
293 | + info.setId(templateId); | |
294 | + info.setParams(setAliAlarmParams(alarmInfo, organization)); | |
295 | + info.setTemplatePurpose(MsgTemplatePurposeEnum.FOR_ALARM_NOTICE.name()); | |
296 | + List<String> phones = new ArrayList<>(); | |
297 | + contacts.stream() | |
298 | + .parallel() | |
299 | + .forEach( | |
300 | + item -> { | |
301 | + if (StringUtils.isEmpty(item.getWechat())&&StringUtils.isEmpty(item.getPhone())) { | |
302 | + return; | |
303 | + } | |
304 | + phones.add(item.getWechat()==null?item.getPhone():item.getWechat()); | |
305 | + }); | |
306 | + String phone = String.join(",",phones); | |
307 | + info.setPhoneNumbers(phone); | |
308 | + smsService.sendSms(info); | |
309 | + } | |
271 | 310 | /** |
272 | 311 | * 微信通知设备告警信息 |
273 | 312 | * | ... | ... |