Commit bdbc5b2626823c8715e310f09fd9b3bfd9751b05

Authored by YunaiV
1 parent e52f0b7d

1. 阿里云 sms client 增加查询模板的封装

2. 重构阿里云 sms client 客户端,增加 invoke 基础方法
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java
@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.sms.core.client; @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.sms.core.client;
3 import cn.iocoder.dashboard.common.core.KeyValue; 3 import cn.iocoder.dashboard.common.core.KeyValue;
4 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; 4 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
5 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 5 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
  6 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
6 7
7 import java.util.List; 8 import java.util.List;
8 9
@@ -41,4 +42,12 @@ public interface SmsClient { @@ -41,4 +42,12 @@ public interface SmsClient {
41 */ 42 */
42 List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable; 43 List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
43 44
  45 + /**
  46 + * 查询指定的短信模板
  47 + *
  48 + * @param apiTemplateId 短信 API 的模板编号
  49 + * @return 短信模板
  50 + */
  51 + SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId);
  52 +
44 } 53 }
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.sms.core.client.dto;
  2 +
  3 +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * 短信模板 Response DTO
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Data
  12 +public class SmsTemplateRespDTO {
  13 +
  14 + /**
  15 + * 模板编号
  16 + */
  17 + private String id;
  18 + /**
  19 + * 短信内容
  20 + */
  21 + private String content;
  22 + /**
  23 + * 审核状态
  24 + *
  25 + * 枚举 {@link SmsTemplateAuditStatusEnum}
  26 + */
  27 + private Integer auditStatus;
  28 + /**
  29 + * 审核未通过的理由
  30 + */
  31 + private String auditReason;
  32 +
  33 +}
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; @@ -6,6 +6,7 @@ import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
6 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; 6 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
7 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; 7 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
8 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 8 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
  9 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
9 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; 10 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
10 import lombok.extern.slf4j.Slf4j; 11 import lombok.extern.slf4j.Slf4j;
11 12
@@ -77,7 +78,7 @@ public abstract class AbstractSmsClient implements SmsClient { @@ -77,7 +78,7 @@ public abstract class AbstractSmsClient implements SmsClient {
77 result = doSendSms(logId, mobile, apiTemplateId, templateParams); 78 result = doSendSms(logId, mobile, apiTemplateId, templateParams);
78 } catch (Throwable ex) { 79 } catch (Throwable ex) {
79 // 打印异常日志 80 // 打印异常日志
80 - log.error("[send][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]", 81 + log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
81 logId, mobile, apiTemplateId, templateParams, ex); 82 logId, mobile, apiTemplateId, templateParams, ex);
82 // 封装返回 83 // 封装返回
83 return SmsCommonResult.error(ex); 84 return SmsCommonResult.error(ex);
@@ -101,4 +102,21 @@ public abstract class AbstractSmsClient implements SmsClient { @@ -101,4 +102,21 @@ public abstract class AbstractSmsClient implements SmsClient {
101 102
102 protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable; 103 protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;
103 104
  105 + @Override
  106 + public SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId) {
  107 + // 执行短信发送
  108 + SmsCommonResult<SmsTemplateRespDTO> result;
  109 + try {
  110 + result = doGetSmsTemplate(apiTemplateId);
  111 + } catch (Throwable ex) {
  112 + // 打印异常日志
  113 + log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex);
  114 + // 封装返回
  115 + return SmsCommonResult.error(ex);
  116 + }
  117 + return result;
  118 + }
  119 +
  120 + protected abstract SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable;
  121 +
104 } 122 }
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java
1 package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; 1 package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.ReflectUtil;
4 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.dashboard.common.core.KeyValue; 6 import cn.iocoder.dashboard.common.core.KeyValue;
6 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; 7 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
7 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; 8 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
8 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 9 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
  10 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
9 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; 11 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
  12 +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
10 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; 13 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
11 import cn.iocoder.dashboard.util.collection.MapUtils; 14 import cn.iocoder.dashboard.util.collection.MapUtils;
12 import cn.iocoder.dashboard.util.json.JsonUtils; 15 import cn.iocoder.dashboard.util.json.JsonUtils;
  16 +import com.aliyuncs.AcsRequest;
  17 +import com.aliyuncs.AcsResponse;
13 import com.aliyuncs.DefaultAcsClient; 18 import com.aliyuncs.DefaultAcsClient;
14 import com.aliyuncs.IAcsClient; 19 import com.aliyuncs.IAcsClient;
  20 +import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
