Forráskód Böngészése

优化短信通知,增加阿里云短信通知

zhou-hao 5 éve
szülő
commit
011f56a7ce

+ 6 - 0
jetlinks-components/notify-component/notify-sms/pom.xml

@@ -17,6 +17,12 @@
             <artifactId>hsweb-easy-orm-rdb</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+
         <dependency>
             <groupId>org.hswebframework.web</groupId>
             <artifactId>hsweb-starter</artifactId>

+ 1 - 1
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/provider/PlainTextSmsTemplate.java

@@ -1,4 +1,4 @@
-package org.jetlinks.community.notify.sms.provider;
+package org.jetlinks.community.notify.sms;
 
 import lombok.Getter;
 import lombok.Setter;

+ 20 - 0
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/SmsProvider.java

@@ -0,0 +1,20 @@
+package org.jetlinks.community.notify.sms;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.jetlinks.community.notify.Provider;
+
+@Getter
+@AllArgsConstructor
+public enum SmsProvider implements Provider {
+
+    aliyunSms("阿里云短信服务")
+    ;
+    private final String name;
+
+    @Override
+    public String getId() {
+        return name();
+    }
+
+}

+ 4 - 4
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/provider/TestSmsProvider.java

@@ -1,10 +1,10 @@
-package org.jetlinks.community.notify.sms.provider;
+package org.jetlinks.community.notify.sms;
 
 import com.alibaba.fastjson.JSON;
 import lombok.extern.slf4j.Slf4j;
+import org.jetlinks.community.notify.*;
 import org.jetlinks.core.Values;
 import org.jetlinks.core.metadata.ConfigMetadata;
-import org.jetlinks.community.notify.*;
 import org.jetlinks.community.notify.template.Template;
 import org.jetlinks.community.notify.template.TemplateManager;
 import org.jetlinks.community.notify.template.TemplateProperties;
@@ -54,7 +54,7 @@ public class TestSmsProvider extends AbstractNotifier<PlainTextSmsTemplate> impl
     @Nonnull
     @Override
     public Mono<Void> send(@Nonnull PlainTextSmsTemplate template, @Nonnull Values context) {
-        return Mono.fromRunnable(() -> log.info("send sms [{}] message:{}", template.getSendTo(context.getAllValues()), template.getTextSms(context.getAllValues())));
+        return Mono.fromRunnable(() -> log.info("send sms {} message:{}", template.getSendTo(context.getAllValues()), template.getTextSms(context.getAllValues())));
     }
 
     @Nonnull
@@ -71,7 +71,7 @@ public class TestSmsProvider extends AbstractNotifier<PlainTextSmsTemplate> impl
 
     @Override
     public String getNotifierId() {
-        return "test-sms-notify";
+        return "test-sms-sender";
     }
 
     @Override

+ 115 - 0
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsNotifier.java

