Commit be20178f1207c76391dc45aebea0c001842e93ce
Merge remote-tracking branch 'upstream/master'
Showing
27 changed files
with
312 additions
and
840 deletions
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java
| @@ -31,8 +31,8 @@ public interface SmsClient { | @@ -31,8 +31,8 @@ public interface SmsClient { | ||
| 31 | * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序 | 31 | * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序 |
| 32 | * @return 短信发送结果 | 32 | * @return 短信发送结果 |
| 33 | */ | 33 | */ |
| 34 | - SmsCommonResult<SmsSendRespDTO> sendSms(Long logId, String mobile, String apiTemplateId, | ||
| 35 | - List<KeyValue<String, Object>> templateParams); | 34 | + SmsSendRespDTO sendSms(Long logId, String mobile, String apiTemplateId, |
| 35 | + List<KeyValue<String, Object>> templateParams) throws Throwable; | ||
| 36 | 36 | ||
| 37 | /** | 37 | /** |
| 38 | * 解析接收短信的接收结果 | 38 | * 解析接收短信的接收结果 |
| @@ -49,6 +49,6 @@ public interface SmsClient { | @@ -49,6 +49,6 @@ public interface SmsClient { | ||
| 49 | * @param apiTemplateId 短信 API 的模板编号 | 49 | * @param apiTemplateId 短信 API 的模板编号 |
| 50 | * @return 短信模板 | 50 | * @return 短信模板 |
| 51 | */ | 51 | */ |
| 52 | - SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId); | 52 | + SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable; |
| 53 | 53 | ||
| 54 | } | 54 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCodeMapping.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 5 | - | ||
| 6 | -import java.util.function.Function; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * 将 API 的错误码,转换为通用的错误码 | ||
| 10 | - * | ||
| 11 | - * @see SmsCommonResult | ||
| 12 | - * @see SmsFrameworkErrorCodeConstants | ||
| 13 | - * | ||
| 14 | - * @author 芋道源码 | ||
| 15 | - */ | ||
| 16 | -public interface SmsCodeMapping extends Function<String, ErrorCode> { | ||
| 17 | -} |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCommonResult.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client; | ||
| 2 | - | ||
| 3 | -import cn.hutool.core.exceptions.ExceptionUtil; | ||
| 4 | -import cn.hutool.core.lang.Assert; | ||
| 5 | -import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 6 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 7 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 8 | -import lombok.Data; | ||
| 9 | -import lombok.EqualsAndHashCode; | ||
| 10 | -import lombok.ToString; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * 短信的 CommonResult 拓展类 | ||
| 14 | - * | ||
| 15 | - * 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段 | ||
| 16 | - * | ||
| 17 | - * 另外,一些短信平台(例如说阿里云、腾讯云)会返回一个请求编号,用于排查请求失败的问题,我们设置到 {@link #apiRequestId} 字段 | ||
| 18 | - * | ||
| 19 | - * @author 芋道源码 | ||
| 20 | - */ | ||
| 21 | -@Data | ||
| 22 | -@EqualsAndHashCode(callSuper = true) | ||
| 23 | -@ToString(callSuper = true) | ||
| 24 | -public class SmsCommonResult<T> extends CommonResult<T> { | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * API 返回错误码 | ||
| 28 | - * | ||
| 29 | - * 由于第三方的错误码可能是字符串,所以使用 String 类型 | ||
| 30 | - */ | ||
| 31 | - private String apiCode; | ||
| 32 | - /** | ||
| 33 | - * API 返回提示 | ||
| 34 | - */ | ||
| 35 | - private String apiMsg; | ||
| 36 | - | ||
| 37 | - /** | ||
| 38 | - * API 请求编号 | ||
| 39 | - */ | ||
| 40 | - private String apiRequestId; | ||
| 41 | - | ||
| 42 | - private SmsCommonResult() { | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | - public static <T> SmsCommonResult<T> build(String apiCode, String apiMsg, String apiRequestId, | ||
| 46 | - T data, SmsCodeMapping codeMapping) { | ||
| 47 | - Assert.notNull(codeMapping, "参数 codeMapping 不能为空"); | ||
| 48 | - SmsCommonResult<T> result = new SmsCommonResult<T>().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId); | ||
| 49 | - result.setData(data); | ||
| 50 | - // 翻译错误码 | ||
| 51 | - if (codeMapping != null) { | ||
| 52 | - ErrorCode errorCode = codeMapping.apply(apiCode); | ||
| 53 | - if (errorCode == null) { | ||
| 54 | - errorCode = SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; | ||
| 55 | - } | ||
| 56 | - result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg()); | ||
| 57 | - } | ||
| 58 | - return result; | ||
| 59 | - } | ||
| 60 | - | ||
| 61 | - public static <T> SmsCommonResult<T> error(Throwable ex) { | ||
| 62 | - SmsCommonResult<T> result = new SmsCommonResult<>(); | ||
| 63 | - result.setCode(SmsFrameworkErrorCodeConstants.EXCEPTION.getCode()); | ||
| 64 | - result.setMsg(ExceptionUtil.getRootCauseMessage(ex)); | ||
| 65 | - return result; | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | -} |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java
| @@ -11,8 +11,33 @@ import lombok.Data; | @@ -11,8 +11,33 @@ import lombok.Data; | ||
| 11 | public class SmsSendRespDTO { | 11 | public class SmsSendRespDTO { |
| 12 | 12 | ||
| 13 | /** | 13 | /** |
| 14 | + * 是否成功 | ||
| 15 | + */ | ||
| 16 | + private Boolean success; | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * API 请求编号 | ||
| 20 | + */ | ||
| 21 | + private String apiRequestId; | ||
| 22 | + | ||
| 23 | + // ==================== 成功时字段 ==================== | ||
| 24 | + | ||
| 25 | + /** | ||
| 14 | * 短信 API 发送返回的序号 | 26 | * 短信 API 发送返回的序号 |
| 15 | */ | 27 | */ |
| 16 | private String serialNo; | 28 | private String serialNo; |
| 17 | 29 | ||
| 30 | + // ==================== 失败时字段 ==================== | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * API 返回错误码 | ||
| 34 | + * | ||
| 35 | + * 由于第三方的错误码可能是字符串,所以使用 String 类型 | ||
| 36 | + */ | ||
| 37 | + private String apiCode; | ||
| 38 | + /** | ||
| 39 | + * API 返回提示 | ||
| 40 | + */ | ||
| 41 | + private String apiMsg; | ||
| 42 | + | ||
| 18 | } | 43 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java
| 1 | package cn.iocoder.yudao.framework.sms.core.client.impl; | 1 | package cn.iocoder.yudao.framework.sms.core.client.impl; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 4 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; | 3 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; |
| 5 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; | ||
| 6 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 7 | -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | ||
| 8 | -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | ||
| 9 | -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | ||
| 10 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; | 4 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; |
| 11 | import lombok.extern.slf4j.Slf4j; | 5 | import lombok.extern.slf4j.Slf4j; |
| 12 | 6 | ||
| 13 | -import java.util.List; | ||
| 14 | - | ||
| 15 | /** | 7 | /** |
| 16 | * 短信客户端的抽象类,提供模板方法,减少子类的冗余代码 | 8 | * 短信客户端的抽象类,提供模板方法,减少子类的冗余代码 |
| 17 | * | 9 | * |
| @@ -25,14 +17,9 @@ public abstract class AbstractSmsClient implements SmsClient { | @@ -25,14 +17,9 @@ public abstract class AbstractSmsClient implements SmsClient { | ||
| 25 | * 短信渠道配置 | 17 | * 短信渠道配置 |
| 26 | */ | 18 | */ |
| 27 | protected volatile SmsChannelProperties properties; | 19 | protected volatile SmsChannelProperties properties; |
| 28 | - /** | ||
| 29 | - * 错误码枚举类 | ||
| 30 | - */ | ||
| 31 | - protected final SmsCodeMapping codeMapping; | ||
| 32 | 20 | ||
| 33 | - public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) { | ||
| 34 | - this.properties = prepareProperties(properties); | ||
| 35 | - this.codeMapping = codeMapping; | 21 | + public AbstractSmsClient(SmsChannelProperties properties) { |
| 22 | + this.properties = properties; | ||
| 36 | } | 23 | } |
| 37 | 24 | ||
| 38 | /** | 25 | /** |
| @@ -54,74 +41,13 @@ public abstract class AbstractSmsClient implements SmsClient { | @@ -54,74 +41,13 @@ public abstract class AbstractSmsClient implements SmsClient { | ||
| 54 | return; | 41 | return; |
| 55 | } | 42 | } |
| 56 | log.info("[refresh][配置({})发生变化,重新初始化]", properties); | 43 | log.info("[refresh][配置({})发生变化,重新初始化]", properties); |
| 57 | - this.properties = prepareProperties(properties); | ||
| 58 | // 初始化 | 44 | // 初始化 |
| 59 | this.init(); | 45 | this.init(); |
| 60 | } | 46 | } |
| 61 | 47 | ||
| 62 | - /** | ||
| 63 | - * 在赋值给{@link this#properties}前,子类可根据需要预处理短信渠道配置 | ||
| 64 | - * | ||
| 65 | - * @param properties 数据库中存储的短信渠道配置 | ||
| 66 | - * @return 满足子类实现的短信渠道配置 | ||
| 67 | - */ | ||
| 68 | - protected SmsChannelProperties prepareProperties(SmsChannelProperties properties) { | ||
| 69 | - return properties; | ||
| 70 | - } | ||
| 71 | - | ||
| 72 | @Override | 48 | @Override |
| 73 | public Long getId() { | 49 | public Long getId() { |
| 74 | return properties.getId(); | 50 | return properties.getId(); |
| 75 | } | 51 | } |
| 76 | 52 | ||
| 77 | - @Override | ||
| 78 | - public final SmsCommonResult<SmsSendRespDTO> sendSms(Long logId, String mobile, | ||
| 79 | - String apiTemplateId, List<KeyValue<String, Object>> templateParams) { | ||
| 80 | - // 执行短信发送 | ||
| 81 | - SmsCommonResult<SmsSendRespDTO> result; | ||
| 82 | - try { | ||
| 83 | - result = doSendSms(logId, mobile, apiTemplateId, templateParams); | ||
| 84 | - } catch (Throwable ex) { | ||
| 85 | - // 打印异常日志 | ||
| 86 | - log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]", | ||
| 87 | - logId, mobile, apiTemplateId, templateParams, ex); | ||
| 88 | - // 封装返回 | ||
| 89 | - return SmsCommonResult.error(ex); | ||
| 90 | - } | ||
| 91 | - return result; | ||
| 92 | - } | ||
| 93 | - | ||
| 94 | - protected abstract SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile, | ||
| 95 | - String apiTemplateId, List<KeyValue<String, Object>> templateParams) | ||
| 96 | - throws Throwable; | ||
| 97 | - | ||
| 98 | - @Override | ||
| 99 | - public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable { | ||
| 100 | - try { | ||
| 101 | - return doParseSmsReceiveStatus(text); | ||
| 102 | - } catch (Throwable ex) { | ||
| 103 | - log.error("[parseSmsReceiveStatus][text({}) 解析发生异常]", text, ex); | ||
| 104 | - throw ex; | ||
| 105 | - } | ||
| 106 | - } | ||
| 107 | - | ||
| 108 | - protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable; | ||
| 109 | - | ||
| 110 | - @Override | ||
| 111 | - public SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId) { | ||
| 112 | - // 执行短信发送 | ||
| 113 | - SmsCommonResult<SmsTemplateRespDTO> result; | ||
| 114 | - try { | ||
| 115 | - result = doGetSmsTemplate(apiTemplateId); | ||
| 116 | - } catch (Throwable ex) { | ||
| 117 | - // 打印异常日志 | ||
| 118 | - log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex); | ||
| 119 | - // 封装返回 | ||
| 120 | - return SmsCommonResult.error(ex); | ||
| 121 | - } | ||
| 122 | - return result; | ||
| 123 | - } | ||
| 124 | - | ||
| 125 | - protected abstract SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable; | ||
| 126 | - | ||
| 127 | } | 53 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java
| 1 | package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; | 1 | package cn.iocoder.yudao.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; | ||
| 5 | -import cn.hutool.core.util.StrUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 4 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 7 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | 5 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 6 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 7 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| 11 | import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; | 10 | import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; |
| 12 | import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | 11 | import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; |
| 13 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; | 12 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; |
| 14 | -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 15 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 16 | -import com.aliyuncs.AcsRequest; | ||
| 17 | -import com.aliyuncs.AcsResponse; | ||
| 18 | import com.aliyuncs.DefaultAcsClient; | 13 | import com.aliyuncs.DefaultAcsClient; |
| 19 | import com.aliyuncs.IAcsClient; | 14 | import com.aliyuncs.IAcsClient; |
| 20 | import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; | 15 | import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; |
| 16 | +import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; | ||
| 21 | import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; | 17 | import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; |
| 22 | -import com.aliyuncs.exceptions.ClientException; | 18 | +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; |
| 23 | import com.aliyuncs.profile.DefaultProfile; | 19 | import com.aliyuncs.profile.DefaultProfile; |
| 24 | import com.aliyuncs.profile.IClientProfile; | 20 | import com.aliyuncs.profile.IClientProfile; |
| 25 | import com.fasterxml.jackson.annotation.JsonFormat; | 21 | import com.fasterxml.jackson.annotation.JsonFormat; |
| @@ -31,9 +27,8 @@ import lombok.extern.slf4j.Slf4j; | @@ -31,9 +27,8 @@ import lombok.extern.slf4j.Slf4j; | ||
| 31 | import java.time.LocalDateTime; | 27 | import java.time.LocalDateTime; |
| 32 | import java.util.List; | 28 | import java.util.List; |
| 33 | import java.util.Objects; | 29 | import java.util.Objects; |
| 34 | -import java.util.function.Function; | ||
| 35 | -import java.util.stream.Collectors; | ||
| 36 | 30 | ||
| 31 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 37 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 32 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 38 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; | 33 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; |
| 39 | 34 | ||
| @@ -47,6 +42,11 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE | @@ -47,6 +42,11 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE | ||
| 47 | public class AliyunSmsClient extends AbstractSmsClient { | 42 | public class AliyunSmsClient extends AbstractSmsClient { |
| 48 | 43 | ||
| 49 | /** | 44 | /** |
| 45 | + * 调用成功 code | ||
| 46 | + */ | ||
| 47 | + public static final String API_CODE_SUCCESS = "OK"; | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | * REGION, 使用杭州 | 50 | * REGION, 使用杭州 |
| 51 | */ | 51 | */ |
| 52 | private static final String ENDPOINT = "cn-hangzhou"; | 52 | private static final String ENDPOINT = "cn-hangzhou"; |
| @@ -57,7 +57,7 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -57,7 +57,7 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 57 | private volatile IAcsClient client; | 57 | private volatile IAcsClient client; |
| 58 | 58 | ||
| 59 | public AliyunSmsClient(SmsChannelProperties properties) { | 59 | public AliyunSmsClient(SmsChannelProperties properties) { |
| 60 | - super(properties, new AliyunSmsCodeMapping()); | 60 | + super(properties); |
| 61 | Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); | 61 | Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); |
| 62 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); | 62 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); |
| 63 | } | 63 | } |
| @@ -69,9 +69,9 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -69,9 +69,9 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | @Override | 71 | @Override |
| 72 | - protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile, | ||
| 73 | - String apiTemplateId, List<KeyValue<String, Object>> templateParams) { | ||
| 74 | - // 构建参数 | 72 | + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, |
| 73 | + List<KeyValue<String, Object>> templateParams) throws Throwable { | ||
| 74 | + // 构建请求 | ||
| 75 | SendSmsRequest request = new SendSmsRequest(); | 75 | SendSmsRequest request = new SendSmsRequest(); |
| 76 | request.setPhoneNumbers(mobile); | 76 | request.setPhoneNumbers(mobile); |
| 77 | request.setSignName(properties.getSignature()); | 77 | request.setSignName(properties.getSignature()); |
| @@ -79,34 +79,32 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -79,34 +79,32 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 79 | request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); | 79 | request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); |
| 80 | request.setOutId(String.valueOf(sendLogId)); | 80 | request.setOutId(String.valueOf(sendLogId)); |
| 81 | // 执行请求 | 81 | // 执行请求 |
| 82 | - return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId())); | 82 | + SendSmsResponse response = client.getAcsResponse(request); |
| 83 | + return new SmsSendRespDTO().setSuccess(Objects.equals(response.getCode(), API_CODE_SUCCESS)).setSerialNo(response.getBizId()) | ||
| 84 | + .setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage()); | ||
| 83 | } | 85 | } |
| 84 | 86 | ||
| 85 | @Override | 87 | @Override |
| 86 | - protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable { | 88 | + public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { |
| 87 | List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); | 89 | List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); |
| 88 | - return statuses.stream().map(status -> { | ||
| 89 | - SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); | ||
| 90 | - resp.setSuccess(status.getSuccess()); | ||
| 91 | - resp.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()); | ||
| 92 | - resp.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()); | ||
| 93 | - resp.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId())); | ||
| 94 | - return resp; | ||
| 95 | - }).collect(Collectors.toList()); | 90 | + return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess()) |
| 91 | + .setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()) | ||
| 92 | + .setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()) | ||
| 93 | + .setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()))); | ||
| 96 | } | 94 | } |
| 97 | 95 | ||
| 98 | @Override | 96 | @Override |
| 99 | - protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) { | ||
| 100 | - // 构建参数 | 97 | + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { |
| 98 | + // 构建请求 | ||
| 101 | QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); | 99 | QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); |
| 102 | request.setTemplateCode(apiTemplateId); | 100 | request.setTemplateCode(apiTemplateId); |
| 103 | // 执行请求 | 101 | // 执行请求 |
| 104 | - return invoke(request, response -> { | ||
| 105 | - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); | ||
| 106 | - data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); | ||
| 107 | - data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); | ||
| 108 | - return data; | ||
| 109 | - }); | 102 | + QuerySmsTemplateResponse response = client.getAcsResponse(request); |
| 103 | + if (response.getTemplateStatus() == null) { | ||
| 104 | + return null; | ||
| 105 | + } | ||
| 106 | + return new SmsTemplateRespDTO().setId(response.getTemplateCode()).setContent(response.getTemplateContent()) | ||
| 107 | + .setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); | ||
| 110 | } | 108 | } |
| 111 | 109 | ||
| 112 | @VisibleForTesting | 110 | @VisibleForTesting |
| @@ -119,37 +117,10 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -119,37 +117,10 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 119 | } | 117 | } |
| 120 | } | 118 | } |
| 121 | 119 | ||
| 122 | - @VisibleForTesting | ||
| 123 | - <T extends AcsResponse, R> SmsCommonResult<R> invoke(AcsRequest<T> request, Function<T, R> responseConsumer) { | ||
| 124 | - try { | ||
| 125 | - // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射 | ||
| 126 | - T sendResult = client.getAcsResponse(request); | ||
| 127 | - String code = (String) ReflectUtil.getFieldValue(sendResult, "code"); | ||
| 128 | - String message = (String) ReflectUtil.getFieldValue(sendResult, "message"); | ||
| 129 | - String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId"); | ||
| 130 | - // 解析结果 | ||
| 131 | - R data = null; | ||
| 132 | - if (Objects.equals(code, "OK")) { // 请求成功的情况下 | ||
| 133 | - data = responseConsumer.apply(sendResult); | ||
| 134 | - } | ||
| 135 | - // 拼接结果 | ||
| 136 | - return SmsCommonResult.build(code, message, requestId, data, codeMapping); | ||
| 137 | - } catch (ClientException ex) { | ||
| 138 | - return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping); | ||
| 139 | - } | ||
| 140 | - } | ||
| 141 | - | ||
| 142 | - private static String formatResultMsg(ClientException ex) { | ||
| 143 | - if (StrUtil.isEmpty(ex.getErrorDescription())) { | ||
| 144 | - return ex.getErrMsg(); | ||
| 145 | - } | ||
| 146 | - return ex.getErrMsg() + " => " + ex.getErrorDescription(); | ||
| 147 | - } | ||
| 148 | - | ||
| 149 | /** | 120 | /** |
| 150 | * 短信接收状态 | 121 | * 短信接收状态 |
| 151 | * | 122 | * |
| 152 | - * 参见 https://help.aliyun.com/document_detail/101867.html 文档 | 123 | + * 参见 <a href="https://help.aliyun.com/document_detail/101867.html">文档</a> |
| 153 | * | 124 | * |
| 154 | * @author 芋道源码 | 125 | * @author 芋道源码 |
| 155 | */ | 126 | */ |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 5 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; | ||
| 6 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * 阿里云的 SmsCodeMapping 实现类 | ||
| 10 | - * | ||
| 11 | - * 参见 https://help.aliyun.com/document_detail/101346.htm 文档 | ||
| 12 | - * | ||
| 13 | - * @author 芋道源码 | ||
| 14 | - */ | ||
| 15 | -public class AliyunSmsCodeMapping implements SmsCodeMapping { | ||
| 16 | - | ||
| 17 | - @Override | ||
| 18 | - public ErrorCode apply(String apiCode) { | ||
| 19 | - switch (apiCode) { | ||
| 20 | - case "OK": return GlobalErrorCodeConstants.SUCCESS; | ||
| 21 | - case "isv.ACCOUNT_NOT_EXISTS": | ||
| 22 | - case "isv.ACCOUNT_ABNORMAL": | ||
| 23 | - case "MissingAccessKeyId": return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID; | ||
| 24 | - case "isp.RAM_PERMISSION_DENY": return SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY; | ||
| 25 | - case "isv.INVALID_JSON_PARAM": | ||
| 26 | - case "isv.INVALID_PARAMETERS": return SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR; | ||
| 27 | - case "isv.BUSINESS_LIMIT_CONTROL": return SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL; | ||
| 28 | - case "isv.DAY_LIMIT_CONTROL": return SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL; | ||
| 29 | - case "isv.SMS_CONTENT_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID; | ||
| 30 | - case "isv.SMS_TEMPLATE_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID; | ||
| 31 | - case "isv.SMS_SIGNATURE_ILLEGAL": | ||
| 32 | - case "isv.SIGN_NAME_ILLEGAL": | ||
| 33 | - case "isv.SMS_SIGN_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID; | ||
| 34 | - case "isv.AMOUNT_NOT_ENOUGH": | ||
| 35 | - case "isv.OUT_OF_SERVICE": return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH; | ||
| 36 | - case "isv.MOBILE_NUMBER_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID; | ||
| 37 | - case "isv.TEMPLATE_MISSING_PARAMETERS": return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR; | ||
| 38 | - default: return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; | ||
| 39 | - } | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | -} |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client.impl.debug; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 5 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; | ||
| 6 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 7 | - | ||
| 8 | -import java.util.Objects; | ||
| 9 | - | ||
| 10 | -/** | ||
| 11 | - * 钉钉的 SmsCodeMapping 实现类 | ||
| 12 | - * | ||
| 13 | - * @author 芋道源码 | ||
| 14 | - */ | ||
| 15 | -public class DebugDingTalkCodeMapping implements SmsCodeMapping { | ||
| 16 | - | ||
| 17 | - @Override | ||
| 18 | - public ErrorCode apply(String apiCode) { | ||
| 19 | - return Objects.equals(apiCode, "0") ? GlobalErrorCodeConstants.SUCCESS : SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; | ||
| 20 | - } | ||
| 21 | - | ||
| 22 | -} |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java
| @@ -8,19 +8,19 @@ import cn.hutool.crypto.digest.DigestUtil; | @@ -8,19 +8,19 @@ import cn.hutool.crypto.digest.DigestUtil; | ||
| 8 | import cn.hutool.crypto.digest.HmacAlgorithm; | 8 | import cn.hutool.crypto.digest.HmacAlgorithm; |
| 9 | import cn.hutool.http.HttpUtil; | 9 | import cn.hutool.http.HttpUtil; |
| 10 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 10 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 11 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | 11 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 12 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 12 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 13 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 13 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 14 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 14 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 15 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| 15 | import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; | 16 | import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; |
| 16 | import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | 17 | import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; |
| 17 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; | 18 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; |
| 18 | -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 19 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 20 | 19 | ||
| 21 | import java.util.HashMap; | 20 | import java.util.HashMap; |
| 22 | import java.util.List; | 21 | import java.util.List; |
| 23 | import java.util.Map; | 22 | import java.util.Map; |
| 23 | +import java.util.Objects; | ||
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * 基于钉钉 WebHook 实现的调试的短信客户端实现类 | 26 | * 基于钉钉 WebHook 实现的调试的短信客户端实现类 |
| @@ -32,7 +32,7 @@ import java.util.Map; | @@ -32,7 +32,7 @@ import java.util.Map; | ||
| 32 | public class DebugDingTalkSmsClient extends AbstractSmsClient { | 32 | public class DebugDingTalkSmsClient extends AbstractSmsClient { |
| 33 | 33 | ||
| 34 | public DebugDingTalkSmsClient(SmsChannelProperties properties) { | 34 | public DebugDingTalkSmsClient(SmsChannelProperties properties) { |
| 35 | - super(properties, new DebugDingTalkCodeMapping()); | 35 | + super(properties); |
| 36 | Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); | 36 | Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); |
| 37 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); | 37 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); |
| 38 | } | 38 | } |
| @@ -42,8 +42,8 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { | @@ -42,8 +42,8 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { | ||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | @Override | 44 | @Override |
| 45 | - protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile, | ||
| 46 | - String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable { | 45 | + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, |
| 46 | + String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable { | ||
| 47 | // 构建请求 | 47 | // 构建请求 |
| 48 | String url = buildUrl("robot/send"); | 48 | String url = buildUrl("robot/send"); |
| 49 | Map<String, Object> params = new HashMap<>(); | 49 | Map<String, Object> params = new HashMap<>(); |
| @@ -55,14 +55,15 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { | @@ -55,14 +55,15 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { | ||
| 55 | String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params)); | 55 | String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params)); |
| 56 | // 解析结果 | 56 | // 解析结果 |
| 57 | Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class); | 57 | Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class); |
| 58 | - return SmsCommonResult.build(MapUtil.getStr(responseObj, "errcode"), MapUtil.getStr(responseObj, "errorMsg"), | ||
| 59 | - null, new SmsSendRespDTO().setSerialNo(StrUtil.uuid()), codeMapping); | 58 | + String errorCode = MapUtil.getStr(responseObj, "errcode"); |
| 59 | + return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid()) | ||
| 60 | + .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg")); | ||
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | /** | 63 | /** |
| 63 | * 构建请求地址 | 64 | * 构建请求地址 |
| 64 | * | 65 | * |
| 65 | - * 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档 | 66 | + * 参见 <a href="https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71">文档</a> |
| 66 | * | 67 | * |
| 67 | * @param path 请求路径 | 68 | * @param path 请求路径 |
| 68 | * @return 请求地址 | 69 | * @return 请求地址 |
| @@ -82,15 +83,14 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { | @@ -82,15 +83,14 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { | ||
| 82 | } | 83 | } |
| 83 | 84 | ||
| 84 | @Override | 85 | @Override |
| 85 | - protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable { | 86 | + public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { |
| 86 | throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调"); | 87 | throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调"); |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | @Override | 90 | @Override |
| 90 | - protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) { | ||
| 91 | - SmsTemplateRespDTO data = new SmsTemplateRespDTO().setId(apiTemplateId).setContent("") | 91 | + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) { |
| 92 | + return new SmsTemplateRespDTO().setId(apiTemplateId).setContent("") | ||
| 92 | .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(""); | 93 | .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(""); |
| 93 | - return SmsCommonResult.build("0", "success", null, data, codeMapping); | ||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | } | 96 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsChannelProperties.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; | ||
| 2 | - | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import cn.hutool.core.lang.Assert; | ||
| 5 | -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; | ||
| 6 | -import lombok.Data; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * 腾讯云短信配置实现类 | ||
| 10 | - * 腾讯云发送短信时,需要额外的参数 sdkAppId, | ||
| 11 | - * | ||
| 12 | - * @author shiwp | ||
| 13 | - */ | ||
| 14 | -@Data | ||
| 15 | -public class TencentSmsChannelProperties extends SmsChannelProperties { | ||
| 16 | - | ||
| 17 | - /** | ||
| 18 | - * 应用 id | ||
| 19 | - */ | ||
| 20 | - private String sdkAppId; | ||
| 21 | - | ||
| 22 | - /** | ||
| 23 | - * 考虑到不破坏原有的 apiKey + apiSecret 的结构, | ||
| 24 | - * 所以腾讯云短信存储时,将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。 | ||
| 25 | - * 因此在使用时,需要将 secretId 和 sdkAppId 解析出来,分别存储到对应字段中。 | ||
| 26 | - */ | ||
| 27 | - public static TencentSmsChannelProperties build(SmsChannelProperties properties) { | ||
| 28 | - if (properties instanceof TencentSmsChannelProperties) { | ||
| 29 | - return (TencentSmsChannelProperties) properties; | ||
| 30 | - } | ||
| 31 | - TencentSmsChannelProperties result = BeanUtil.toBean(properties, TencentSmsChannelProperties.class); | ||
| 32 | - String combineKey = properties.getApiKey(); | ||
| 33 | - Assert.notEmpty(combineKey, "apiKey 不能为空"); | ||
| 34 | - String[] keys = combineKey.trim().split(" "); | ||
| 35 | - Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]"); | ||
| 36 | - Assert.notBlank(keys[0], "腾讯云短信 secretId 不能为空"); | ||
| 37 | - Assert.notBlank(keys[1], "腾讯云短信 sdkAppId 不能为空"); | ||
| 38 | - result.setSdkAppId(keys[1]).setApiKey(keys[0]); | ||
| 39 | - return result; | ||
| 40 | - } | ||
| 41 | -} |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java
| @@ -4,9 +4,7 @@ import cn.hutool.core.lang.Assert; | @@ -4,9 +4,7 @@ import cn.hutool.core.lang.Assert; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 5 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 6 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 7 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 8 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 9 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 11 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 12 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| @@ -17,23 +15,22 @@ import com.fasterxml.jackson.annotation.JsonFormat; | @@ -17,23 +15,22 @@ import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 17 | import com.fasterxml.jackson.annotation.JsonProperty; | 15 | import com.fasterxml.jackson.annotation.JsonProperty; |
| 18 | import com.google.common.annotations.VisibleForTesting; | 16 | import com.google.common.annotations.VisibleForTesting; |
| 19 | import com.tencentcloudapi.common.Credential; | 17 | import com.tencentcloudapi.common.Credential; |
| 20 | -import com.tencentcloudapi.common.exception.TencentCloudSDKException; | ||
| 21 | import com.tencentcloudapi.sms.v20210111.SmsClient; | 18 | import com.tencentcloudapi.sms.v20210111.SmsClient; |
| 22 | import com.tencentcloudapi.sms.v20210111.models.*; | 19 | import com.tencentcloudapi.sms.v20210111.models.*; |
| 23 | import lombok.Data; | 20 | import lombok.Data; |
| 24 | 21 | ||
| 25 | import java.time.LocalDateTime; | 22 | import java.time.LocalDateTime; |
| 26 | import java.util.List; | 23 | import java.util.List; |
| 27 | -import java.util.function.Function; | ||
| 28 | -import java.util.function.Supplier; | 24 | +import java.util.Objects; |
| 29 | 25 | ||
| 26 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 30 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 27 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 31 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; | 28 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; |
| 32 | 29 | ||
| 33 | /** | 30 | /** |
| 34 | * 腾讯云短信功能实现 | 31 | * 腾讯云短信功能实现 |
| 35 | - * <p> | ||
| 36 | - * 参见 https://cloud.tencent.com/document/product/382/52077 | 32 | + * |
| 33 | + * 参见 <a href="https://cloud.tencent.com/document/product/382/52077">文档</a> | ||
| 37 | * | 34 | * |
| 38 | * @author shiwp | 35 | * @author shiwp |
| 39 | */ | 36 | */ |
| @@ -42,7 +39,7 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -42,7 +39,7 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 42 | /** | 39 | /** |
| 43 | * 调用成功 code | 40 | * 调用成功 code |
| 44 | */ | 41 | */ |
| 45 | - public static final String API_SUCCESS_CODE = "Ok"; | 42 | + public static final String API_CODE_SUCCESS = "Ok"; |
| 46 | 43 | ||
| 47 | /** | 44 | /** |
| 48 | * REGION,使用南京 | 45 | * REGION,使用南京 |
| @@ -51,180 +48,103 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -51,180 +48,103 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 51 | 48 | ||
| 52 | /** | 49 | /** |
| 53 | * 是否国际/港澳台短信: | 50 | * 是否国际/港澳台短信: |
| 51 | + * | ||
| 54 | * 0:表示国内短信。 | 52 | * 0:表示国内短信。 |
| 55 | * 1:表示国际/港澳台短信。 | 53 | * 1:表示国际/港澳台短信。 |
| 56 | */ | 54 | */ |
| 57 | - private static final long INTERNATIONAL = 0L; | 55 | + private static final long INTERNATIONAL_CHINA = 0L; |
| 58 | 56 | ||
| 59 | private SmsClient client; | 57 | private SmsClient client; |
| 60 | 58 | ||
| 61 | public TencentSmsClient(SmsChannelProperties properties) { | 59 | public TencentSmsClient(SmsChannelProperties properties) { |
| 62 | - super(properties, new TencentSmsCodeMapping()); | 60 | + super(properties); |
| 63 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); | 61 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); |
| 62 | + validateSdkAppId(properties); | ||
| 64 | } | 63 | } |
| 65 | 64 | ||
| 66 | @Override | 65 | @Override |
| 67 | protected void doInit() { | 66 | protected void doInit() { |
| 68 | // 实例化一个认证对象,入参需要传入腾讯云账户密钥对 secretId,secretKey | 67 | // 实例化一个认证对象,入参需要传入腾讯云账户密钥对 secretId,secretKey |
| 69 | - Credential credential = new Credential(properties.getApiKey(), properties.getApiSecret()); | 68 | + Credential credential = new Credential(getApiKey(), properties.getApiSecret()); |
| 70 | client = new SmsClient(credential, ENDPOINT); | 69 | client = new SmsClient(credential, ENDPOINT); |
| 71 | } | 70 | } |
| 72 | 71 | ||
| 73 | - @Override | ||
| 74 | - protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, | ||
| 75 | - String mobile, | ||
| 76 | - String apiTemplateId, | ||
| 77 | - List<KeyValue<String, Object>> templateParams) throws Throwable { | ||
| 78 | - return invoke(() -> buildSendSmsRequest(sendLogId, mobile, apiTemplateId, templateParams), | ||
| 79 | - this::doSendSms0, | ||
| 80 | - response -> { | ||
| 81 | - SendStatus sendStatus = response.getSendStatusSet()[0]; | ||
| 82 | - return SmsCommonResult.build(sendStatus.getCode(), sendStatus.getMessage(), response.getRequestId(), | ||
| 83 | - new SmsSendRespDTO().setSerialNo(sendStatus.getSerialNo()), codeMapping); | ||
| 84 | - }); | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - | ||
| 88 | /** | 72 | /** |
| 89 | - * 腾讯云发放短信的时候,需要额外的参数 sdkAppId。 | ||
| 90 | - * 考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。 | ||
| 91 | - * 因此,这边需要使用 TencentSmsChannelProperties 做拆分,重新封装到 properties 内。 | 73 | + * 参数校验腾讯云的 SDK AppId |
| 74 | + * | ||
| 75 | + * 原因是:腾讯云发放短信的时候,需要额外的参数 sdkAppId | ||
| 76 | + * | ||
| 77 | + * 解决方案:考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。 | ||
| 92 | * | 78 | * |
| 93 | - * @param properties 数据库中存储的短信渠道配置 | ||
| 94 | - * @return TencentSmsChannelProperties | 79 | + * @param properties 配置 |
| 95 | */ | 80 | */ |
| 96 | - @Override | ||
| 97 | - protected SmsChannelProperties prepareProperties(SmsChannelProperties properties) { | ||
| 98 | - return TencentSmsChannelProperties.build(properties); | 81 | + private static void validateSdkAppId(SmsChannelProperties properties) { |
| 82 | + String combineKey = properties.getApiKey(); | ||
| 83 | + Assert.notEmpty(combineKey, "apiKey 不能为空"); | ||
| 84 | + String[] keys = combineKey.trim().split(" "); | ||
| 85 | + Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]"); | ||
| 99 | } | 86 | } |
| 100 | 87 | ||
| 101 | - /** | ||
| 102 | - * 调用腾讯云 SDK 发送短信 | ||
| 103 | - * | ||
| 104 | - * @param request 发送短信请求 | ||
| 105 | - * @return 发送短信响应 | ||
| 106 | - * @throws TencentCloudSDKException SDK 用来封装发送短信失败 | ||
| 107 | - */ | ||
| 108 | - private SendSmsResponse doSendSms0(SendSmsRequest request) throws TencentCloudSDKException { | ||
| 109 | - return client.SendSms(request); | 88 | + private String getSdkAppId() { |
| 89 | + return StrUtil.subAfter(properties.getApiKey(), " ", true); | ||
| 110 | } | 90 | } |
| 111 | 91 | ||
| 112 | - /** | ||
| 113 | - * 封装腾讯云发送短信请求 | ||
| 114 | - * | ||
| 115 | - * @param sendLogId 日志编号 | ||
| 116 | - * @param mobile 手机号 | ||
| 117 | - * @param apiTemplateId 短信 API 的模板编号 | ||
| 118 | - * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序 | ||
| 119 | - * @return 腾讯云发送短信请求 | ||
| 120 | - */ | ||
| 121 | - private SendSmsRequest buildSendSmsRequest(Long sendLogId, | ||
| 122 | - String mobile, | ||
| 123 | - String apiTemplateId, | ||
| 124 | - List<KeyValue<String, Object>> templateParams) { | 92 | + private String getApiKey() { |
| 93 | + return StrUtil.subBefore(properties.getApiKey(), " ", true); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + @Override | ||
| 97 | + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, | ||
| 98 | + String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable { | ||
| 99 | + // 构建请求 | ||
| 125 | SendSmsRequest request = new SendSmsRequest(); | 100 | SendSmsRequest request = new SendSmsRequest(); |
| 126 | - request.setSmsSdkAppId(((TencentSmsChannelProperties) properties).getSdkAppId()); | 101 | + request.setSmsSdkAppId(getSdkAppId()); |
| 127 | request.setPhoneNumberSet(new String[]{mobile}); | 102 | request.setPhoneNumberSet(new String[]{mobile}); |
| 128 | request.setSignName(properties.getSignature()); | 103 | request.setSignName(properties.getSignature()); |
| 129 | request.setTemplateId(apiTemplateId); | 104 | request.setTemplateId(apiTemplateId); |
| 130 | request.setTemplateParamSet(ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue()))); | 105 | request.setTemplateParamSet(ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue()))); |
| 131 | request.setSessionContext(JsonUtils.toJsonString(new SessionContext().setLogId(sendLogId))); | 106 | request.setSessionContext(JsonUtils.toJsonString(new SessionContext().setLogId(sendLogId))); |
| 132 | - return request; | 107 | + // 执行请求 |
| 108 | + SendSmsResponse response = client.SendSms(request); | ||
| 109 | + SendStatus status = response.getSendStatusSet()[0]; | ||
| 110 | + return new SmsSendRespDTO().setSuccess(Objects.equals(status.getCode(), API_CODE_SUCCESS)).setSerialNo(status.getSerialNo()) | ||
| 111 | + .setApiRequestId(response.getRequestId()).setApiCode(status.getCode()).setApiMsg(status.getMessage()); | ||
| 133 | } | 112 | } |
| 134 | 113 | ||
| 135 | @Override | 114 | @Override |
| 136 | - protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable { | 115 | + public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { |
| 137 | List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class); | 116 | List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class); |
| 138 | - return CollectionUtils.convertList(callback, status -> { | ||
| 139 | - SmsReceiveRespDTO data = new SmsReceiveRespDTO(); | ||
| 140 | - data.setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription()); | ||
| 141 | - data.setReceiveTime(status.getReceiveTime()).setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus())); | ||
| 142 | - data.setMobile(status.getMobile()).setSerialNo(status.getSerialNo()); | ||
| 143 | - SessionContext context; | ||
| 144 | - Long logId; | ||
| 145 | - Assert.notNull(context = status.getSessionContext(), "回执信息中未解析出 context,请联系腾讯云小助手"); | ||
| 146 | - Assert.notNull(logId = context.getLogId(), "回执信息中未解析出 logId,请联系腾讯云小助手"); | ||
| 147 | - data.setLogId(logId); | ||
| 148 | - return data; | ||
| 149 | - }); | 117 | + return convertList(callback, status -> new SmsReceiveRespDTO() |
| 118 | + .setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus())) | ||
| 119 | + .setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription()) | ||
| 120 | + .setMobile(status.getMobile()).setReceiveTime(status.getReceiveTime()) | ||
| 121 | + .setSerialNo(status.getSerialNo()).setLogId(status.getSessionContext().getLogId())); | ||
| 150 | } | 122 | } |
| 151 | 123 | ||
| 152 | @Override | 124 | @Override |
| 153 | - protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable { | ||
| 154 | - return invoke(() -> this.buildSmsTemplateStatusRequest(apiTemplateId), | ||
| 155 | - this::doGetSmsTemplate0, | ||
| 156 | - response -> { | ||
| 157 | - SmsTemplateRespDTO data = convertTemplateStatusDTO(response.getDescribeTemplateStatusSet()[0]); | ||
| 158 | - return SmsCommonResult.build(API_SUCCESS_CODE, null, response.getRequestId(), data, codeMapping); | ||
| 159 | - }); | ||
| 160 | - } | ||
| 161 | - | ||
| 162 | - @VisibleForTesting | ||
| 163 | - SmsTemplateRespDTO convertTemplateStatusDTO(DescribeTemplateListStatus templateStatus) { | ||
| 164 | - if (templateStatus == null) { | ||
| 165 | - return null; | ||
| 166 | - } | ||
| 167 | - SmsTemplateAuditStatusEnum auditStatus; | ||
| 168 | - Assert.notNull(templateStatus.getStatusCode(), | ||
| 169 | - StrUtil.format("短信模版审核状态为 null,模版 id{}", templateStatus.getTemplateId())); | ||
| 170 | - switch (templateStatus.getStatusCode().intValue()) { | ||
| 171 | - case -1: | ||
| 172 | - auditStatus = SmsTemplateAuditStatusEnum.FAIL; | ||
| 173 | - break; | ||
| 174 | - case 0: | ||
| 175 | - auditStatus = SmsTemplateAuditStatusEnum.SUCCESS; | ||
| 176 | - break; | ||
| 177 | - case 1: | ||
| 178 | - auditStatus = SmsTemplateAuditStatusEnum.CHECKING; | ||
| 179 | - break; | ||
| 180 | - default: | ||
| 181 | - throw new IllegalStateException(StrUtil.format("不能解析短信模版审核状态{},模版 id{}", | ||
| 182 | - templateStatus.getStatusCode(), templateStatus.getTemplateId())); | ||
| 183 | - } | ||
| 184 | - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); | ||
| 185 | - data.setId(String.valueOf(templateStatus.getTemplateId())).setContent(templateStatus.getTemplateContent()); | ||
| 186 | - data.setAuditStatus(auditStatus.getStatus()).setAuditReason(templateStatus.getReviewReply()); | ||
| 187 | - return data; | ||
| 188 | - } | ||
| 189 | - | ||
| 190 | - /** | ||
| 191 | - * 封装查询模版审核状态请求 | ||
| 192 | - * @param apiTemplateId api 的模版 id | ||
| 193 | - * @return 查询模版审核状态请求 | ||
| 194 | - */ | ||
| 195 | - private DescribeSmsTemplateListRequest buildSmsTemplateStatusRequest(String apiTemplateId) { | 125 | + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { |
| 126 | + // 构建请求 | ||
| 196 | DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest(); | 127 | DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest(); |
| 197 | request.setTemplateIdSet(new Long[]{Long.parseLong(apiTemplateId)}); | 128 | request.setTemplateIdSet(new Long[]{Long.parseLong(apiTemplateId)}); |
| 198 | - // 地区 0:表示国内短信。1:表示国际/港澳台短信。 | ||
| 199 | - request.setInternational(INTERNATIONAL); | ||
| 200 | - return request; | ||
| 201 | - } | ||
| 202 | - | ||
| 203 | - /** | ||
| 204 | - * 调用腾讯云 SDK 查询短信模版状态 | ||
| 205 | - * | ||
| 206 | - * @param request 查询短信模版状态请求 | ||
| 207 | - * @return 查询短信模版状态响应 | ||
| 208 | - * @throws TencentCloudSDKException SDK 用来封装查询短信模版状态失败 | ||
| 209 | - */ | ||
| 210 | - private DescribeSmsTemplateListResponse doGetSmsTemplate0(DescribeSmsTemplateListRequest request) throws TencentCloudSDKException { | ||
| 211 | - return client.DescribeSmsTemplateList(request); | 129 | + request.setInternational(INTERNATIONAL_CHINA); |
| 130 | + // 执行请求 | ||
| 131 | + DescribeSmsTemplateListResponse response = client.DescribeSmsTemplateList(request); | ||
| 132 | + DescribeTemplateListStatus status = response.getDescribeTemplateStatusSet()[0]; | ||
| 133 | + if (status == null || status.getStatusCode() == null) { | ||
| 134 | + return null; | ||
| 135 | + } | ||
| 136 | + return new SmsTemplateRespDTO().setId(status.getTemplateId().toString()).setContent(status.getTemplateContent()) | ||
| 137 | + .setAuditStatus(convertSmsTemplateAuditStatus(status.getStatusCode().intValue())).setAuditReason(status.getReviewReply()); | ||
| 212 | } | 138 | } |
| 213 | 139 | ||
| 214 | - <Q, P, R> SmsCommonResult<R> invoke(Supplier<Q> requestSupplier, | ||
| 215 | - SdkFunction<Q, P> responseSupplier, | ||
| 216 | - Function<P, SmsCommonResult<R>> resultGen) { | ||
| 217 | - // 构建请求body | ||
| 218 | - Q request = requestSupplier.get(); | ||
| 219 | - P response; | ||
| 220 | - // 调用腾讯云发送短信 | ||
| 221 | - try { | ||
| 222 | - response = responseSupplier.apply(request); | ||
| 223 | - } catch (TencentCloudSDKException e) { | ||
| 224 | - // 调用异常,封装结果 | ||
| 225 | - return SmsCommonResult.build(e.getErrorCode(), e.getMessage(), e.getRequestId(), null, codeMapping); | 140 | + @VisibleForTesting |
| 141 | + Integer convertSmsTemplateAuditStatus(int templateStatus) { | ||
| 142 | + switch (templateStatus) { | ||
| 143 | + case 1: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); | ||
| 144 | + case 0: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); | ||
| 145 | + case -1: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); | ||
| 146 | + default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); | ||
| 226 | } | 147 | } |
| 227 | - return resultGen.apply(response); | ||
| 228 | } | 148 | } |
| 229 | 149 | ||
| 230 | @Data | 150 | @Data |
| @@ -278,7 +198,7 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -278,7 +198,7 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 278 | private String serialNo; | 198 | private String serialNo; |
| 279 | 199 | ||
| 280 | /** | 200 | /** |
| 281 | - * 用户的 session 内容(与发送接口的请求参数SessionContext一致) | 201 | + * 用户的 session 内容(与发送接口的请求参数 SessionContext 一致) |
| 282 | */ | 202 | */ |
| 283 | @JsonProperty("ext") | 203 | @JsonProperty("ext") |
| 284 | private SessionContext sessionContext; | 204 | private SessionContext sessionContext; |
| @@ -293,10 +213,7 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -293,10 +213,7 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 293 | * 发送短信记录id | 213 | * 发送短信记录id |
| 294 | */ | 214 | */ |
| 295 | private Long logId; | 215 | private Long logId; |
| 296 | - } | ||
| 297 | 216 | ||
| 298 | - private interface SdkFunction<T, R> { | ||
| 299 | - R apply(T t) throws TencentCloudSDKException; | ||
| 300 | } | 217 | } |
| 301 | 218 | ||
| 302 | } | 219 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMapping.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 5 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; | ||
| 6 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 7 | - | ||
| 8 | -import static cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; | ||
| 9 | - | ||
| 10 | -/** | ||
| 11 | - * 腾讯云的 SmsCodeMapping 实现类 | ||
| 12 | - * | ||
| 13 | - * 参见 https://cloud.tencent.com/document/api/382/52075#.E5.85.AC.E5.85.B1.E9.94.99.E8.AF.AF.E7.A0.81 | ||
| 14 | - * | ||
| 15 | - * @author : shiwp | ||
| 16 | - */ | ||
| 17 | -public class TencentSmsCodeMapping implements SmsCodeMapping { | ||
| 18 | - | ||
| 19 | - @Override | ||
| 20 | - public ErrorCode apply(String apiCode) { | ||
| 21 | - switch (apiCode) { | ||
| 22 | - case TencentSmsClient.API_SUCCESS_CODE: return GlobalErrorCodeConstants.SUCCESS; | ||
| 23 | - case "FailedOperation.ContainSensitiveWord": return SMS_SEND_CONTENT_INVALID; | ||
| 24 | - case "FailedOperation.JsonParseFail": | ||
| 25 | - case "MissingParameter.EmptyPhoneNumberSet": | ||
| 26 | - case "LimitExceeded.PhoneNumberCountLimit": | ||
| 27 | - case "FailedOperation.FailResolvePacket": return GlobalErrorCodeConstants.BAD_REQUEST; | ||
| 28 | - case "FailedOperation.InsufficientBalanceInSmsPackage": return SMS_ACCOUNT_MONEY_NOT_ENOUGH; | ||
| 29 | - case "FailedOperation.MarketingSendTimeConstraint": return SMS_SEND_MARKET_LIMIT_CONTROL; | ||
| 30 | - case "FailedOperation.PhoneNumberInBlacklist": return SMS_MOBILE_BLACK; | ||
| 31 | - case "FailedOperation.SignatureIncorrectOrUnapproved": return SMS_SIGN_INVALID; | ||
| 32 | - case "FailedOperation.MissingTemplateToModify": | ||
| 33 | - case "FailedOperation.TemplateIncorrectOrUnapproved": return SMS_TEMPLATE_INVALID; | ||
| 34 | - case "InvalidParameterValue.IncorrectPhoneNumber": return SMS_MOBILE_INVALID; | ||
| 35 | - case "InvalidParameterValue.SdkAppIdNotExist": return SMS_APP_ID_INVALID; | ||
| 36 | - case "InvalidParameterValue.TemplateParameterLengthLimit": | ||
| 37 | - case "InvalidParameterValue.TemplateParameterFormatError": return SMS_TEMPLATE_PARAM_ERROR; | ||
| 38 | - case "LimitExceeded.PhoneNumberDailyLimit": return SMS_SEND_DAY_LIMIT_CONTROL; | ||
| 39 | - case "LimitExceeded.PhoneNumberThirtySecondLimit": | ||
| 40 | - case "LimitExceeded.PhoneNumberOneHourLimit": return SMS_SEND_BUSINESS_LIMIT_CONTROL; | ||
| 41 | - case "UnauthorizedOperation.RequestPermissionDeny": | ||
| 42 | - case "FailedOperation.ForbidAddMarketingTemplates": | ||
| 43 | - case "FailedOperation.NotEnterpriseCertification": | ||
| 44 | - case "UnauthorizedOperation.IndividualUserMarketingSmsPermissionDeny": return SMS_PERMISSION_DENY; | ||
| 45 | - case "UnauthorizedOperation.RequestIpNotInWhitelist": return SMS_IP_DENY; | ||
| 46 | - case "AuthFailure.SecretIdNotFound": return SMS_ACCOUNT_INVALID; | ||
| 47 | - } | ||
| 48 | - return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; | ||
| 49 | - } | ||
| 50 | -} | ||
| 51 | \ No newline at end of file | 0 | \ No newline at end of file |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java
| 1 | package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; | 1 | package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.ReflectUtil; | 3 | import cn.hutool.core.util.ReflectUtil; |
| 4 | -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 5 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 4 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 6 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 7 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | 5 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 6 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 7 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| 11 | import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | 9 | import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; |
| 12 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; | 10 | import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; |
| 13 | -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 14 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 15 | -import com.aliyuncs.AcsRequest; | 11 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| 16 | import com.aliyuncs.IAcsClient; | 12 | import com.aliyuncs.IAcsClient; |
| 17 | import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; | 13 | import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; |
| 18 | import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; | 14 | import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; |
| 19 | import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; | 15 | import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; |
| 20 | import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; | 16 | import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; |
| 21 | -import com.aliyuncs.exceptions.ClientException; | ||
| 22 | import com.google.common.collect.Lists; | 17 | import com.google.common.collect.Lists; |
| 23 | -import org.junit.jupiter.api.Assertions; | ||
| 24 | import org.junit.jupiter.api.Test; | 18 | import org.junit.jupiter.api.Test; |
| 25 | import org.mockito.ArgumentMatcher; | 19 | import org.mockito.ArgumentMatcher; |
| 26 | import org.mockito.InjectMocks; | 20 | import org.mockito.InjectMocks; |
| @@ -28,12 +22,10 @@ import org.mockito.Mock; | @@ -28,12 +22,10 @@ import org.mockito.Mock; | ||
| 28 | 22 | ||
| 29 | import java.time.LocalDateTime; | 23 | import java.time.LocalDateTime; |
| 30 | import java.util.List; | 24 | import java.util.List; |
| 31 | -import java.util.function.Function; | ||
| 32 | 25 | ||
| 33 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 26 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 34 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 27 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 35 | import static org.junit.jupiter.api.Assertions.*; | 28 | import static org.junit.jupiter.api.Assertions.*; |
| 36 | -import static org.mockito.ArgumentMatchers.any; | ||
| 37 | import static org.mockito.ArgumentMatchers.argThat; | 29 | import static org.mockito.ArgumentMatchers.argThat; |
| 38 | import static org.mockito.Mockito.when; | 30 | import static org.mockito.Mockito.when; |
| 39 | 31 | ||
| @@ -67,8 +59,7 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | @@ -67,8 +59,7 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | ||
| 67 | } | 59 | } |
| 68 | 60 | ||
| 69 | @Test | 61 | @Test |
| 70 | - @SuppressWarnings("unchecked") | ||
| 71 | - public void testDoSendSms() throws ClientException { | 62 | + public void tesSendSms_success() throws Throwable { |
| 72 | // 准备参数 | 63 | // 准备参数 |
| 73 | Long sendLogId = randomLongId(); | 64 | Long sendLogId = randomLongId(); |
| 74 | String mobile = randomString(); | 65 | String mobile = randomString(); |
| @@ -87,20 +78,47 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | @@ -87,20 +78,47 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | ||
| 87 | }))).thenReturn(response); | 78 | }))).thenReturn(response); |
| 88 | 79 | ||
| 89 | // 调用 | 80 | // 调用 |
| 90 | - SmsCommonResult<SmsSendRespDTO> result = smsClient.doSendSms(sendLogId, mobile, | 81 | + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, |
| 91 | apiTemplateId, templateParams); | 82 | apiTemplateId, templateParams); |
| 92 | // 断言 | 83 | // 断言 |
| 84 | + assertTrue(result.getSuccess()); | ||
| 85 | + assertEquals(response.getRequestId(), result.getApiRequestId()); | ||
| 93 | assertEquals(response.getCode(), result.getApiCode()); | 86 | assertEquals(response.getCode(), result.getApiCode()); |
| 94 | assertEquals(response.getMessage(), result.getApiMsg()); | 87 | assertEquals(response.getMessage(), result.getApiMsg()); |
| 95 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); | ||
| 96 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); | 88 | + assertEquals(response.getBizId(), result.getSerialNo()); |
| 89 | + } | ||
| 90 | + | ||
| 91 | + @Test | ||
| 92 | + public void tesSendSms_fail() throws Throwable { | ||
| 93 | + // 准备参数 | ||
| 94 | + Long sendLogId = randomLongId(); | ||
| 95 | + String mobile = randomString(); | ||
| 96 | + String apiTemplateId = randomString(); | ||
| 97 | + List<KeyValue<String, Object>> templateParams = Lists.newArrayList( | ||
| 98 | + new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); | ||
| 99 | + // mock 方法 | ||
| 100 | + SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("ERROR")); | ||
| 101 | + when(client.getAcsResponse(argThat((ArgumentMatcher<SendSmsRequest>) acsRequest -> { | ||
| 102 | + assertEquals(mobile, acsRequest.getPhoneNumbers()); | ||
| 103 | + assertEquals(properties.getSignature(), acsRequest.getSignName()); | ||
| 104 | + assertEquals(apiTemplateId, acsRequest.getTemplateCode()); | ||
| 105 | + assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); | ||
| 106 | + assertEquals(sendLogId.toString(), acsRequest.getOutId()); | ||
| 107 | + return true; | ||
| 108 | + }))).thenReturn(response); | ||
| 109 | + | ||
| 110 | + // 调用 | ||
| 111 | + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); | ||
| 112 | + // 断言 | ||
| 113 | + assertFalse(result.getSuccess()); | ||
| 97 | assertEquals(response.getRequestId(), result.getApiRequestId()); | 114 | assertEquals(response.getRequestId(), result.getApiRequestId()); |
| 98 | - // 断言结果 | ||
| 99 | - assertEquals(response.getBizId(), result.getData().getSerialNo()); | 115 | + assertEquals(response.getCode(), result.getApiCode()); |
| 116 | + assertEquals(response.getMessage(), result.getApiMsg()); | ||
| 117 | + assertEquals(response.getBizId(), result.getSerialNo()); | ||
| 100 | } | 118 | } |
| 101 | 119 | ||
| 102 | @Test | 120 | @Test |
| 103 | - public void testDoTParseSmsReceiveStatus() throws Throwable { | 121 | + public void testParseSmsReceiveStatus() { |
| 104 | // 准备参数 | 122 | // 准备参数 |
| 105 | String text = "[\n" + | 123 | String text = "[\n" + |
| 106 | " {\n" + | 124 | " {\n" + |
| @@ -118,20 +136,21 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | @@ -118,20 +136,21 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | ||
| 118 | // mock 方法 | 136 | // mock 方法 |
| 119 | 137 | ||
| 120 | // 调用 | 138 | // 调用 |
| 121 | - List<SmsReceiveRespDTO> statuses = smsClient.doParseSmsReceiveStatus(text); | 139 | + List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text); |
| 122 | // 断言 | 140 | // 断言 |
| 123 | assertEquals(1, statuses.size()); | 141 | assertEquals(1, statuses.size()); |
| 124 | assertTrue(statuses.get(0).getSuccess()); | 142 | assertTrue(statuses.get(0).getSuccess()); |
| 125 | assertEquals("DELIVERED", statuses.get(0).getErrorCode()); | 143 | assertEquals("DELIVERED", statuses.get(0).getErrorCode()); |
| 126 | assertEquals("用户接收成功", statuses.get(0).getErrorMsg()); | 144 | assertEquals("用户接收成功", statuses.get(0).getErrorMsg()); |
| 127 | assertEquals("13900000001", statuses.get(0).getMobile()); | 145 | assertEquals("13900000001", statuses.get(0).getMobile()); |
| 128 | - assertEquals(LocalDateTime.of(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime()); | 146 | + assertEquals(LocalDateTime.of(2017, 2, 2, 22, 23, 24), |
| 147 | + statuses.get(0).getReceiveTime()); | ||
| 129 | assertEquals("12345", statuses.get(0).getSerialNo()); | 148 | assertEquals("12345", statuses.get(0).getSerialNo()); |
| 130 | assertEquals(67890L, statuses.get(0).getLogId()); | 149 | assertEquals(67890L, statuses.get(0).getLogId()); |
| 131 | } | 150 | } |
| 132 | 151 | ||
| 133 | @Test | 152 | @Test |
| 134 | - public void testDoGetSmsTemplate() throws ClientException { | 153 | + public void testGetSmsTemplate() throws Throwable { |
| 135 | // 准备参数 | 154 | // 准备参数 |
| 136 | String apiTemplateId = randomString(); | 155 | String apiTemplateId = randomString(); |
| 137 | // mock 方法 | 156 | // mock 方法 |
| @@ -145,18 +164,12 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | @@ -145,18 +164,12 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | ||
| 145 | }))).thenReturn(response); | 164 | }))).thenReturn(response); |
| 146 | 165 | ||
| 147 | // 调用 | 166 | // 调用 |
| 148 | - SmsCommonResult<SmsTemplateRespDTO> result = smsClient.doGetSmsTemplate(apiTemplateId); | 167 | + SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId); |
| 149 | // 断言 | 168 | // 断言 |
| 150 | - assertEquals(response.getCode(), result.getApiCode()); | ||
| 151 | - assertEquals(response.getMessage(), result.getApiMsg()); | ||
| 152 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); | ||
| 153 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); | ||
| 154 | - assertEquals(response.getRequestId(), result.getApiRequestId()); | ||
| 155 | - // 断言结果 | ||
| 156 | - assertEquals(response.getTemplateCode(), result.getData().getId()); | ||
| 157 | - assertEquals(response.getTemplateContent(), result.getData().getContent()); | ||
| 158 | - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); | ||
| 159 | - assertEquals(response.getReason(), result.getData().getAuditReason()); | 169 | + assertEquals(response.getTemplateCode(), result.getId()); |
| 170 | + assertEquals(response.getTemplateContent(), result.getContent()); | ||
| 171 | + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus()); | ||
| 172 | + assertEquals(response.getReason(), result.getAuditReason()); | ||
| 160 | } | 173 | } |
| 161 | 174 | ||
| 162 | @Test | 175 | @Test |
| @@ -171,55 +184,4 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | @@ -171,55 +184,4 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | ||
| 171 | "未知审核状态(3)"); | 184 | "未知审核状态(3)"); |
| 172 | } | 185 | } |
| 173 | 186 | ||
| 174 | - @Test | ||
| 175 | - @SuppressWarnings("unchecked") | ||
| 176 | - public void testInvoke_throwable() throws ClientException { | ||
| 177 | - // 准备参数 | ||
| 178 | - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); | ||
| 179 | - // mock 方法 | ||
| 180 | - ClientException ex = new ClientException("isv.INVALID_PARAMETERS", "参数不正确", randomString()); | ||
| 181 | - when(client.getAcsResponse(any(AcsRequest.class))).thenThrow(ex); | ||
| 182 | - | ||
| 183 | - // 调用,并断言异常 | ||
| 184 | - SmsCommonResult<?> result = smsClient.invoke(request, null); | ||
| 185 | - // 断言 | ||
| 186 | - assertEquals(ex.getErrCode(), result.getApiCode()); | ||
| 187 | - assertEquals(ex.getErrMsg(), result.getApiMsg()); | ||
| 188 | - Assertions.assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR.getCode(), result.getCode()); | ||
| 189 | - Assertions.assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR.getMsg(), result.getMsg()); | ||
| 190 | - assertEquals(ex.getRequestId(), result.getApiRequestId()); | ||
| 191 | - } | ||
| 192 | - | ||
| 193 | - @Test | ||
| 194 | - public void testInvoke_success() throws ClientException { | ||
| 195 | - // 准备参数 | ||
| 196 | - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); | ||
| 197 | - Function<QuerySmsTemplateResponse, SmsTemplateRespDTO> responseConsumer = response -> { | ||
| 198 | - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); | ||
| 199 | - data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); | ||
| 200 | - data.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(response.getReason()); | ||
| 201 | - return data; | ||
| 202 | - }; | ||
| 203 | - // mock 方法 | ||
| 204 | - QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { | ||
| 205 | - o.setCode("OK"); | ||
| 206 | - o.setTemplateStatus(1); // 设置模板通过 | ||
| 207 | - }); | ||
| 208 | - when(client.getAcsResponse(any(AcsRequest.class))).thenReturn(response); | ||
| 209 | - | ||
| 210 | - // 调用 | ||
| 211 | - SmsCommonResult<SmsTemplateRespDTO> result = smsClient.invoke(request, responseConsumer); | ||
| 212 | - // 断言 | ||
| 213 | - assertEquals(response.getCode(), result.getApiCode()); | ||
| 214 | - assertEquals(response.getMessage(), result.getApiMsg()); | ||
| 215 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); | ||
| 216 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); | ||
| 217 | - assertEquals(response.getRequestId(), result.getApiRequestId()); | ||
| 218 | - // 断言结果 | ||
| 219 | - assertEquals(response.getTemplateCode(), result.getData().getId()); | ||
| 220 | - assertEquals(response.getTemplateContent(), result.getData().getContent()); | ||
| 221 | - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); | ||
| 222 | - assertEquals(response.getReason(), result.getData().getAuditReason()); | ||
| 223 | - } | ||
| 224 | - | ||
| 225 | } | 187 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 4 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 5 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 6 | -import org.junit.jupiter.api.Test; | ||
| 7 | -import org.mockito.InjectMocks; | ||
| 8 | - | ||
| 9 | -import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 10 | - | ||
| 11 | -/** | ||
| 12 | - * {@link AliyunSmsCodeMapping} 的单元测试 | ||
| 13 | - * | ||
| 14 | - * @author 芋道源码 | ||
| 15 | - */ | ||
| 16 | -public class AliyunSmsCodeMappingTest extends BaseMockitoUnitTest { | ||
| 17 | - | ||
| 18 | - @InjectMocks | ||
| 19 | - private AliyunSmsCodeMapping codeMapping; | ||
| 20 | - | ||
| 21 | - @Test | ||
| 22 | - public void testApply() { | ||
| 23 | - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply("OK")); | ||
| 24 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("MissingAccessKeyId")); | ||
| 25 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_NOT_EXISTS")); | ||
| 26 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_ABNORMAL")); | ||
| 27 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("isv.DAY_LIMIT_CONTROL")); | ||
| 28 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("isv.SMS_CONTENT_ILLEGAL")); | ||
| 29 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGN_ILLEGAL")); | ||
| 30 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SIGN_NAME_ILLEGAL")); | ||
| 31 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("isp.RAM_PERMISSION_DENY")); | ||
| 32 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.OUT_OF_SERVICE")); | ||
| 33 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.AMOUNT_NOT_ENOUGH")); | ||
| 34 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("isv.SMS_TEMPLATE_ILLEGAL")); | ||
| 35 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGNATURE_ILLEGAL")); | ||
| 36 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_PARAMETERS")); | ||
| 37 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_JSON_PARAM")); | ||
| 38 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("isv.MOBILE_NUMBER_ILLEGAL")); | ||
| 39 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("isv.TEMPLATE_MISSING_PARAMETERS")); | ||
| 40 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("isv.BUSINESS_LIMIT_CONTROL")); | ||
| 41 | - } | ||
| 42 | - | ||
| 43 | -} |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java
| 1 | package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; | 1 | package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.ReflectUtil; | 3 | import cn.hutool.core.util.ReflectUtil; |
| 4 | -import cn.hutool.core.util.StrUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 4 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 6 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 5 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 8 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 9 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 10 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 11 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 12 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 13 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| @@ -31,7 +28,6 @@ import java.util.List; | @@ -31,7 +28,6 @@ import java.util.List; | ||
| 31 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 28 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 32 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 29 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 33 | import static org.junit.jupiter.api.Assertions.*; | 30 | import static org.junit.jupiter.api.Assertions.*; |
| 34 | -import static org.junit.jupiter.api.Assertions.assertThrows; | ||
| 35 | import static org.mockito.ArgumentMatchers.argThat; | 31 | import static org.mockito.ArgumentMatchers.argThat; |
| 36 | import static org.mockito.Mockito.when; | 32 | import static org.mockito.Mockito.when; |
| 37 | 33 | ||
| @@ -78,7 +74,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -78,7 +74,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 78 | } | 74 | } |
| 79 | 75 | ||
| 80 | @Test | 76 | @Test |
| 81 | - public void testDoSendSms() throws Throwable { | 77 | + public void testDoSendSms_success() throws Throwable { |
| 82 | // 准备参数 | 78 | // 准备参数 |
| 83 | Long sendLogId = randomLongId(); | 79 | Long sendLogId = randomLongId(); |
| 84 | String mobile = randomString(); | 80 | String mobile = randomString(); |
| @@ -94,7 +90,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -94,7 +90,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 94 | o.setSendStatusSet(sendStatuses); | 90 | o.setSendStatusSet(sendStatuses); |
| 95 | SendStatus sendStatus = new SendStatus(); | 91 | SendStatus sendStatus = new SendStatus(); |
| 96 | sendStatuses[0] = sendStatus; | 92 | sendStatuses[0] = sendStatus; |
| 97 | - sendStatus.setCode(TencentSmsClient.API_SUCCESS_CODE); | 93 | + sendStatus.setCode(TencentSmsClient.API_CODE_SUCCESS); |
| 98 | sendStatus.setMessage("send success"); | 94 | sendStatus.setMessage("send success"); |
| 99 | sendStatus.setSerialNo(serialNo); | 95 | sendStatus.setSerialNo(serialNo); |
| 100 | }); | 96 | }); |
| @@ -109,20 +105,58 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -109,20 +105,58 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 109 | }))).thenReturn(response); | 105 | }))).thenReturn(response); |
| 110 | 106 | ||
| 111 | // 调用 | 107 | // 调用 |
| 112 | - SmsCommonResult<SmsSendRespDTO> result = smsClient.doSendSms(sendLogId, mobile, | ||
| 113 | - apiTemplateId, templateParams); | 108 | + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); |
| 114 | // 断言 | 109 | // 断言 |
| 110 | + assertTrue(result.getSuccess()); | ||
| 111 | + assertEquals(response.getRequestId(), result.getApiRequestId()); | ||
| 115 | assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode()); | 112 | assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode()); |
| 116 | assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg()); | 113 | assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg()); |
| 117 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); | ||
| 118 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); | 114 | + assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo()); |
| 115 | + } | ||
| 116 | + | ||
| 117 | + @Test | ||
| 118 | + public void testDoSendSms_fail() throws Throwable { | ||
| 119 | + // 准备参数 | ||
| 120 | + Long sendLogId = randomLongId(); | ||
| 121 | + String mobile = randomString(); | ||
| 122 | + String apiTemplateId = randomString(); | ||
| 123 | + List<KeyValue<String, Object>> templateParams = Lists.newArrayList( | ||
| 124 | + new KeyValue<>("1", 1234), new KeyValue<>("2", "login")); | ||
| 125 | + String requestId = randomString(); | ||
| 126 | + String serialNo = randomString(); | ||
| 127 | + // mock 方法 | ||
| 128 | + SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> { | ||
| 129 | + o.setRequestId(requestId); | ||
| 130 | + SendStatus[] sendStatuses = new SendStatus[1]; | ||
| 131 | + o.setSendStatusSet(sendStatuses); | ||
| 132 | + SendStatus sendStatus = new SendStatus(); | ||
| 133 | + sendStatuses[0] = sendStatus; | ||
| 134 | + sendStatus.setCode("ERROR"); | ||
| 135 | + sendStatus.setMessage("send success"); | ||
| 136 | + sendStatus.setSerialNo(serialNo); | ||
| 137 | + }); | ||
| 138 | + when(client.SendSms(argThat(request -> { | ||
| 139 | + assertEquals(mobile, request.getPhoneNumberSet()[0]); | ||
| 140 | + assertEquals(properties.getSignature(), request.getSignName()); | ||
| 141 | + assertEquals(apiTemplateId, request.getTemplateId()); | ||
| 142 | + assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)), | ||
| 143 | + toJsonString(request.getTemplateParamSet())); | ||
| 144 | + assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId")); | ||
| 145 | + return true; | ||
| 146 | + }))).thenReturn(response); | ||
| 147 | + | ||
| 148 | + // 调用 | ||
| 149 | + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); | ||
| 150 | + // 断言 | ||
| 151 | + assertFalse(result.getSuccess()); | ||
| 119 | assertEquals(response.getRequestId(), result.getApiRequestId()); | 152 | assertEquals(response.getRequestId(), result.getApiRequestId()); |
| 120 | - // 断言结果 | ||
| 121 | - assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getData().getSerialNo()); | 153 | + assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode()); |
| 154 | + assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg()); | ||
| 155 | + assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo()); | ||
| 122 | } | 156 | } |
| 123 | 157 | ||
| 124 | @Test | 158 | @Test |
| 125 | - public void testDoTParseSmsReceiveStatus() throws Throwable { | 159 | + public void testParseSmsReceiveStatus() { |
| 126 | // 准备参数 | 160 | // 准备参数 |
| 127 | String text = "[\n" + | 161 | String text = "[\n" + |
| 128 | " {\n" + | 162 | " {\n" + |
| @@ -139,7 +173,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -139,7 +173,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 139 | // mock 方法 | 173 | // mock 方法 |
| 140 | 174 | ||
| 141 | // 调用 | 175 | // 调用 |
| 142 | - List<SmsReceiveRespDTO> statuses = smsClient.doParseSmsReceiveStatus(text); | 176 | + List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text); |
| 143 | // 断言 | 177 | // 断言 |
| 144 | assertEquals(1, statuses.size()); | 178 | assertEquals(1, statuses.size()); |
| 145 | assertTrue(statuses.get(0).getSuccess()); | 179 | assertTrue(statuses.get(0).getSuccess()); |
| @@ -152,7 +186,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -152,7 +186,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 152 | } | 186 | } |
| 153 | 187 | ||
| 154 | @Test | 188 | @Test |
| 155 | - public void testDoGetSmsTemplate() throws Throwable { | 189 | + public void testGetSmsTemplate() throws Throwable { |
| 156 | // 准备参数 | 190 | // 准备参数 |
| 157 | Long apiTemplateId = randomLongId(); | 191 | Long apiTemplateId = randomLongId(); |
| 158 | String requestId = randomString(); | 192 | String requestId = randomString(); |
| @@ -173,50 +207,24 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -173,50 +207,24 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 173 | }))).thenReturn(response); | 207 | }))).thenReturn(response); |
| 174 | 208 | ||
| 175 | // 调用 | 209 | // 调用 |
| 176 | - SmsCommonResult<SmsTemplateRespDTO> result = smsClient.doGetSmsTemplate(apiTemplateId.toString()); | 210 | + SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId.toString()); |
| 177 | // 断言 | 211 | // 断言 |
| 178 | - assertEquals(TencentSmsClient.API_SUCCESS_CODE, result.getApiCode()); | ||
| 179 | - assertNull(result.getApiMsg()); | ||
| 180 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); | ||
| 181 | - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); | ||
| 182 | - assertEquals(response.getRequestId(), result.getApiRequestId()); | ||
| 183 | - // 断言结果 | ||
| 184 | - assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getData().getId()); | ||
| 185 | - assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getData().getContent()); | ||
| 186 | - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); | ||
| 187 | - assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getData().getAuditReason()); | ||
| 188 | - } | ||
| 189 | - | ||
| 190 | - @Test | ||
| 191 | - public void testConvertSuccessTemplateStatus() { | ||
| 192 | - testTemplateStatus(SmsTemplateAuditStatusEnum.SUCCESS, 0L); | ||
| 193 | - } | ||
| 194 | - | ||
| 195 | - @Test | ||
| 196 | - public void testConvertCheckingTemplateStatus() { | ||
| 197 | - testTemplateStatus(SmsTemplateAuditStatusEnum.CHECKING, 1L); | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | - @Test | ||
| 201 | - public void testConvertFailTemplateStatus() { | ||
| 202 | - testTemplateStatus(SmsTemplateAuditStatusEnum.FAIL, -1L); | 212 | + assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getId()); |
| 213 | + assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getContent()); | ||
| 214 | + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus()); | ||
| 215 | + assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getAuditReason()); | ||
| 203 | } | 216 | } |
| 204 | 217 | ||
| 205 | @Test | 218 | @Test |
| 206 | - public void testConvertUnknownTemplateStatus() { | ||
| 207 | - DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus(); | ||
| 208 | - templateStatus.setStatusCode(3L); | ||
| 209 | - Long templateId = randomLongId(); | ||
| 210 | - // 调用,并断言结果 | ||
| 211 | - assertThrows(IllegalStateException.class, () -> smsClient.convertTemplateStatusDTO(templateStatus), | ||
| 212 | - StrUtil.format("不能解析短信模版审核状态[3],模版id[{}]", templateId)); | ||
| 213 | - } | ||
| 214 | - | ||
| 215 | - private void testTemplateStatus(SmsTemplateAuditStatusEnum expected, Long value) { | ||
| 216 | - DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus(); | ||
| 217 | - templateStatus.setStatusCode(value); | ||
| 218 | - SmsTemplateRespDTO result = smsClient.convertTemplateStatusDTO(templateStatus); | ||
| 219 | - assertEquals(expected.getStatus(), result.getAuditStatus()); | 219 | + public void testConvertSmsTemplateAuditStatus() { |
| 220 | + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), | ||
| 221 | + smsClient.convertSmsTemplateAuditStatus(0)); | ||
| 222 | + assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), | ||
| 223 | + smsClient.convertSmsTemplateAuditStatus(1)); | ||
| 224 | + assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), | ||
| 225 | + smsClient.convertSmsTemplateAuditStatus(-1)); | ||
| 226 | + assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus(3), | ||
| 227 | + "未知审核状态(3)"); | ||
| 220 | } | 228 | } |
| 221 | 229 | ||
| 222 | } | 230 | } |
yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMappingTest.java deleted
| 1 | -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 4 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | ||
| 5 | -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 6 | -import org.junit.jupiter.api.Test; | ||
| 7 | -import org.mockito.InjectMocks; | ||
| 8 | - | ||
| 9 | -import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 10 | - | ||
| 11 | -/** | ||
| 12 | - * {@link TencentSmsCodeMapping} 的单元测试 | ||
| 13 | - * | ||
| 14 | - * @author : shiwp | ||
| 15 | - */ | ||
| 16 | -public class TencentSmsCodeMappingTest extends BaseMockitoUnitTest { | ||
| 17 | - | ||
| 18 | - @InjectMocks | ||
| 19 | - private TencentSmsCodeMapping codeMapping; | ||
| 20 | - | ||
| 21 | - @Test | ||
| 22 | - public void testApply() { | ||
| 23 | - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(TencentSmsClient.API_SUCCESS_CODE)); | ||
| 24 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("FailedOperation.ContainSensitiveWord")); | ||
| 25 | - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("FailedOperation.JsonParseFail")); | ||
| 26 | - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("MissingParameter.EmptyPhoneNumberSet")); | ||
| 27 | - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("LimitExceeded.PhoneNumberCountLimit")); | ||
| 28 | - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("FailedOperation.FailResolvePacket")); | ||
| 29 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("FailedOperation.InsufficientBalanceInSmsPackage")); | ||
| 30 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_MARKET_LIMIT_CONTROL, codeMapping.apply("FailedOperation.MarketingSendTimeConstraint")); | ||
| 31 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply("FailedOperation.PhoneNumberInBlacklist")); | ||
| 32 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("FailedOperation.SignatureIncorrectOrUnapproved")); | ||
| 33 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("FailedOperation.MissingTemplateToModify")); | ||
| 34 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("FailedOperation.TemplateIncorrectOrUnapproved")); | ||
| 35 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("InvalidParameterValue.IncorrectPhoneNumber")); | ||
| 36 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_APP_ID_INVALID, codeMapping.apply("InvalidParameterValue.SdkAppIdNotExist")); | ||
| 37 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("InvalidParameterValue.TemplateParameterLengthLimit")); | ||
| 38 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("InvalidParameterValue.TemplateParameterFormatError")); | ||
| 39 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberDailyLimit")); | ||
| 40 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberThirtySecondLimit")); | ||
| 41 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberOneHourLimit")); | ||
| 42 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("UnauthorizedOperation.RequestPermissionDeny")); | ||
| 43 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("FailedOperation.ForbidAddMarketingTemplates")); | ||
| 44 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("FailedOperation.NotEnterpriseCertification")); | ||
| 45 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("UnauthorizedOperation.IndividualUserMarketingSmsPermissionDeny")); | ||
| 46 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply("UnauthorizedOperation.RequestIpNotInWhitelist")); | ||
| 47 | - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("AuthFailure.SecretIdNotFound")); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | -} | ||
| 51 | \ No newline at end of file | 0 | \ No newline at end of file |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| @@ -82,6 +82,10 @@ public interface ErrorCodeConstants { | @@ -82,6 +82,10 @@ public interface ErrorCodeConstants { | ||
| 82 | // ========== 短信模板 1-002-012-000 ========== | 82 | // ========== 短信模板 1-002-012-000 ========== |
| 83 | ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在"); | 83 | ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在"); |
| 84 | ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_012_001, "已经存在编码为【{}】的短信模板"); | 84 | ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_012_001, "已经存在编码为【{}】的短信模板"); |
| 85 | + ErrorCode SMS_TEMPLATE_API_ERROR = new ErrorCode(1_002_012_002, "短信 API 模板调用失败,原因是:{}"); | ||
| 86 | + ErrorCode SMS_TEMPLATE_API_AUDIT_CHECKING = new ErrorCode(1_002_012_003, "短信 API 模版无法使用,原因:审批中"); | ||
| 87 | + ErrorCode SMS_TEMPLATE_API_AUDIT_FAIL = new ErrorCode(1_002_012_004, "短信 API 模版无法使用,原因:审批不通过,{}"); | ||
| 88 | + ErrorCode SMS_TEMPLATE_API_NOT_FOUND = new ErrorCode(1_002_012_005, "短信 API 模版无法使用,原因:模版不存在"); | ||
| 85 | 89 | ||
| 86 | // ========== 短信发送 1-002-013-000 ========== | 90 | // ========== 短信发送 1-002-013-000 ========== |
| 87 | ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在"); | 91 | ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在"); |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java
| @@ -63,12 +63,6 @@ public class SmsLogExcelVO { | @@ -63,12 +63,6 @@ public class SmsLogExcelVO { | ||
| 63 | @ExcelProperty("发送时间") | 63 | @ExcelProperty("发送时间") |
| 64 | private LocalDateTime sendTime; | 64 | private LocalDateTime sendTime; |
| 65 | 65 | ||
| 66 | - @ExcelProperty("发送结果的编码") | ||
| 67 | - private Integer sendCode; | ||
| 68 | - | ||
| 69 | - @ExcelProperty("发送结果的提示") | ||
| 70 | - private String sendMsg; | ||
| 71 | - | ||
| 72 | @ExcelProperty("短信 API 发送结果的编码") | 66 | @ExcelProperty("短信 API 发送结果的编码") |
| 73 | private String apiSendCode; | 67 | private String apiSendCode; |
| 74 | 68 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java
| @@ -52,12 +52,6 @@ public class SmsLogRespVO { | @@ -52,12 +52,6 @@ public class SmsLogRespVO { | ||
| 52 | @Schema(description = "发送时间") | 52 | @Schema(description = "发送时间") |
| 53 | private LocalDateTime sendTime; | 53 | private LocalDateTime sendTime; |
| 54 | 54 | ||
| 55 | - @Schema(description = "发送结果的编码", example = "0") | ||
| 56 | - private Integer sendCode; | ||
| 57 | - | ||
| 58 | - @Schema(description = "发送结果的提示", example = "成功") | ||
| 59 | - private String sendMsg; | ||
| 60 | - | ||
| 61 | @Schema(description = "短信 API 发送结果的编码", example = "SUCCESS") | 55 | @Schema(description = "短信 API 发送结果的编码", example = "SUCCESS") |
| 62 | private String apiSendCode; | 56 | private String apiSendCode; |
| 63 | 57 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java
| 1 | package cn.iocoder.yudao.module.system.dal.dataobject.sms; | 1 | package cn.iocoder.yudao.module.system.dal.dataobject.sms; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; | ||
| 4 | -import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; | ||
| 5 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 7 | -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; | 5 | +import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; |
| 6 | +import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; | ||
| 8 | import com.baomidou.mybatisplus.annotation.KeySequence; | 7 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 9 | import com.baomidou.mybatisplus.annotation.TableField; | 8 | import com.baomidou.mybatisplus.annotation.TableField; |
| 10 | import com.baomidou.mybatisplus.annotation.TableName; | 9 | import com.baomidou.mybatisplus.annotation.TableName; |
| @@ -116,19 +115,6 @@ public class SmsLogDO extends BaseDO { | @@ -116,19 +115,6 @@ public class SmsLogDO extends BaseDO { | ||
| 116 | */ | 115 | */ |
| 117 | private LocalDateTime sendTime; | 116 | private LocalDateTime sendTime; |
| 118 | /** | 117 | /** |
| 119 | - * 发送结果的编码 | ||
| 120 | - * | ||
| 121 | - * 枚举 {@link SmsFrameworkErrorCodeConstants} | ||
| 122 | - */ | ||
| 123 | - private Integer sendCode; | ||
| 124 | - /** | ||
| 125 | - * 发送结果的提示 | ||
| 126 | - * | ||
| 127 | - * 一般情况下,使用 {@link SmsFrameworkErrorCodeConstants} | ||
| 128 | - * 异常情况下,通过格式化 Exception 的提示存储 | ||
| 129 | - */ | ||
| 130 | - private String sendMsg; | ||
| 131 | - /** | ||
| 132 | * 短信 API 发送结果的编码 | 118 | * 短信 API 发送结果的编码 |
| 133 | * | 119 | * |
| 134 | * 由于第三方的错误码可能是字符串,所以使用 String 类型 | 120 | * 由于第三方的错误码可能是字符串,所以使用 String 类型 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java
| @@ -37,15 +37,15 @@ public interface SmsLogService { | @@ -37,15 +37,15 @@ public interface SmsLogService { | ||
| 37 | * 更新日志的发送结果 | 37 | * 更新日志的发送结果 |
| 38 | * | 38 | * |
| 39 | * @param id 日志编号 | 39 | * @param id 日志编号 |
| 40 | - * @param sendCode 发送结果的编码 | ||
| 41 | - * @param sendMsg 发送结果的提示 | 40 | + * @param success 发送是否成功 |
| 42 | * @param apiSendCode 短信 API 发送结果的编码 | 41 | * @param apiSendCode 短信 API 发送结果的编码 |
| 43 | * @param apiSendMsg 短信 API 发送失败的提示 | 42 | * @param apiSendMsg 短信 API 发送失败的提示 |
| 44 | * @param apiRequestId 短信 API 发送返回的唯一请求 ID | 43 | * @param apiRequestId 短信 API 发送返回的唯一请求 ID |
| 45 | * @param apiSerialNo 短信 API 发送返回的序号 | 44 | * @param apiSerialNo 短信 API 发送返回的序号 |
| 46 | */ | 45 | */ |
| 47 | - void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, | ||
| 48 | - String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo); | 46 | + void updateSmsSendResult(Long id, Boolean success, |
| 47 | + String apiSendCode, String apiSendMsg, | ||
| 48 | + String apiRequestId, String apiSerialNo); | ||
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * 更新日志的接收结果 | 51 | * 更新日志的接收结果 |
| @@ -56,7 +56,8 @@ public interface SmsLogService { | @@ -56,7 +56,8 @@ public interface SmsLogService { | ||
| 56 | * @param apiReceiveCode API 接收结果的编码 | 56 | * @param apiReceiveCode API 接收结果的编码 |
| 57 | * @param apiReceiveMsg API 接收结果的说明 | 57 | * @param apiReceiveMsg API 接收结果的说明 |
| 58 | */ | 58 | */ |
| 59 | - void updateSmsReceiveResult(Long id, Boolean success, LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg); | 59 | + void updateSmsReceiveResult(Long id, Boolean success, |
| 60 | + LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg); | ||
| 60 | 61 | ||
| 61 | /** | 62 | /** |
| 62 | * 获得短信日志分页 | 63 | * 获得短信日志分页 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.sms; | 1 | package cn.iocoder.yudao.module.system.service.sms; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; | 4 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; |
| 6 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; |
| 8 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsLogMapper; | 8 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsLogMapper; |
| 9 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 10 | import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; | 9 | import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; |
| 11 | import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; | 10 | import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; |
| 12 | import lombok.extern.slf4j.Slf4j; | 11 | import lombok.extern.slf4j.Slf4j; |
| @@ -55,13 +54,12 @@ public class SmsLogServiceImpl implements SmsLogService { | @@ -55,13 +54,12 @@ public class SmsLogServiceImpl implements SmsLogService { | ||
| 55 | } | 54 | } |
| 56 | 55 | ||
| 57 | @Override | 56 | @Override |
| 58 | - public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, | 57 | + public void updateSmsSendResult(Long id, Boolean success, |
| 59 | String apiSendCode, String apiSendMsg, | 58 | String apiSendCode, String apiSendMsg, |
| 60 | String apiRequestId, String apiSerialNo) { | 59 | String apiRequestId, String apiSerialNo) { |
| 61 | - SmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? | ||
| 62 | - SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; | ||
| 63 | - smsLogMapper.updateById(SmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()) | ||
| 64 | - .sendTime(LocalDateTime.now()).sendCode(sendCode).sendMsg(sendMsg) | 60 | + SmsSendStatusEnum sendStatus = success ? SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; |
| 61 | + smsLogMapper.updateById(SmsLogDO.builder().id(id) | ||
| 62 | + .sendStatus(sendStatus.getStatus()).sendTime(LocalDateTime.now()) | ||
| 65 | .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) | 63 | .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) |
| 66 | .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); | 64 | .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); |
| 67 | } | 65 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.sms; | 1 | package cn.iocoder.yudao.module.system.service.sms; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.exceptions.ExceptionUtil; | ||
| 4 | import cn.hutool.core.lang.Assert; | 5 | import cn.hutool.core.lang.Assert; |
| 5 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 7 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| @@ -8,7 +9,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | @@ -8,7 +9,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 8 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 9 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 9 | import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; | 10 | import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; |
| 10 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; | 11 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; |
| 11 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 12 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 12 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 13 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 13 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 14 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | 14 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; |
| @@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; | @@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; | ||
| 19 | import cn.iocoder.yudao.module.system.service.member.MemberService; | 19 | import cn.iocoder.yudao.module.system.service.member.MemberService; |
| 20 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; | 20 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 21 | import com.google.common.annotations.VisibleForTesting; | 21 | import com.google.common.annotations.VisibleForTesting; |
| 22 | +import lombok.extern.slf4j.Slf4j; | ||
| 22 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
| 23 | 24 | ||
| 24 | import javax.annotation.Resource; | 25 | import javax.annotation.Resource; |
| @@ -35,6 +36,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -35,6 +36,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 35 | * @author 芋道源码 | 36 | * @author 芋道源码 |
| 36 | */ | 37 | */ |
| 37 | @Service | 38 | @Service |
| 39 | +@Slf4j | ||
| 38 | public class SmsSendServiceImpl implements SmsSendService { | 40 | public class SmsSendServiceImpl implements SmsSendService { |
| 39 | 41 | ||
| 40 | @Resource | 42 | @Resource |
| @@ -158,11 +160,17 @@ public class SmsSendServiceImpl implements SmsSendService { | @@ -158,11 +160,17 @@ public class SmsSendServiceImpl implements SmsSendService { | ||
| 158 | SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId()); | 160 | SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId()); |
| 159 | Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); | 161 | Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); |
| 160 | // 发送短信 | 162 | // 发送短信 |
| 161 | - SmsCommonResult<SmsSendRespDTO> sendResult = smsClient.sendSms(message.getLogId(), message.getMobile(), | ||
| 162 | - message.getApiTemplateId(), message.getTemplateParams()); | ||
| 163 | - smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), | ||
| 164 | - sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(), | ||
| 165 | - sendResult.getData() != null ? sendResult.getData().getSerialNo() : null); | 163 | + try { |
| 164 | + SmsSendRespDTO sendResponse = smsClient.sendSms(message.getLogId(), message.getMobile(), | ||
| 165 | + message.getApiTemplateId(), message.getTemplateParams()); | ||
| 166 | + smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(), | ||
| 167 | + sendResponse.getApiCode(), sendResponse.getApiMsg(), | ||
| 168 | + sendResponse.getApiRequestId(), sendResponse.getSerialNo()); | ||
| 169 | + } catch (Throwable ex) { | ||
| 170 | + log.error("[doSendSms][发送短信异常,日志编号({})]", message.getLogId(), ex); | ||
| 171 | + smsLogService.updateSmsSendResult(message.getLogId(), false, | ||
| 172 | + "EXCEPTION", ExceptionUtil.getRootCauseMessage(ex), null, null); | ||
| 173 | + } | ||
| 166 | } | 174 | } |
| 167 | 175 | ||
| 168 | @Override | 176 | @Override |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.sms; | 1 | package cn.iocoder.yudao.module.system.service.sms; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.exceptions.ExceptionUtil; | ||
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.hutool.core.util.ReUtil; | 5 | import cn.hutool.core.util.ReUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; | 9 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; |
| 8 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| 11 | +import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | ||
| 10 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; | 12 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; |
| 11 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; | 13 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; |
| 12 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; | 14 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; |
| @@ -21,11 +23,11 @@ import lombok.extern.slf4j.Slf4j; | @@ -21,11 +23,11 @@ import lombok.extern.slf4j.Slf4j; | ||
| 21 | import org.springframework.cache.annotation.CacheEvict; | 23 | import org.springframework.cache.annotation.CacheEvict; |
| 22 | import org.springframework.cache.annotation.Cacheable; | 24 | import org.springframework.cache.annotation.Cacheable; |
| 23 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
| 24 | -import org.springframework.util.Assert; | ||
| 25 | 26 | ||
| 26 | import javax.annotation.Resource; | 27 | import javax.annotation.Resource; |
| 27 | import java.util.List; | 28 | import java.util.List; |
| 28 | import java.util.Map; | 29 | import java.util.Map; |
| 30 | +import java.util.Objects; | ||
| 29 | import java.util.regex.Pattern; | 31 | import java.util.regex.Pattern; |
| 30 | 32 | ||
| 31 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 33 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -171,9 +173,24 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { | @@ -171,9 +173,24 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { | ||
| 171 | // 获得短信模板 | 173 | // 获得短信模板 |
| 172 | SmsClient smsClient = smsChannelService.getSmsClient(channelId); | 174 | SmsClient smsClient = smsChannelService.getSmsClient(channelId); |
| 173 | Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); | 175 | Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); |
| 174 | - SmsCommonResult<SmsTemplateRespDTO> templateResult = smsClient.getSmsTemplate(apiTemplateId); | ||
| 175 | - // 校验短信模板是否正确 | ||
| 176 | - templateResult.checkError(); | 176 | + SmsTemplateRespDTO template; |
| 177 | + try { | ||
| 178 | + template = smsClient.getSmsTemplate(apiTemplateId); | ||
| 179 | + } catch (Throwable ex) { | ||
| 180 | + throw exception(SMS_TEMPLATE_API_ERROR, ExceptionUtil.getRootCauseMessage(ex)); | ||
| 181 | + } | ||
| 182 | + // 校验短信模版 | ||
| 183 | + if (template == null) { | ||
| 184 | + throw exception(SMS_TEMPLATE_API_NOT_FOUND); | ||
| 185 | + } | ||
| 186 | + if (Objects.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.CHECKING.getStatus())) { | ||
| 187 | + throw exception(SMS_TEMPLATE_API_AUDIT_CHECKING); | ||
| 188 | + } | ||
| 189 | + if (Objects.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.FAIL.getStatus())) { | ||
| 190 | + throw exception(SMS_TEMPLATE_API_AUDIT_FAIL, template.getAuditReason()); | ||
| 191 | + } | ||
| 192 | + Assert.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), | ||
| 193 | + String.format("短信模板(%s) 审核状态(%d) 不正确", apiTemplateId, template.getAuditStatus())); | ||
| 177 | } | 194 | } |
| 178 | 195 | ||
| 179 | @Override | 196 | @Override |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.service.sms; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.service.sms; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.map.MapUtil; | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 5 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 8 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 7 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| @@ -172,22 +171,20 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest { | @@ -172,22 +171,20 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest { | ||
| 172 | smsLogMapper.insert(dbSmsLog); | 171 | smsLogMapper.insert(dbSmsLog); |
| 173 | // 准备参数 | 172 | // 准备参数 |
| 174 | Long id = dbSmsLog.getId(); | 173 | Long id = dbSmsLog.getId(); |
| 175 | - Integer sendCode = randomInteger(); | ||
| 176 | - String sendMsg = randomString(); | 174 | + Boolean success = randomBoolean(); |
| 177 | String apiSendCode = randomString(); | 175 | String apiSendCode = randomString(); |
| 178 | String apiSendMsg = randomString(); | 176 | String apiSendMsg = randomString(); |
| 179 | String apiRequestId = randomString(); | 177 | String apiRequestId = randomString(); |
| 180 | String apiSerialNo = randomString(); | 178 | String apiSerialNo = randomString(); |
| 181 | 179 | ||
| 182 | // 调用 | 180 | // 调用 |
| 183 | - smsLogService.updateSmsSendResult(id, sendCode, sendMsg, | 181 | + smsLogService.updateSmsSendResult(id, success, |
| 184 | apiSendCode, apiSendMsg, apiRequestId, apiSerialNo); | 182 | apiSendCode, apiSendMsg, apiRequestId, apiSerialNo); |
| 185 | // 断言 | 183 | // 断言 |
| 186 | dbSmsLog = smsLogMapper.selectById(id); | 184 | dbSmsLog = smsLogMapper.selectById(id); |
| 187 | - assertEquals(CommonResult.isSuccess(sendCode) ? SmsSendStatusEnum.SUCCESS.getStatus() | ||
| 188 | - : SmsSendStatusEnum.FAILURE.getStatus(), dbSmsLog.getSendStatus()); | 185 | + assertEquals(success ? SmsSendStatusEnum.SUCCESS.getStatus() : SmsSendStatusEnum.FAILURE.getStatus(), |
| 186 | + dbSmsLog.getSendStatus()); | ||
| 189 | assertNotNull(dbSmsLog.getSendTime()); | 187 | assertNotNull(dbSmsLog.getSendTime()); |
| 190 | - assertEquals(sendMsg, dbSmsLog.getSendMsg()); | ||
| 191 | assertEquals(apiSendCode, dbSmsLog.getApiSendCode()); | 188 | assertEquals(apiSendCode, dbSmsLog.getApiSendCode()); |
| 192 | assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg()); | 189 | assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg()); |
| 193 | assertEquals(apiRequestId, dbSmsLog.getApiRequestId()); | 190 | assertEquals(apiRequestId, dbSmsLog.getApiRequestId()); |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java
| @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; | @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 7 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; | 7 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; |
| 8 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; | 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; |
| 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; | 9 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; |
| 11 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | 10 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| @@ -244,15 +243,14 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { | @@ -244,15 +243,14 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 244 | 243 | ||
| 245 | @Test | 244 | @Test |
| 246 | @SuppressWarnings("unchecked") | 245 | @SuppressWarnings("unchecked") |
| 247 | - public void testDoSendSms() { | 246 | + public void testDoSendSms() throws Throwable { |
| 248 | // 准备参数 | 247 | // 准备参数 |
| 249 | SmsSendMessage message = randomPojo(SmsSendMessage.class); | 248 | SmsSendMessage message = randomPojo(SmsSendMessage.class); |
| 250 | // mock SmsClientFactory 的方法 | 249 | // mock SmsClientFactory 的方法 |
| 251 | SmsClient smsClient = spy(SmsClient.class); | 250 | SmsClient smsClient = spy(SmsClient.class); |
| 252 | when(smsChannelService.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient); | 251 | when(smsChannelService.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient); |
| 253 | // mock SmsClient 的方法 | 252 | // mock SmsClient 的方法 |
| 254 | - SmsCommonResult<SmsSendRespDTO> sendResult = randomPojo(SmsCommonResult.class, SmsSendRespDTO.class); | ||
| 255 | - sendResult.setData(randomPojo(SmsSendRespDTO.class)); | 253 | + SmsSendRespDTO sendResult = randomPojo(SmsSendRespDTO.class); |
| 256 | when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()), | 254 | when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()), |
| 257 | eq(message.getTemplateParams()))).thenReturn(sendResult); | 255 | eq(message.getTemplateParams()))).thenReturn(sendResult); |
| 258 | 256 | ||
| @@ -260,8 +258,8 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { | @@ -260,8 +258,8 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 260 | smsService.doSendSms(message); | 258 | smsService.doSendSms(message); |
| 261 | // 断言 | 259 | // 断言 |
| 262 | verify(smsLogService).updateSmsSendResult(eq(message.getLogId()), | 260 | verify(smsLogService).updateSmsSendResult(eq(message.getLogId()), |
| 263 | - eq(sendResult.getCode()), eq(sendResult.getMsg()), eq(sendResult.getApiCode()), | ||
| 264 | - eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getData().getSerialNo())); | 261 | + eq(sendResult.getSuccess()), eq(sendResult.getApiCode()), |
| 262 | + eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getSerialNo())); | ||
| 265 | } | 263 | } |
| 266 | 264 | ||
| 267 | @Test | 265 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java
| 1 | package cn.iocoder.yudao.module.system.service.sms; | 1 | package cn.iocoder.yudao.module.system.service.sms; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 5 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 6 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 8 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; | 7 | import cn.iocoder.yudao.framework.sms.core.client.SmsClient; |
| 9 | -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; | ||
| 10 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; | 8 | import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; |
| 9 | +import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | ||
| 11 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 10 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 12 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; | 11 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; |
| 13 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; | 12 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; |
| @@ -65,7 +64,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | @@ -65,7 +64,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | ||
| 65 | 64 | ||
| 66 | @Test | 65 | @Test |
| 67 | @SuppressWarnings("unchecked") | 66 | @SuppressWarnings("unchecked") |
| 68 | - public void testCreateSmsTemplate_success() { | 67 | + public void testCreateSmsTemplate_success() throws Throwable { |
| 69 | // 准备参数 | 68 | // 准备参数 |
| 70 | SmsTemplateCreateReqVO reqVO = randomPojo(SmsTemplateCreateReqVO.class, o -> { | 69 | SmsTemplateCreateReqVO reqVO = randomPojo(SmsTemplateCreateReqVO.class, o -> { |
| 71 | o.setContent("正在进行登录操作{operation},您的验证码是{code}"); | 70 | o.setContent("正在进行登录操作{operation},您的验证码是{code}"); |
| @@ -80,8 +79,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | @@ -80,8 +79,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | ||
| 80 | when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); | 79 | when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); |
| 81 | // mock 获得 API 短信模板成功 | 80 | // mock 获得 API 短信模板成功 |
| 82 | when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); | 81 | when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); |
| 83 | - when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class, | ||
| 84 | - o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode()))); | 82 | + when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn( |
| 83 | + randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()))); | ||
| 85 | 84 | ||
| 86 | // 调用 | 85 | // 调用 |
| 87 | Long smsTemplateId = smsTemplateService.createSmsTemplate(reqVO); | 86 | Long smsTemplateId = smsTemplateService.createSmsTemplate(reqVO); |
| @@ -96,7 +95,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | @@ -96,7 +95,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | ||
| 96 | 95 | ||
| 97 | @Test | 96 | @Test |
| 98 | @SuppressWarnings("unchecked") | 97 | @SuppressWarnings("unchecked") |
| 99 | - public void testUpdateSmsTemplate_success() { | 98 | + public void testUpdateSmsTemplate_success() throws Throwable { |
| 100 | // mock 数据 | 99 | // mock 数据 |
| 101 | SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); | 100 | SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); |
| 102 | smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据 | 101 | smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据 |
| @@ -115,8 +114,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | @@ -115,8 +114,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { | ||
| 115 | when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); | 114 | when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); |
| 116 | // mock 获得 API 短信模板成功 | 115 | // mock 获得 API 短信模板成功 |
| 117 | when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); | 116 | when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); |
| 118 | - when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class, | ||
| 119 | - o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode()))); | 117 | + when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn( |
| 118 | + randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()))); | ||
| 120 | 119 | ||
| 121 | // 调用 | 120 | // 调用 |
| 122 | smsTemplateService.updateSmsTemplate(reqVO); | 121 | smsTemplateService.updateSmsTemplate(reqVO); |