From bdbc5b2626823c8715e310f09fd9b3bfd9751b05 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 8 Apr 2021 00:51:59 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E9=98=BF=E9=87=8C=E4=BA=91=20sms=20client?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=E6=9F=A5=E8=AF=A2=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E7=9A=84=E5=B0=81=E8=A3=85=202.=20=E9=87=8D=E6=9E=84=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91=20sms=20client=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=20invoke=20=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/sms/core/client/SmsClient.java | 9 +++ .../core/client/dto/SmsTemplateRespDTO.java | 33 +++++++++ .../core/client/impl/AbstractSmsClient.java | 20 +++++- .../client/impl/aliyun/AliyunSmsClient.java | 68 ++++++++++++++----- .../impl/aliyun/AliyunSmsCodeMapping.java | 1 + .../client/impl/yunpian/YunpianSmsClient.java | 6 ++ .../enums/SmsTemplateAuditStatusEnum.java | 21 ++++++ .../AliyunSmsClientIntegrationTest.java | 25 +++++-- 8 files changed, 161 insertions(+), 22 deletions(-) create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java index 591ded92e..9d156dd69 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java +++ b/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 parseSmsReceiveStatus(String text) throws Throwable; + /** + * 查询指定的短信模板 + * + * @param apiTemplateId 短信 API 的模板编号 + * @return 短信模板 + */ + SmsCommonResult getSmsTemplate(String apiTemplateId); + } diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java new file mode 100644 index 000000000..938310e71 --- /dev/null +++ b/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; + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java index a443e5e11..254040229 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/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 doParseSmsReceiveStatus(String text) throws Throwable; + @Override + public SmsCommonResult getSmsTemplate(String apiTemplateId) { + // 执行短信发送 + SmsCommonResult result; + try { + result = doGetSmsTemplate(apiTemplateId); + } catch (Throwable ex) { + // 打印异常日志 + log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex); + // 封装返回 + return SmsCommonResult.error(ex); + } + return result; + } + + protected abstract SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable; + } diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java index 8dae88586..b2c4c13ad 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/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> 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 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 SmsCommonResult invoke(AcsRequest request, Function 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); + } + } + /** * 短信接收状态 * diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java index 8a804de0c..ee491ef5e 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java +++ b/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; } diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java index 59c61e45e..f72db456b 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java +++ b/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 doGetSmsTemplate(String apiTemplateId) throws Throwable { + return null; + } + /** * 短信接收状态 * diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java new file mode 100644 index 000000000..888b2eeb5 --- /dev/null +++ b/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; + +} diff --git a/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java b/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java index 8643a3a6c..dc1904a3a 100644 --- a/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java +++ b/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> templateParams = new ArrayList<>(); templateParams.add(new KeyValue<>("code", "1024")); // templateParams.put("operation", "嘿嘿"); // SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); - SmsCommonResult result = smsClient.sendSms(1L, "15601691399", "SMS_207945135", templateParams); + SmsCommonResult result = smsClient.sendSms(1L, "15601691399", + "SMS_207945135", templateParams); + System.out.println(result); + } + + @Test + public void testGetSmsTemplate() { + String apiTemplateId = "SMS_2079451351"; + SmsCommonResult result = smsClient.getSmsTemplate(apiTemplateId); System.out.println(result); }