@@ -0,0 +1,115 @@
+package org.jetlinks.community.notify.sms.aliyun;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyuncs.CommonRequest;
+import com.aliyuncs.CommonResponse;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.exception.BusinessException;
+import org.hswebframework.web.logger.ReactiveLogger;
+import org.jetlinks.community.notify.*;
+import org.jetlinks.community.notify.sms.SmsProvider;
+import org.jetlinks.core.Values;
+import org.jetlinks.community.notify.template.TemplateManager;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
+
+import javax.annotation.Nonnull;
+import java.util.Map;
+import java.util.Objects;
+
+@Slf4j
+public class AliyunSmsNotifier extends AbstractNotifier<AliyunSmsTemplate> {
+
+    private final IAcsClient client;
+    private final int connectTimeout = 1000;
+    private final int readTimeout = 5000;
+
+    @Getter
+    private String notifierId;
+
+    private String domain = "dysmsapi.aliyuncs.com";
+    private String regionId = "cn-hangzhou";
+
+    public AliyunSmsNotifier(NotifierProperties profile, TemplateManager templateManager) {
+        super(templateManager);
+        Map<String, Object> config = profile.getConfiguration();
+        DefaultProfile defaultProfile = DefaultProfile.getProfile(
+            this.regionId = (String) Objects.requireNonNull(config.get("regionId"), "regionId不能为空"),
+            (String) Objects.requireNonNull(config.get("accessKeyId"), "accessKeyId不能为空"),
+            (String) Objects.requireNonNull(config.get("secret"), "secret不能为空")
+        );
+        this.client = new DefaultAcsClient(defaultProfile);
+        this.domain = (String) config.getOrDefault("domain", domain);
+        this.notifierId = profile.getId();
+    }
+
+    public AliyunSmsNotifier(IClientProfile profile, TemplateManager templateManager) {
+        this(new DefaultAcsClient(profile), templateManager);
+    }
+
+    public AliyunSmsNotifier(IAcsClient client, TemplateManager templateManager) {
+        super(templateManager);
+        this.client = client;
+    }
+
+    @Override
+    @Nonnull
+    public NotifyType getType() {
+        return DefaultNotifyType.sms;
+    }
+
+    @Nonnull
+    @Override
+    public Provider getProvider() {
+        return SmsProvider.aliyunSms;
+    }
+
+    @Override
+    @Nonnull
+    public Mono<Void> send(@Nonnull AliyunSmsTemplate template, @Nonnull Values context) {
+
+        return Mono.<Void>defer(() -> {
+            try {
+                CommonRequest request = new CommonRequest();
+                request.setSysMethod(MethodType.POST);
+                request.setSysDomain(domain);
+                request.setSysVersion("2017-05-25");
+                request.setSysAction("SendSms");
+                request.setSysConnectTimeout(connectTimeout);
+                request.setSysReadTimeout(readTimeout);
+                request.putQueryParameter("RegionId", regionId);
+                request.putQueryParameter("PhoneNumbers", template.getPhoneNumber());
+                request.putQueryParameter("SignName", template.getSignName());
+                request.putQueryParameter("TemplateCode", template.getCode());
+                request.putQueryParameter("TemplateParam", template.createTtsParam(context.getAllValues()));
+
+                CommonResponse response = client.getCommonResponse(request);
+
+                log.info("发送短信通知完成 {}:{}", response.getHttpResponse().getStatus(), response.getData());
+
+                JSONObject json = JSON.parseObject(response.getData());
+                if (!"ok".equalsIgnoreCase(json.getString("Code"))) {
+                    return Mono.error(new BusinessException(json.getString("Message"), json.getString("Code")));
+                }
+            } catch (Exception e) {
+                return Mono.error(e);
+            }
+            return Mono.empty();
+        }).doOnEach(ReactiveLogger.onError(err -> {
+            log.info("发送短信通知失败", err);
+        })).subscribeOn(Schedulers.elastic());
+    }
+
+    @Override
+    @Nonnull
+    public Mono<Void> close() {
+        return Mono.fromRunnable(client::shutdown);
+    }
+}

+ 78 - 0
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsNotifierProvider.java

