Procházet zdrojové kódy

1. 阿里云 sms client 增加查询模板的封装
2. 重构阿里云 sms client 客户端,增加 invoke 基础方法

YunaiV před 4 roky
rodič
revize
bdbc5b2626

+ 9 - 0
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.sms.core.client;
 import cn.iocoder.dashboard.common.core.KeyValue;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 
 import java.util.List;
 
@@ -41,4 +42,12 @@ public interface SmsClient {
      */
     List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
 
+    /**
+     * 查询指定的短信模板
+     *
+     * @param apiTemplateId 短信 API 的模板编号
+     * @return 短信模板
+     */
+    SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId);
+
 }

+ 33 - 0
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.dashboard.framework.sms.core.client.dto;
+
+import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
+import lombok.Data;
+
+/**
+ * 短信模板 Response DTO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class SmsTemplateRespDTO {
+
+    /**
+     * 模板编号
+     */
+    private String id;
+    /**
+     * 短信内容
+     */
+    private String content;
+    /**
+     * 审核状态
+     *
+     * 枚举 {@link SmsTemplateAuditStatusEnum}
+     */
+    private Integer auditStatus;
+    /**
+     * 审核未通过的理由
+     */
+    private String auditReason;
+
+}

+ 19 - 1
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java

@@ -6,6 +6,7 @@ import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 import lombok.extern.slf4j.Slf4j;
 
@@ -77,7 +78,7 @@ public abstract class AbstractSmsClient implements SmsClient {
             result = doSendSms(logId, mobile, apiTemplateId, templateParams);
         } catch (Throwable ex) {
             // 打印异常日志
-            log.error("[send][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
+            log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
                     logId, mobile, apiTemplateId, templateParams, ex);
             // 封装返回
             return SmsCommonResult.error(ex);
@@ -101,4 +102,21 @@ public abstract class AbstractSmsClient implements SmsClient {
 
     protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;
 
+    @Override
+    public SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId) {
+        // 执行短信发送
+        SmsCommonResult<SmsTemplateRespDTO> result;
+        try {
+            result = doGetSmsTemplate(apiTemplateId);
+        } catch (Throwable ex) {
+            // 打印异常日志
+            log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex);
+            // 封装返回
+            return SmsCommonResult.error(ex);
+        }
+        return result;
+    }
+
+    protected abstract SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable;
+
 }

+ 52 - 16
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java

@@ -1,21 +1,25 @@
 package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
 
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.dashboard.common.core.KeyValue;
 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
+import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 import cn.iocoder.dashboard.util.collection.MapUtils;
 import cn.iocoder.dashboard.util.json.JsonUtils;
+import com.aliyuncs.AcsRequest;
+import com.aliyuncs.AcsResponse;
 import com.aliyuncs.DefaultAcsClient;
 import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
 import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
 import com.aliyuncs.exceptions.ClientException;
-import com.aliyuncs.http.MethodType;
 import com.aliyuncs.profile.DefaultProfile;
 import com.aliyuncs.profile.IClientProfile;
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -25,6 +29,8 @@ import lombok.extern.slf4j.Slf4j;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -66,25 +72,13 @@ public class AliyunSmsClient extends AbstractSmsClient {
                                                         String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
         // 构建参数
         SendSmsRequest request = new SendSmsRequest();
-        request.setSysMethod(MethodType.POST);
         request.setPhoneNumbers(mobile);
         request.setSignName(properties.getSignature());
         request.setTemplateCode(apiTemplateId);
         request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams)));
         request.setOutId(String.valueOf(sendLogId));
-
-        try {
-            // 执行发送
-            SendSmsResponse sendResult = acsClient.getAcsResponse(request);
-            // 解析结果
-            SmsSendRespDTO data = null;
-            if (sendResult.getBizId() != null) {
-                data = new SmsSendRespDTO().setSerialNo(sendResult.getBizId());
-            }
-            return SmsCommonResult.build(sendResult.getCode(), sendResult.getMessage(), sendResult.getRequestId(), data, codeMapping);
-        } catch (ClientException ex) {
-            return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
-        }
+        // 执行请求
+        return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId()));
     }
 
     private static String formatResultMsg(ClientException ex) {
@@ -107,6 +101,48 @@ public class AliyunSmsClient extends AbstractSmsClient {
         }).collect(Collectors.toList());
     }
 
