diff --git a/src/main/java/cn/iocoder/dashboard/common/core/KeyValue.java b/src/main/java/cn/iocoder/dashboard/common/core/KeyValue.java new file mode 100644 index 000000000..57fe08b5a --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/common/core/KeyValue.java @@ -0,0 +1,20 @@ +package cn.iocoder.dashboard.common.core; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Key Value 的键值对 + * + * @author 芋道源码 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class KeyValue { + + private K key; + private V value; + +} diff --git a/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java b/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java index 73b4c7a76..0a56d334a 100644 --- a/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java +++ b/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java @@ -8,6 +8,7 @@ import lombok.Data; import org.springframework.util.Assert; import java.io.Serializable; +import java.util.Objects; /** * 通用返回 @@ -67,9 +68,13 @@ public class CommonResult implements Serializable { return result; } + public static boolean isSuccess(Integer code) { + return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode()); + } + @JsonIgnore // 避免 jackson 序列化 public boolean isSuccess() { - return GlobalErrorCodeConstants.SUCCESS.getCode().equals(code); + return isSuccess(GlobalErrorCodeConstants.SUCCESS.getCode()); } @JsonIgnore // 避免 jackson 序列化 diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java index 5028e1b0f..f343b540f 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java @@ -1,10 +1,11 @@ package cn.iocoder.dashboard.framework.sms.core.client; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; import javax.servlet.ServletRequest; -import java.util.Map; +import java.util.List; /** * 短信客户端接口 @@ -24,13 +25,13 @@ public interface SmsClient { /** * 发送消息 * - * @param sendLogId 发送日志编号 + * @param logId 日志编号 * @param mobile 手机号 * @param apiTemplateId 短信 API 的模板编号 * @param templateParams 短信模板参数 * @return 短信发送结果 */ - SmsCommonResult send(Long sendLogId, String mobile, String apiTemplateId, Map templateParams); + SmsCommonResult send(Long logId, String mobile, String apiTemplateId, List> templateParams); // TODO FROM 芋艿 to ZZF:是不是可以改成意图更明确的解析返回结果,例如说 parseXXXX /** diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java index 0f6777a3f..c3f6b51ae 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.framework.sms.core.client.dto; import lombok.Data; /** - * 短信发送响应 DTO + * 短信发送 Response DTO * * @author 芋道源码 */ diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java index 1c2dce0e6..6e334cf0a 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java @@ -1,13 +1,14 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl; +import cn.iocoder.dashboard.common.core.KeyValue; +import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; -import java.util.Map; +import java.util.List; /** * 短信客户端抽象类 @@ -67,16 +68,16 @@ public abstract class AbstractSmsClient implements SmsClient { } @Override - public final SmsCommonResult send(Long sendLogId, String mobile, - String apiTemplateId, Map templateParams) { + public final SmsCommonResult send(Long logId, String mobile, + String apiTemplateId, List> templateParams) { // 执行短信发送 SmsCommonResult result; try { - result = doSend(sendLogId, mobile, apiTemplateId, templateParams); + result = doSend(logId, mobile, apiTemplateId, templateParams); } catch (Throwable ex) { // 打印异常日志 log.error("[send][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]", - sendLogId, mobile, apiTemplateId, templateParams, ex); + logId, mobile, apiTemplateId, templateParams, ex); // 封装返回 return SmsCommonResult.error(ex); } @@ -93,6 +94,7 @@ public abstract class AbstractSmsClient implements SmsClient { * @return 短信发送结果 */ protected abstract SmsCommonResult doSend(Long sendLogId, String mobile, - String apiTemplateId, Map templateParams) throws Throwable; + String apiTemplateId, List> templateParams) + throws Throwable; } diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java index 4dbaffbf0..acc8a0193 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java @@ -3,12 +3,14 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; +import cn.iocoder.dashboard.util.collection.MapUtils; import cn.iocoder.dashboard.util.json.JsonUtils; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; @@ -60,14 +62,14 @@ public class AliyunSmsClient extends AbstractSmsClient { @Override protected SmsCommonResult doSend(Long sendLogId, String mobile, - String apiTemplateId, Map templateParams) throws Throwable { + String apiTemplateId, List> templateParams) { // 构建参数 SendSmsRequest request = new SendSmsRequest(); request.setSysMethod(MethodType.POST); request.setPhoneNumbers(mobile); request.setSignName(properties.getSignature()); request.setTemplateCode(apiTemplateId); - request.setTemplateParam(JsonUtils.toJsonString(templateParams)); + request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); request.setOutId(String.valueOf(sendLogId)); try { diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java index d11be8c1b..8a804de0c 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java @@ -1,6 +1,7 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; import cn.iocoder.dashboard.common.exception.ErrorCode; +import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; @@ -15,7 +16,7 @@ public class AliyunSmsCodeMapping implements SmsCodeMapping { @Override public ErrorCode apply(String apiCode) { switch (apiCode) { - case "OK": return null; + case "OK": return GlobalErrorCodeConstants.SUCCESS; case "MissingAccessKeyId": return SMS_CHANNEL_API_KEY_MISSING; case "isp.RAM_PERMISSION_DENY": return SMS_CHANNEL_PERMISSION_DENY; case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR; diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java index 503aa32d5..249d8c481 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java @@ -6,6 +6,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail; import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; @@ -65,7 +66,7 @@ public class YunpianSmsClient extends AbstractSmsClient { @Override protected SmsCommonResult doSend(Long sendLogId, String mobile, - String apiTemplateId, Map templateParams) throws Throwable { + String apiTemplateId, List> templateParams) throws Throwable { // 构建参数 Map request = new HashMap<>(); request.put(YunpianConstant.APIKEY, properties.getApiKey()); @@ -89,13 +90,13 @@ public class YunpianSmsClient extends AbstractSmsClient { data, codeMapping); } - private static String formatTplValue(Map templateParams) { + private static String formatTplValue(List> templateParams) { if (CollUtil.isEmpty(templateParams)) { return ""; } // 参考 https://www.yunpian.com/official/document/sms/zh_cn/introduction_demos_encode_sample 格式化 StringJoiner joiner = new StringJoiner("&"); - templateParams.forEach((key, value) -> joiner.add(String.format("#%s#=%s", key, URLUtil.encode(String.valueOf(value))))); + templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), URLUtil.encode(String.valueOf(param.getValue()))))); return joiner.toString(); } diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java index f0cbb762f..741410944 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java @@ -12,7 +12,6 @@ import cn.iocoder.dashboard.common.exception.ErrorCode; public interface SmsFrameworkErrorCodeConstants { // ========== 渠道相关 2001000100 ========== - ErrorCode SMS_CHANNEL_CLIENT_NOT_EXISTS = new ErrorCode(2001000100, "短信渠道的客户端不存在"); ErrorCode SMS_CHANNEL_API_KEY_MISSING = new ErrorCode(2001000101, "API Key 不存在"); ErrorCode SMS_CHANNEL_PERMISSION_DENY = new ErrorCode(2001000102, "没有发送短信的权限"); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java index 415e47405..3d6ccc575 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java @@ -4,7 +4,6 @@ import cn.iocoder.dashboard.common.pojo.CommonResult; import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService; import io.swagger.annotations.Api; @@ -13,7 +12,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import java.util.List; import static cn.iocoder.dashboard.common.pojo.CommonResult.success; @@ -31,12 +29,6 @@ public class SmsChannelController { return success(service.pageSmsChannels(reqVO)); } - @ApiOperation("获取渠道枚举") - @GetMapping("/list/channel-enum") - public CommonResult> getChannelEnums() { - return success(service.getSmsChannelEnums()); - } - @ApiOperation("添加消息渠道") @PostMapping("/create") public CommonResult add(@Validated @RequestBody SmsChannelCreateReqVO reqVO) { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelEnumRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelEnumRespVO.java deleted file mode 100644 index cb156781d..000000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelEnumRespVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.dashboard.modules.system.controller.sms.vo.resp; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - - -@ApiModel("用户分页 Request VO") -@Data -@NoArgsConstructor -@EqualsAndHashCode -public class SmsChannelEnumRespVO implements Serializable { - - private String code; - - private String name; - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java index 43d72b471..c8a0f7591 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java @@ -1,10 +1,8 @@ package cn.iocoder.dashboard.modules.system.convert.sms; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO; import org.mapstruct.Mapper; @@ -21,8 +19,6 @@ public interface SmsChannelConvert { SysSmsChannelDO convert(SysUserUpdateReqVO bean); - List convertEnum(List bean); - List convert(List bean); List convertProperty(List list); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsChannelDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsChannelDO.java index 4bca7e517..7b0b3f072 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsChannelDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsChannelDO.java @@ -6,16 +6,18 @@ import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.ToString; /** - * 短信渠道 + * 短信渠道 DO * * @author zzf * @since 2021-01-25 */ -@TableName(value = "sms_channel", autoResultMap = true) +@TableName(value = "sys_sms_channel", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class SysSmsChannelDO extends BaseDO { /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsSendLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java similarity index 76% rename from src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsSendLogDO.java rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java index 53e725634..44d0da639 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsSendLogDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java @@ -2,28 +2,30 @@ package cn.iocoder.dashboard.modules.system.dal.dataobject.sms; import cn.iocoder.dashboard.common.enums.UserTypeEnum; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; import java.util.Date; import java.util.Map; /** - * 短信发送日志 + * 短信日志 DO * * @author zzf * @since 2021-01-25 */ -@TableName(value = "sms_send_log", autoResultMap = true) +@TableName(value = "sys_sms_log", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @AllArgsConstructor @NoArgsConstructor @Builder -public class SysSmsSendLogDO extends BaseDO { +public class SysSmsLogDO extends BaseDO { /** * 自增编号 @@ -48,7 +50,7 @@ public class SysSmsSendLogDO extends BaseDO { // ========= 模板相关字段 ========= /** - * 短信模板编号 + * 模板编号 * * 关联 {@link SysSmsTemplateDO#getId()} */ @@ -70,8 +72,9 @@ public class SysSmsSendLogDO extends BaseDO { */ private String templateContent; /** - * 基于 {@link SysSmsTemplateDO#getParams()} 输入后的内容 + * 基于 {@link SysSmsTemplateDO#getParams()} 输入后的参数 */ + @TableField(typeHandler = JacksonTypeHandler.class) private Map templateParams; /** * 短信 API 的模板编号 @@ -106,32 +109,32 @@ public class SysSmsSendLogDO extends BaseDO { */ private Integer sendStatus; /** - * 时间发送时间 + * 发送时间 */ private Date sendTime; /** - * 发送失败的类型 + * 发送结果的编码 * - * 枚举 {@link SmsSendFailureTypeEnum#getType()} + * 枚举 {@link SmsFrameworkErrorCodeConstants} */ - private Integer sendFailureType; + private Integer sendCode; /** - * 发送失败的提示 + * 发送结果的提示 * - * 一般情况下,使用 {@link SmsSendFailureTypeEnum#getMsg()} + * 一般情况下,使用 {@link SmsFrameworkErrorCodeConstants} * 异常情况下,通过格式化 Exception 的提示存储 */ - private String sendFailureMsg; + private String sendMsg; /** - * 短信 API 发送失败的类型 + * 短信 API 发送结果的编码 * * 由于第三方的错误码可能是字符串,所以使用 String 类型 */ - private String apiSendFailureType; + private String apiSendCode; /** * 短信 API 发送失败的提示 */ - private String apiSendFailureMsg; + private String apiSendMsg; /** * 短信 API 发送返回的唯一请求 ID * @@ -147,9 +150,9 @@ public class SysSmsSendLogDO extends BaseDO { // ========= 接收相关字段 ========= - /** - * 是否获取过结果[0否 1是] - */ - private Integer gotResult; +// /** +// * 是否获取过结果[0否 1是] +// */ +// private Integer gotResult; } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java index ba2b9940e..9316358df 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java @@ -8,18 +8,20 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.ToString; import java.util.List; /** - * 短信模板 + * 短信模板 DO * * @author zzf * @since 2021-01-25 */ +@TableName(value = "sys_sms_template", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) -@TableName(value = "sms_template", autoResultMap = true) +@ToString(callSuper = true) public class SysSmsTemplateDO extends BaseDO { /** @@ -46,11 +48,11 @@ public class SysSmsTemplateDO extends BaseDO { */ private String code; /** - * 名称 + * 模板名称 */ private String name; /** - * 内容 + * 模板内容 * * 内容的参数,使用 {} 包括,例如说 {name} */ diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsSendLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java similarity index 73% rename from src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsSendLogMapper.java rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java index 74d713d48..2255c444e 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsSendLogMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java @@ -1,9 +1,9 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.sms; import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsSendLogDO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; import org.apache.ibatis.annotations.Mapper; @Mapper -public interface SysSmsSendLogMapper extends BaseMapperX { +public interface SysSmsLogMapper extends BaseMapperX { } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SysSmsSendStatusEnum.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SysSmsSendStatusEnum.java index 083b11c98..1d505ee02 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SysSmsSendStatusEnum.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SysSmsSendStatusEnum.java @@ -16,6 +16,7 @@ public enum SysSmsSendStatusEnum { INIT(0), // 初始化 SUCCESS(10), // 发送成功 FAILURE(20), // 发送失败 + IGNORE(30), // 忽略,即不发送 ; private final int status; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java index 40cc80ba5..9bb30514a 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java @@ -1,10 +1,11 @@ package cn.iocoder.dashboard.modules.system.mq.message.sms; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage; import lombok.Data; import javax.validation.constraints.NotNull; -import java.util.Map; +import java.util.List; /** * 短信发送消息 @@ -15,10 +16,10 @@ import java.util.Map; public class SysSmsSendMessage implements StreamMessage { /** - * 发送日志编号 + * 短信日志编号 */ - @NotNull(message = "发送日志编号不能为空") - private Long sendLogId; + @NotNull(message = "短信日志编号不能为空") + private Long logId; /** * 手机号 */ @@ -37,7 +38,7 @@ public class SysSmsSendMessage implements StreamMessage { /** * 短信模板参数 */ - private Map templateParams; + private List> templateParams; @Override public String getStreamKey() { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java index 257de549c..8e72bcf38 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java @@ -1,5 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.producer.sms; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage; import lombok.extern.slf4j.Slf4j; @@ -7,7 +8,7 @@ import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; -import java.util.Map; +import java.util.List; /** * 短信发送流消息监听器 @@ -25,16 +26,15 @@ public class SysSmsProducer { /** * 发送短信 Message * - * @param sendLogId 发送日志编号 + * @param logId 短信日志编号 * @param mobile 手机号 * @param channelId 渠道编号 * @param apiTemplateId 短信模板编号 * @param templateParams 短信模板参数 - * @param sendLogId 发送日志编号 */ - public void sendSmsSendMessage(Long sendLogId, String mobile, - Long channelId, String apiTemplateId, Map templateParams) { - SysSmsSendMessage message = new SysSmsSendMessage().setSendLogId(sendLogId).setMobile(mobile); + public void sendSmsSendMessage(Long logId, String mobile, + Long channelId, String apiTemplateId, List> templateParams) { + SysSmsSendMessage message = new SysSmsSendMessage().setLogId(logId).setMobile(mobile); message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams); RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelService.java index e720e363f..142812b3c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelService.java @@ -3,11 +3,8 @@ package cn.iocoder.dashboard.modules.system.service.sms; import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO; -import java.util.List; - /** * 短信渠道Service接口 * @@ -17,9 +14,9 @@ import java.util.List; public interface SysSmsChannelService { /** - * 初始化短信渠道并缓存短信模板信息 + * 初始化短信客户端 */ - void initSmsClientAndCacheSmsTemplate(); + void initSmsClients(); /** * 分页查询短信渠道信息 @@ -37,11 +34,4 @@ public interface SysSmsChannelService { */ Long createSmsChannel(SmsChannelCreateReqVO reqVO); - /** - * 获取短信渠道枚举/渠道编码 - * - * @return 短信渠道枚举/渠道编码 - */ - List getSmsChannelEnums(); - } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java new file mode 100644 index 000000000..fd04a62b5 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java @@ -0,0 +1,44 @@ +package cn.iocoder.dashboard.modules.system.service.sms; + +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; + +import java.util.Map; + +/** + * 短信日志服务接口 + * + * @author zzf + * @date 13:48 2021/3/2 + */ +public interface SysSmsLogService { + + /** + * 创建短信日志 + * + * @param mobile 手机号 + * @param userId 用户编号 + * @param userType 用户类型 + * @param isSend 是否发送 + * @param template 短信模板 + * @param templateContent 短信内容 + * @param templateParams 短信参数 + * @return 发送日志编号 + */ + Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend, + SysSmsTemplateDO template, String templateContent, Map templateParams); + + /** + * 更新发送日志的结果 + * + * @param id 日志编号 + * @param sendCode 发送结果的编码 + * @param sendMsg 发送结果的提示 + * @param apiSendCode 短信 API 发送结果的编码 + * @param apiSendMsg 短信 API 发送失败的提示 + * @param apiRequestId 短信 API 发送返回的唯一请求 ID + * @param apiSerialNo 短信 API 发送返回的序号 + */ + void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, + String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo); + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsSendLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsSendLogService.java deleted file mode 100644 index 7c91b55cb..000000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsSendLogService.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.dashboard.modules.system.service.sms; - -import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; - -import java.util.Map; - -/** - * 短信发送日志服务接口 - * - * @author zzf - * @date 13:48 2021/3/2 - */ -public interface SysSmsSendLogService { - - /** - * 创建发送日志 - * - * @param mobile 手机号 - * @param userId 用户编号 - * @param userType 用户类型 - * @param template 短信模板 - * @param templateContent 短信内容 - * @param templateParams 短信参数 - * @return - */ - Long createSmsSendLog(String mobile, Long userId, Integer userType, - SysSmsTemplateDO template, String templateContent, Map templateParams); - - /** - * 更新发送日志的结果 - * - * @param id 日志编号 - * @param success 是否成功 - * @param sendFailureType 发送失败的类型 - * @param sendFailureMsg 发送失败的提示 - * @param apiSendFailureType 短信 API 发送失败的类型 - * @param apiSendFailureMsg 短信 API 发送失败的提示 - * @param apiRequestId 短信 API 发送返回的唯一请求 ID - * @param apiSerialNo 短信 API 发送返回的序号 - */ - void updateSmsSendLogResult(Long id, Boolean success, Integer sendFailureType, String sendFailureMsg, - String apiSendFailureType, String apiSendFailureMsg, String apiRequestId, String apiSerialNo); - - default void updateSmsSendLogFailure(Long id, SmsSendFailureTypeEnum sendFailureType) { - updateSmsSendLogResult(id, false, sendFailureType.getType(), sendFailureType.getMsg(), - null, null, null, null); - } - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java index 930a7db9c..a34d511bb 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java @@ -3,21 +3,17 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; import cn.iocoder.dashboard.modules.system.convert.sms.SmsChannelConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO; import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsChannelMapper; -import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsTemplateMapper; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.Arrays; import java.util.List; /** @@ -35,12 +31,9 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { @Resource private SysSmsChannelMapper channelMapper; - @Resource - private SysSmsTemplateMapper templateMapper; - @Override @PostConstruct - public void initSmsClientAndCacheSmsTemplate() { + public void initSmsClients() { // 查询有效渠道信息 List channelDOList = channelMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); // 创建渠道 Client @@ -48,6 +41,8 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties)); } + // TODO 芋艿:刷新缓存 + @Override public PageResult pageSmsChannels(SmsChannelPageReqVO reqVO) { return channelMapper.selectChannelPage(reqVO); @@ -60,11 +55,6 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { return channelDO.getId(); } - @Override - public List getSmsChannelEnums() { - return SmsChannelConvert.INSTANCE.convertEnum(Arrays.asList(SmsChannelEnum.values())); - } - // @Override // public List listSmsChannelAllEnabledInfo() { // List channelDOList = channelMapper.selectListByStatus(); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsSendLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsSendLogServiceImpl.java index b57912bd4..00c43e8f1 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsSendLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsSendLogServiceImpl.java @@ -1,10 +1,11 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl; -import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsSendLogDO; +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsSendLogMapper; +import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsLogMapper; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; -import cn.iocoder.dashboard.modules.system.service.sms.SysSmsSendLogService; +import cn.iocoder.dashboard.modules.system.service.sms.SysSmsLogService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -21,15 +22,18 @@ import java.util.Objects; */ @Slf4j @Service -public class SysSmsSendLogServiceImpl implements SysSmsSendLogService { +public class SysSmsSendLogServiceImpl implements SysSmsLogService { @Resource - private SysSmsSendLogMapper smsSendLogMapper; + private SysSmsLogMapper smsLogMapper; @Override - public Long createSmsSendLog(String mobile, Long userId, Integer userType, - SysSmsTemplateDO template, String templateContent, Map templateParams) { - SysSmsSendLogDO.SysSmsSendLogDOBuilder logBuilder = SysSmsSendLogDO.builder(); + public Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend, + SysSmsTemplateDO template, String templateContent, Map templateParams) { + SysSmsLogDO.SysSmsLogDOBuilder logBuilder = SysSmsLogDO.builder(); + // 根据是否要发送,设置状态 + logBuilder.sendStatus(Objects.equals(isSend, true) ? SysSmsSendStatusEnum.INIT.getStatus() + : SysSmsSendStatusEnum.IGNORE.getStatus()); // 设置手机相关字段 logBuilder.mobile(mobile).userId(userId).userType(userType); // 设置模板相关字段 @@ -39,18 +43,18 @@ public class SysSmsSendLogServiceImpl implements SysSmsSendLogService { logBuilder.channelId(template.getChannelId()).channelCode(template.getChannelCode()); // 插入数据库 - SysSmsSendLogDO logDO = logBuilder.build(); - smsSendLogMapper.insert(logDO); + SysSmsLogDO logDO = logBuilder.build(); + smsLogMapper.insert(logDO); return logDO.getId(); } @Override - public void updateSmsSendLogResult(Long id, Boolean success, Integer sendFailureType, String sendFailureMsg, - String apiSendFailureType, String apiSendFailureMsg, String apiRequestId, String apiSerialNo) { - SysSmsSendStatusEnum sendStatus = Objects.equals(success, true) ? SysSmsSendStatusEnum.SUCCESS : SysSmsSendStatusEnum.FAILURE; - smsSendLogMapper.updateById(new SysSmsSendLogDO().setId(id).setSendStatus(sendStatus.getStatus()).setSendTime(new Date()) - .setSendFailureType(sendFailureType).setSendFailureMsg(sendFailureMsg) - .setApiSendFailureType(apiSendFailureType).setApiSendFailureMsg(apiSendFailureMsg).setApiRequestId(apiRequestId).setApiSerialNo(apiSerialNo)); + public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, + String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) { + SysSmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? SysSmsSendStatusEnum.SUCCESS : SysSmsSendStatusEnum.FAILURE; + smsLogMapper.updateById(SysSmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()).sendTime(new Date()) + .sendCode(sendCode).sendMsg(sendMsg).apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) + .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java index e722b4499..959a997b0 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java @@ -1,29 +1,32 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.common.enums.UserTypeEnum; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage; import cn.iocoder.dashboard.modules.system.mq.producer.sms.SysSmsProducer; -import cn.iocoder.dashboard.modules.system.service.sms.SysSmsSendLogService; +import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService; +import cn.iocoder.dashboard.modules.system.service.sms.SysSmsLogService; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsTemplateService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.Assert; import javax.annotation.Resource; import javax.servlet.ServletRequest; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; @@ -38,10 +41,12 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; @Slf4j public class SysSmsServiceImpl implements SysSmsService { + @Resource + private SysSmsChannelService smsChannelService; @Resource private SysSmsTemplateService smsTemplateService; @Resource - private SysSmsSendLogService smsSendLogService; + private SysSmsLogService smsLogService; @Resource private SysSmsProducer smsProducer; @Resource @@ -54,53 +59,58 @@ public class SysSmsServiceImpl implements SysSmsService { public void sendSingleSms(String mobile, Long userId, Integer userType, String templateCode, Map templateParams) { // 校验短信模板是否合法 - SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode, templateParams); + SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode); // 校验手机号码是否存在 mobile = this.checkMobile(mobile, userId, userType); // 创建发送日志 + Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); // 如果模板被禁用,则不发送短信,只记录日志 String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams); - Long sendLogId = smsSendLogService.createSmsSendLog(mobile, userId, userType, template, content, templateParams); + Long sendLogId = smsLogService.createSmsLog(mobile, userId, userType, isSend, template, content, templateParams); - // 如果模板被禁用,则直接标记发送失败。也就说,不发短信,嘿嘿。 - if (CommonStatusEnum.DISABLE.getStatus().equals(template.getStatus())) { - smsSendLogService.updateSmsSendLogFailure(sendLogId, SmsSendFailureTypeEnum.SMS_TEMPLATE_DISABLE); + // 发送 MQ 消息,异步执行发送短信 + if (!isSend) { return; } - // 如果模板未禁用,发送 MQ 消息。目的是,异步化调用短信平台 - smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), template.getApiTemplateId(), templateParams); + List> newTemplateParams = this.buildTemplateParams(template, templateParams); + smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), template.getApiTemplateId(), newTemplateParams); } @Override public void sendBatchSms(List mobiles, List userIds, Integer userType, String templateCode, Map templateParams) { // 校验短信模板是否存在 - SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode, templateParams); + SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode); } - private SysSmsTemplateDO checkSmsTemplateValid(String templateCode, Map templateParams) { + private SysSmsTemplateDO checkSmsTemplateValid(String templateCode) { // 短信模板不存在 SysSmsTemplateDO template = smsTemplateService.getSmsTemplateByCode(templateCode); if (template == null) { throw exception(SMS_TEMPLATE_NOT_EXISTS); } - // 参数不够 - if (CollUtil.isNotEmpty(template.getParams())) { - template.getParams().forEach(param -> { - if (!templateParams.containsKey(param)) { - throw exception(SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS); - } - }); - } - // 移除多余参数 - if (CollUtil.isEmpty(template.getParams())) { - templateParams.clear(); - } else { - templateParams.entrySet().removeIf(entry -> !template.getParams().contains(entry.getKey())); - } return template; } + /** + * 将参数模板,处理成有序的 KeyValue 数组 + * + * 原因是,部分短信平台并不是使用 key 作为参数,而是数组下标,例如说腾讯云 https://cloud.tencent.com/document/product/382/39023 + * + * @param template 短信模板 + * @param templateParams 原始参数 + * @return 处理后的参数 + */ + private List> buildTemplateParams(SysSmsTemplateDO template, Map templateParams) { + return template.getParams().stream().map(key -> { + Object value = templateParams.get(key); + if (value == null) { + throw exception(SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS, key); + } + return new KeyValue<>(key, value); + }).collect(Collectors.toList()); + } + private String checkMobile(String mobile, Long userId, Integer userType) { mobile = getMobile(mobile, userId, userType); if (StrUtil.isEmpty(mobile)) { @@ -130,15 +140,12 @@ public class SysSmsServiceImpl implements SysSmsService { public void doSendSms(SysSmsSendMessage message) { // 获得渠道对应的 SmsClient 客户端 SmsClient smsClient = smsClientFactory.getSmsClient(message.getChannelId()); - if (smsClient == null) { - log.error("[doSendSms][短信 message({}) 找不到对应的客户端]", message); - smsSendLogService.updateSmsSendLogFailure(message.getSendLogId(), SmsSendFailureTypeEnum.SMS_CHANNEL_CLIENT_NOT_EXISTS); - return; - } - + Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", message.getChannelId())); // 发送短信 - SmsCommonResult sendResult = smsClient.send(message.getSendLogId(), message.getMobile(), + SmsCommonResult sendResult = smsClient.send(message.getLogId(), message.getMobile(), message.getApiTemplateId(), message.getTemplateParams()); + smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), + sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(), sendResult.getData().getSerialNo()); } @Override diff --git a/src/main/java/cn/iocoder/dashboard/util/collection/MapUtils.java b/src/main/java/cn/iocoder/dashboard/util/collection/MapUtils.java index ebe29648f..ce5805db8 100644 --- a/src/main/java/cn/iocoder/dashboard/util/collection/MapUtils.java +++ b/src/main/java/cn/iocoder/dashboard/util/collection/MapUtils.java @@ -2,6 +2,8 @@ package cn.iocoder.dashboard.util.collection; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.iocoder.dashboard.common.core.KeyValue; +import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import java.util.ArrayList; @@ -55,4 +57,10 @@ public class MapUtils { consumer.accept(value); } + public static Map convertMap(List> keyValues) { + Map map = Maps.newLinkedHashMapWithExpectedSize(keyValues.size()); + keyValues.forEach(keyValue -> map.put(keyValue.getKey(), keyValue.getValue())); + return map; + } + } diff --git a/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java index 1c85031b6..baae08886 100644 --- a/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ b/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java @@ -1,12 +1,14 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; import org.junit.jupiter.api.Test; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; /** * {@link AliyunSmsClient} 的集成测试 @@ -26,11 +28,11 @@ public class AliyunSmsClientTest { AliyunSmsClient smsClient = new AliyunSmsClient(properties); smsClient.init(); // 发送短信 - Map templateParams = new HashMap<>(); - templateParams.put("code", "1024"); + List> templateParams = new ArrayList<>(); + templateParams.add(new KeyValue<>("code", "1024")); // templateParams.put("operation", "嘿嘿"); // SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); - SmsCommonResult result = smsClient.send(1L, "15601691399", "SMS_207945135", templateParams); + SmsCommonResult result = smsClient.send(1L, "15601691399", "SMS_207945135", templateParams); System.out.println(result); } diff --git a/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java b/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java index 028cd6c77..6e4d4315c 100644 --- a/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java +++ b/src/test-integration/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java @@ -1,12 +1,14 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; +import cn.iocoder.dashboard.common.core.KeyValue; import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; import org.junit.jupiter.api.Test; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; /** * {@link YunpianSmsClient} 的集成测试 @@ -25,11 +27,11 @@ public class YunpianSmsClientIntegrationTest { YunpianSmsClient smsClient = new YunpianSmsClient(properties); smsClient.init(); // 发送短信 - Map templateParams = new HashMap<>(); - templateParams.put("code", "1024"); - templateParams.put("operation", "嘿嘿"); + List> templateParams = new ArrayList<>(); + templateParams.add(new KeyValue<>("code", "1024")); + templateParams.add(new KeyValue<>("operation", "嘿嘿")); // SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); - SmsCommonResult result = smsClient.send(1L, "15601691399", "4383920", templateParams); + SmsCommonResult result = smsClient.send(1L, "15601691399", "4383920", templateParams); System.out.println(result); }