@@ -0,0 +1,78 @@
+package org.jetlinks.community.notify.sms.aliyun;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.validator.ValidatorUtils;
+import org.jetlinks.community.notify.*;
+import org.jetlinks.community.notify.sms.SmsProvider;
+import org.jetlinks.core.metadata.ConfigMetadata;
+import org.jetlinks.core.metadata.DefaultConfigMetadata;
+import org.jetlinks.core.metadata.types.StringType;
+import org.jetlinks.community.notify.template.TemplateManager;
+import org.jetlinks.community.notify.template.TemplateProperties;
+import org.jetlinks.community.notify.template.TemplateProvider;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.Nonnull;
+
+/**
+ * 阿里云短信通知服务
+ * </a>
+ *
+ * @author zhouhao
+ * @since 1.3
+ */
+@Component
+@Slf4j
+@AllArgsConstructor
+public class AliyunSmsNotifierProvider implements NotifierProvider, TemplateProvider {
+
+    private final TemplateManager templateManager;
+
+    @Nonnull
+    @Override
+    public Provider getProvider() {
+        return SmsProvider.aliyunSms;
+    }
+
+    public static final DefaultConfigMetadata templateConfig = new DefaultConfigMetadata("阿里云短信模版",
+        "https://help.aliyun.com/document_detail/108086.html")
+            .add("signName", "签名", "", new StringType())
+            .add("code", "模版编码", "", new StringType())
+            .add("phoneNumber", "收信人", "", new StringType());
+
+    public static final DefaultConfigMetadata notifierConfig = new DefaultConfigMetadata("阿里云API配置"
+        ,"https://help.aliyun.com/document_detail/101300.html")
+            .add("regionId", "regionId", "regionId", new StringType())
+            .add("accessKeyId", "accessKeyId", "", new StringType())
+            .add("secret", "secret", "", new StringType());
+
+    @Override
+    public ConfigMetadata getTemplateConfigMetadata() {
+        return templateConfig;
+    }
+
+    @Override
+    public ConfigMetadata getNotifierConfigMetadata() {
+        return notifierConfig;
+    }
+
+    @Override
+    public Mono<AliyunSmsTemplate> createTemplate(TemplateProperties properties) {
+        return Mono.fromCallable(() -> ValidatorUtils.tryValidate(JSON.parseObject(properties.getTemplate(), AliyunSmsTemplate.class)));
+    }
+
+    @Nonnull
+    @Override
+    public NotifyType getType() {
+        return DefaultNotifyType.sms;
+    }
+
+    @Nonnull
+    @Override
+    public Mono<AliyunSmsNotifier> createNotifier(@Nonnull NotifierProperties properties) {
+        return Mono.fromSupplier(() -> new AliyunSmsNotifier(properties, templateManager));
+    }
+}

+ 37 - 0
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/aliyun/AliyunSmsTemplate.java

@@ -0,0 +1,37 @@
+package org.jetlinks.community.notify.sms.aliyun;
+
+import com.alibaba.fastjson.JSON;
+import lombok.Getter;
+import lombok.Setter;
+import org.jetlinks.community.notify.template.Template;
+
+import javax.validation.constraints.NotBlank;
+import java.util.Map;
+
+/**
+ * 阿里云短信模版
+ *
+ * @since 1.3
+ */
+@Getter
+@Setter
+public class AliyunSmsTemplate implements Template {
+
+    //签名名称
+    @NotBlank(message = "[signName]不能为空")
+    private String signName;
+
+    //模版编码
+    @NotBlank(message = "[code]不能为空")
+    private String code;
+
+    @NotBlank(message = "[phoneNumber]不能为空")
+    private String phoneNumber;
+
+    private Map<String, String> param;
+
+    public String createTtsParam(Map<String, Object> ctx) {
+
+        return JSON.toJSONString(ctx);
+    }
+}

+ 0 - 172
jetlinks-components/notify-component/notify-sms/src/main/java/org/jetlinks/community/notify/sms/provider/Hy2046SmsSenderProvider.java