15 import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; 21 import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
16 -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;  
17 import com.aliyuncs.exceptions.ClientException; 22 import com.aliyuncs.exceptions.ClientException;
18 -import com.aliyuncs.http.MethodType;  
19 import com.aliyuncs.profile.DefaultProfile; 23 import com.aliyuncs.profile.DefaultProfile;
20 import com.aliyuncs.profile.IClientProfile; 24 import com.aliyuncs.profile.IClientProfile;
21 import com.fasterxml.jackson.annotation.JsonFormat; 25 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -25,6 +29,8 @@ import lombok.extern.slf4j.Slf4j; @@ -25,6 +29,8 @@ import lombok.extern.slf4j.Slf4j;
25 29
26 import java.util.Date; 30 import java.util.Date;
27 import java.util.List; 31 import java.util.List;
  32 +import java.util.Objects;
  33 +import java.util.function.Function;
28 import java.util.stream.Collectors; 34 import java.util.stream.Collectors;
29 35
30 import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 36 import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -66,25 +72,13 @@ public class AliyunSmsClient extends AbstractSmsClient { @@ -66,25 +72,13 @@ public class AliyunSmsClient extends AbstractSmsClient {
66 String apiTemplateId, List<KeyValue<String, Object>> templateParams) { 72 String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
67 // 构建参数 73 // 构建参数
68 SendSmsRequest request = new SendSmsRequest(); 74 SendSmsRequest request = new SendSmsRequest();
69 - request.setSysMethod(MethodType.POST);  
70 request.setPhoneNumbers(mobile); 75 request.setPhoneNumbers(mobile);
71 request.setSignName(properties.getSignature()); 76 request.setSignName(properties.getSignature());
72 request.setTemplateCode(apiTemplateId); 77 request.setTemplateCode(apiTemplateId);
73 request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); 78 request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams)));
74 request.setOutId(String.valueOf(sendLogId)); 79 request.setOutId(String.valueOf(sendLogId));
75 -  
76 - try {  
77 - // 执行发送  
78 - SendSmsResponse sendResult = acsClient.getAcsResponse(request);  
79 - // 解析结果  
80 - SmsSendRespDTO data = null;  
81 - if (sendResult.getBizId() != null) {  
82 - data = new SmsSendRespDTO().setSerialNo(sendResult.getBizId());  
83 - }  
84 - return SmsCommonResult.build(sendResult.getCode(), sendResult.getMessage(), sendResult.getRequestId(), data, codeMapping);  
85 - } catch (ClientException ex) {  
86 - return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);  
87 - } 80 + // 执行请求
  81 + return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId()));
88 } 82 }
89 83
90 private static String formatResultMsg(ClientException ex) { 84 private static String formatResultMsg(ClientException ex) {
@@ -107,6 +101,48 @@ public class AliyunSmsClient extends AbstractSmsClient { @@ -107,6 +101,48 @@ public class AliyunSmsClient extends AbstractSmsClient {
107 }).collect(Collectors.toList()); 101 }).collect(Collectors.toList());
108 } 102 }
109 103
  104 + @Override
  105 + protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) {
  106 + // 构建参数
  107 + QuerySmsTemplateRequest request = new QuerySmsTemplateRequest();
  108 + request.setTemplateCode(apiTemplateId);
  109 + // 执行请求
  110 + return invoke(request, response -> {
  111 + SmsTemplateRespDTO data = new SmsTemplateRespDTO();
  112 + data.setId(response.getTemplateCode()).setContent(response.getTemplateContent());
  113 + data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason());
  114 + return data;
  115 + });
  116 + }
  117 +
  118 + private Integer convertSmsTemplateAuditStatus(Integer templateStatus) {
  119 + switch (templateStatus) {
  120 + case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
  121 + case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
  122 + case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
  123 + default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
  124 + }
  125 + }
  126 +
  127 + private <T extends AcsResponse, R> SmsCommonResult<R> invoke(AcsRequest<T> request, Function<T, R> consumer) {
  128 + try {
  129 + // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射
  130 + T sendResult = acsClient.getAcsResponse(request);
  131 + String code = (String) ReflectUtil.getFieldValue(sendResult, "code");
  132 + String message = (String) ReflectUtil.getFieldValue(sendResult, "message");
  133 + String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId");
  134 + // 解析结果
  135 + R data = null;
  136 + if (Objects.equals(code, "OK")) { // 请求成功的情况下
  137 + data = consumer.apply(sendResult);
  138 + }
  139 + // 拼接结果
  140 + return SmsCommonResult.build(code, message, requestId, data, codeMapping);
  141 + } catch (ClientException ex) {
  142 + return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
  143 + }
  144 + }
  145 +