+    @Override
+    protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) {
+        // 构建参数
+        QuerySmsTemplateRequest request = new QuerySmsTemplateRequest();
+        request.setTemplateCode(apiTemplateId);
+        // 执行请求
+        return invoke(request, response -> {
+            SmsTemplateRespDTO data = new SmsTemplateRespDTO();
+            data.setId(response.getTemplateCode()).setContent(response.getTemplateContent());
+            data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason());
+            return data;
+        });
+    }
+
+    private Integer convertSmsTemplateAuditStatus(Integer templateStatus) {
+        switch (templateStatus) {
+            case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
+            case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
+            case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
+            default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
+        }
+    }
+
+    private <T extends AcsResponse, R> SmsCommonResult<R> invoke(AcsRequest<T> request, Function<T, R> consumer) {
+        try {
+            // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射
+            T sendResult = acsClient.getAcsResponse(request);
+            String code = (String) ReflectUtil.getFieldValue(sendResult, "code");
+            String message = (String) ReflectUtil.getFieldValue(sendResult, "message");
+            String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId");
+            // 解析结果
+            R data = null;
+            if (Objects.equals(code, "OK")) { // 请求成功的情况下
+                data = consumer.apply(sendResult);
+            }
+            // 拼接结果
+            return SmsCommonResult.build(code, message, requestId, data, codeMapping);
+        } catch (ClientException ex) {
+            return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
+        }
+    }
+
     /**
      * 短信接收状态
      *

+ 1 - 0
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java

@@ -21,6 +21,7 @@ public class AliyunSmsCodeMapping implements SmsCodeMapping {
             case "isp.RAM_PERMISSION_DENY": return SMS_CHANNEL_PERMISSION_DENY;
             case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR;
             case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_LIMIT_CONTROL;
+            case "isv.SMS_TEMPLATE_ILLEGAL": return SMS_TEMPLATE_NOT_EXISTS;
         }
         return SMS_UNKNOWN;
     }

+ 6 - 0
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java

@@ -8,6 +8,7 @@ import cn.iocoder.dashboard.common.core.KeyValue;
 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
 import cn.iocoder.dashboard.util.json.JsonUtils;
@@ -114,6 +115,11 @@ public class YunpianSmsClient extends AbstractSmsClient {
         }).collect(Collectors.toList());
     }
 
+    @Override
+    protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable {
+        return null;
+    }
+
     /**
      * 短信接收状态
      *

+ 21 - 0
src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java

@@ -0,0 +1,21 @@
+package cn.iocoder.dashboard.framework.sms.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 短信模板的审核状态枚举
+ *
+ * @author 芋道源码
+ */
+@AllArgsConstructor
+@Getter
+public enum SmsTemplateAuditStatusEnum {
+
+    CHECKING(1),
+    SUCCESS(2),
+    FAIL(3);
+
+    private final Integer status;
+
+}

+ 20 - 5
src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java

@@ -3,8 +3,10 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
 import cn.iocoder.dashboard.common.core.KeyValue;
 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
 import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -15,8 +17,10 @@ import java.util.List;
  */
 public class AliyunSmsClientIntegrationTest {
 
-    @Test
-    public void testSend() {
+    private static AliyunSmsClient smsClient;
+
+    @BeforeAll
+    public static void before() {
         // 创建配置类
         SmsChannelProperties properties = new SmsChannelProperties();
         properties.setId(1L);
@@ -25,14 +29,25 @@ public class AliyunSmsClientIntegrationTest {
         properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY"));
         properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY"));
         // 创建客户端
-        AliyunSmsClient smsClient = new AliyunSmsClient(properties);
+        smsClient = new AliyunSmsClient(properties);
         smsClient.init();
-        // 发送短信
+    }
+
+    @Test
+    public void testSendSms() {
         List<KeyValue<String, Object>> templateParams = new ArrayList<>();
         templateParams.add(new KeyValue<>("code", "1024"));
 //        templateParams.put("operation", "嘿嘿");
 //        SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
-        SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "SMS_207945135", templateParams);
+        SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399",
+                "SMS_207945135", templateParams);
+        System.out.println(result);
+    }
+
+    @Test
+    public void testGetSmsTemplate() {
+        String apiTemplateId = "SMS_2079451351";
+        SmsCommonResult<SmsTemplateRespDTO> result = smsClient.getSmsTemplate(apiTemplateId);
         System.out.println(result);
     }