@@ -1,172 +0,0 @@
-package org.jetlinks.community.notify.sms.provider;
-
-import com.alibaba.fastjson.JSON;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.jetlinks.core.Values;
-import org.jetlinks.core.metadata.ConfigMetadata;
-import org.jetlinks.core.metadata.DefaultConfigMetadata;
-import org.jetlinks.core.metadata.types.PasswordType;
-import org.jetlinks.core.metadata.types.StringType;
-import org.jetlinks.community.notify.*;
-import org.jetlinks.community.notify.template.Template;
-import org.jetlinks.community.notify.template.TemplateManager;
-import org.jetlinks.community.notify.template.TemplateProperties;
-import org.jetlinks.community.notify.template.TemplateProvider;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Component;
-import org.springframework.util.Assert;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Mono;
-
-import javax.annotation.Nonnull;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.Map;
-
-@Component
-@Slf4j
-@Profile({"dev","test"})
-public class Hy2046SmsSenderProvider implements NotifierProvider, TemplateProvider, Provider {
-
-
-    private WebClient webClient = WebClient.builder()
-            .baseUrl("http://sms10692.com/v2sms.aspx")
-            .build();
-
-    @Autowired
-    private TemplateManager templateManager;
-
-    @Nonnull
-    @Override
-    public NotifyType getType() {
-        return DefaultNotifyType.sms;
-    }
-
-    @Nonnull
-    @Override
-    public Provider getProvider() {
-        return this;
-    }
-
-    static DefaultConfigMetadata notifierConfig = new DefaultConfigMetadata("宏衍2046短信配置", "")
-            .add("userId", "userId", "用户ID", new StringType())
-            .add("username", "用户名", "用户名", new StringType())
-            .add("password", "密码", "密码", new PasswordType());
-
-    @Override
-    public ConfigMetadata getNotifierConfigMetadata() {
-        return notifierConfig;
-    }
-
-    @Override
-    public ConfigMetadata getTemplateConfigMetadata() {
-        return PlainTextSmsTemplate.templateConfig;
-    }
-
-    @Override
-    public Mono<? extends Template> createTemplate(TemplateProperties properties) {
-        return Mono.fromSupplier(() -> JSON.parseObject(properties.getTemplate(), PlainTextSmsTemplate.class));
-    }
-
-    @Nonnull
-    @Override
-    public Mono<Hy2046SmsSender> createNotifier(@Nonnull NotifierProperties properties) {
-        return Mono.defer(() -> {
-            String userId = (String) properties.getConfigOrNull("userId");
-            String username = (String) properties.getConfigOrNull("username");
-            String password = (String) properties.getConfigOrNull("password");
-            Assert.hasText(userId, "短信配置错误,缺少userId");
-            Assert.hasText(username, "短信配置错误,缺少username");
-            Assert.hasText(password, "短信配置错误,缺少password");
-            return Mono.just(new Hy2046SmsSender(properties.getId(),userId, username, password));
-        });
-    }
-
-    @Override
-    public String getId() {
-        return "hy2046";
-    }
-
-    @Override
-    public String getName() {
-        return "宏衍2046";
-    }
-
-    class Hy2046SmsSender extends AbstractNotifier<PlainTextSmsTemplate> {
-
-        String userId;
-        String username;
-        String password;
-        @Getter
-        private final String notifierId;
-
-        public Hy2046SmsSender(String id,String userId, String username, String password) {
-            super(templateManager);
-            this.userId = userId;
-            this.notifierId = id;
-            this.username = username;
-            this.password = password;
-        }
-
-        @Nonnull
-        @Override
-        public NotifyType getType() {
-            return DefaultNotifyType.sms;
-        }
-
-        @Nonnull
-        @Override
-        public Provider getProvider() {
-            return Hy2046SmsSenderProvider.this;
-        }
-
-        @Nonnull
-        @Override
-        public Mono<Void> close() {
-            return Mono.empty();
-        }
-
-
-        @Nonnull
-        @Override
-        public Mono<Void> send(@Nonnull PlainTextSmsTemplate template, @Nonnull Values context) {
-            return Mono.defer(() -> {
-                String ts = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
-                String sign = DigestUtils.md5Hex(username.concat(password).concat(ts));
-                String[] sendTo = template.getSendTo(context.getAllValues());
-
-                String mobile = String.join(",", sendTo);
-                MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
-                formData.add("userid", userId);
-                formData.add("timestamp", ts);
-                formData.add("sign", sign);
-                formData.add("mobile", mobile);
-                formData.add("content", template.getTextSms(context.getAllValues()));
-                formData.add("action", "send");
-                formData.add("rt", "json");
-
-                return webClient.post()
-                        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
-                        .body(BodyInserters.fromFormData(formData))
-                        .retrieve()
-                        .bodyToMono(Map.class)
-                        .map(map -> {
-                            if (Integer.valueOf(sendTo.length).equals(map.get("SuccessCounts"))) {
-                                return true;
-                            }
-                            throw new RuntimeException("发送短信失败:" + map.get("Message"));
-                        });
-
-            }).then();
-        }
-
-    }
-}
-