110 /** 146 /**
111 * 短信接收状态 147 * 短信接收状态
112 * 148 *
src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java
@@ -21,6 +21,7 @@ public class AliyunSmsCodeMapping implements SmsCodeMapping { @@ -21,6 +21,7 @@ public class AliyunSmsCodeMapping implements SmsCodeMapping {
21 case "isp.RAM_PERMISSION_DENY": return SMS_CHANNEL_PERMISSION_DENY; 21 case "isp.RAM_PERMISSION_DENY": return SMS_CHANNEL_PERMISSION_DENY;
22 case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR; 22 case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR;
23 case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_LIMIT_CONTROL; 23 case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_LIMIT_CONTROL;
  24 + case "isv.SMS_TEMPLATE_ILLEGAL": return SMS_TEMPLATE_NOT_EXISTS;
24 } 25 }
25 return SMS_UNKNOWN; 26 return SMS_UNKNOWN;
26 } 27 }
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; @@ -8,6 +8,7 @@ import cn.iocoder.dashboard.common.core.KeyValue;
8 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; 8 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
9 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; 9 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
10 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 10 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
  11 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
11 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; 12 import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
12 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; 13 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
13 import cn.iocoder.dashboard.util.json.JsonUtils; 14 import cn.iocoder.dashboard.util.json.JsonUtils;
@@ -114,6 +115,11 @@ public class YunpianSmsClient extends AbstractSmsClient { @@ -114,6 +115,11 @@ public class YunpianSmsClient extends AbstractSmsClient {
114 }).collect(Collectors.toList()); 115 }).collect(Collectors.toList());
115 } 116 }
116 117
  118 + @Override
  119 + protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable {
  120 + return null;
  121 + }
  122 +
117 /** 123 /**
118 * 短信接收状态 124 * 短信接收状态
119 * 125 *
src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.sms.core.enums;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 短信模板的审核状态枚举
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@AllArgsConstructor
  12 +@Getter
  13 +public enum SmsTemplateAuditStatusEnum {
  14 +
  15 + CHECKING(1),
  16 + SUCCESS(2),
  17 + FAIL(3);
  18 +
  19 + private final Integer status;
  20 +
  21 +}
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; @@ -3,8 +3,10 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
3 import cn.iocoder.dashboard.common.core.KeyValue; 3 import cn.iocoder.dashboard.common.core.KeyValue;
4 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; 4 import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
5 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; 5 import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
  6 +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
6 import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; 7 import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
7 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; 8 import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
  9 +import org.junit.jupiter.api.BeforeAll;
8 import org.junit.jupiter.api.Test; 10 import org.junit.jupiter.api.Test;
9 11
10 import java.util.ArrayList; 12 import java.util.ArrayList;
@@ -15,8 +17,10 @@ import java.util.List; @@ -15,8 +17,10 @@ import java.util.List;
15 */ 17 */
16 public class AliyunSmsClientIntegrationTest { 18 public class AliyunSmsClientIntegrationTest {
17 19
18 - @Test  
19 - public void testSend() { 20 + private static AliyunSmsClient smsClient;
  21 +
  22 + @BeforeAll
  23 + public static void before() {
20 // 创建配置类 24 // 创建配置类
21 SmsChannelProperties properties = new SmsChannelProperties(); 25 SmsChannelProperties properties = new SmsChannelProperties();
22 properties.setId(1L); 26 properties.setId(1L);
@@ -25,14 +29,25 @@ public class AliyunSmsClientIntegrationTest { @@ -25,14 +29,25 @@ public class AliyunSmsClientIntegrationTest {
25 properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY")); 29 properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY"));
26 properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY")); 30 properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY"));
27 // 创建客户端 31 // 创建客户端
28 - AliyunSmsClient smsClient = new AliyunSmsClient(properties); 32 + smsClient = new AliyunSmsClient(properties);
29 smsClient.init(); 33 smsClient.init();
30 - // 发送短信 34 + }
  35 +
  36 + @Test
  37 + public void testSendSms() {
31 List<KeyValue<String, Object>> templateParams = new ArrayList<>(); 38 List<KeyValue<String, Object>> templateParams = new ArrayList<>();
32 templateParams.add(new KeyValue<>("code", "1024")); 39 templateParams.add(new KeyValue<>("code", "1024"));
33 // templateParams.put("operation", "嘿嘿"); 40 // templateParams.put("operation", "嘿嘿");
34 // SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); 41 // SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
35 - SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "SMS_207945135", templateParams); 42 + SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399",
  43 + "SMS_207945135", templateParams);
  44 + System.out.println(result);
  45 + }
  46 +
  47 + @Test
  48 + public void testGetSmsTemplate() {
  49 + String apiTemplateId = "SMS_2079451351";
  50 + SmsCommonResult<SmsTemplateRespDTO> result = smsClient.getSmsTemplate(apiTemplateId);
36 System.out.println(result); 51 System.out.println(result);
37 } 52 }
38 53