mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-14 21:52:07 +08:00
短信管理单元测试完善
This commit is contained in:
+2
@@ -14,6 +14,8 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@WithSecurityContext(factory = WithMockLoginUserSecurityContextFactory.class)
|
@WithSecurityContext(factory = WithMockLoginUserSecurityContextFactory.class)
|
||||||
public @interface WithMockLoginUser {
|
public @interface WithMockLoginUser {
|
||||||
|
long userId() default 0L;
|
||||||
|
|
||||||
String username() default "";
|
String username() default "";
|
||||||
|
|
||||||
long deptId() default 0L;
|
long deptId() default 0L;
|
||||||
|
|||||||
+2
@@ -22,6 +22,8 @@ public class WithMockLoginUserSecurityContextFactory implements WithSecurityCont
|
|||||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
|
|
||||||
LoginUser loginUser = new LoginUser();
|
LoginUser loginUser = new LoginUser();
|
||||||
|
long annotationUserId = annotation.userId();
|
||||||
|
loginUser.setId(annotationUserId == 0L ? RandomUtil.randomLong() : annotationUserId);
|
||||||
loginUser.setNickname(RandomUtil.randomString(10));
|
loginUser.setNickname(RandomUtil.randomString(10));
|
||||||
loginUser.setDeptId(RandomUtil.randomLong());
|
loginUser.setDeptId(RandomUtil.randomLong());
|
||||||
loginUser.setOrganId(RandomUtil.randomLong());
|
loginUser.setOrganId(RandomUtil.randomLong());
|
||||||
|
|||||||
-6
@@ -1,14 +1,12 @@
|
|||||||
package com.cf.imes.module.system.api.sms;
|
package com.cf.imes.module.system.api.sms;
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
|
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||||
import com.cf.imes.module.system.enums.ApiConstants;
|
import com.cf.imes.module.system.enums.ApiConstants;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@@ -29,8 +27,4 @@ public interface SmsCodeApi {
|
|||||||
@Operation(summary = "验证短信验证码,并进行使用")
|
@Operation(summary = "验证短信验证码,并进行使用")
|
||||||
CommonResult<Boolean> useSmsCode(@Valid @RequestBody SmsCodeUseReqDTO reqDTO);
|
CommonResult<Boolean> useSmsCode(@Valid @RequestBody SmsCodeUseReqDTO reqDTO);
|
||||||
|
|
||||||
@GetMapping(PREFIX + "/validate")
|
|
||||||
@Operation(summary = "检查验证码是否有效")
|
|
||||||
CommonResult<Boolean> validateSmsCode(@Valid @RequestBody SmsCodeValidateReqDTO reqDTO);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
package com.cf.imes.module.system.api.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
|
||||||
import com.cf.imes.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
|
|
||||||
import com.cf.imes.module.system.enums.ApiConstants;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
|
|
||||||
@FeignClient(name = ApiConstants.NAME) // TODO 晨丰:fallbackFactory =
|
|
||||||
@Tag(name = "RPC 服务 - 短信发送")
|
|
||||||
public interface SmsSendApi {
|
|
||||||
|
|
||||||
String PREFIX = ApiConstants.PREFIX + "/sms/send";
|
|
||||||
|
|
||||||
@PostMapping(PREFIX + "/send-single-admin")
|
|
||||||
@Operation(summary = "发送单条短信给 Admin 用户", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
|
|
||||||
CommonResult<Long> sendSingleSmsToAdmin(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
|
|
||||||
|
|
||||||
@PostMapping(PREFIX + "/send-single-member")
|
|
||||||
@Operation(summary = "发送单条短信给 Member 用户", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
|
|
||||||
CommonResult<Long> sendSingleSmsToMember(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
|
|
||||||
|
|
||||||
}
|
|
||||||
-7
@@ -3,7 +3,6 @@ package com.cf.imes.module.system.api.sms;
|
|||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
|
|
||||||
import com.cf.imes.module.system.service.sms.SmsCodeService;
|
import com.cf.imes.module.system.service.sms.SmsCodeService;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
@@ -31,10 +30,4 @@ public class SmsCodeApiImpl implements SmsCodeApi {
|
|||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommonResult<Boolean> validateSmsCode(SmsCodeValidateReqDTO reqDTO) {
|
|
||||||
smsCodeService.validateSmsCode(reqDTO);
|
|
||||||
return success(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
package com.cf.imes.module.system.api.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
|
||||||
import com.cf.imes.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
|
|
||||||
import com.cf.imes.module.system.service.sms.SmsSendService;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
|
||||||
|
|
||||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
|
||||||
@Validated
|
|
||||||
public class SmsSendApiImpl implements SmsSendApi {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SmsSendService smsSendService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommonResult<Long> sendSingleSmsToAdmin(SmsSendSingleToUserReqDTO reqDTO) {
|
|
||||||
return success(smsSendService.sendSingleSmsToAdmin(reqDTO.getMobile(), reqDTO.getUserId(),
|
|
||||||
reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommonResult<Long> sendSingleSmsToMember(SmsSendSingleToUserReqDTO reqDTO) {
|
|
||||||
return success(smsSendService.sendSingleSmsToMember(reqDTO.getMobile(), reqDTO.getUserId(),
|
|
||||||
reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-82
@@ -1,82 +0,0 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
|
||||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelRespVO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelSimpleRespVO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import com.cf.imes.module.system.service.sms.SmsChannelService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
|
||||||
|
|
||||||
@Tag(name = "管理后台 - 短信渠道")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("system/sms-channel")
|
|
||||||
public class SmsChannelController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SmsChannelService smsChannelService;
|
|
||||||
|
|
||||||
@PostMapping("/create")
|
|
||||||
@Operation(summary = "创建短信渠道")
|
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:create')")
|
|
||||||
public CommonResult<Long> createSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO createReqVO) {
|
|
||||||
return success(smsChannelService.createSmsChannel(createReqVO));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/update")
|
|
||||||
@Operation(summary = "更新短信渠道")
|
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:update')")
|
|
||||||
public CommonResult<Boolean> updateSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO updateReqVO) {
|
|
||||||
smsChannelService.updateSmsChannel(updateReqVO);
|
|
||||||
return success(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
|
||||||
@Operation(summary = "删除短信渠道")
|
|
||||||
@Parameter(name = "id", description = "编号", required = true)
|
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:delete')")
|
|
||||||
public CommonResult<Boolean> deleteSmsChannel(@RequestParam("id") Long id) {
|
|
||||||
smsChannelService.deleteSmsChannel(id);
|
|
||||||
return success(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/get")
|
|
||||||
@Operation(summary = "获得短信渠道")
|
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
|
|
||||||
public CommonResult<SmsChannelRespVO> getSmsChannel(@RequestParam("id") Long id) {
|
|
||||||
SmsChannelDO channel = smsChannelService.getSmsChannel(id);
|
|
||||||
return success(BeanUtils.toBean(channel, SmsChannelRespVO.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/page")
|
|
||||||
@Operation(summary = "获得短信渠道分页")
|
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
|
|
||||||
public CommonResult<PageResult<SmsChannelRespVO>> getSmsChannelPage(@Valid SmsChannelPageReqVO pageVO) {
|
|
||||||
PageResult<SmsChannelDO> pageResult = smsChannelService.getSmsChannelPage(pageVO);
|
|
||||||
return success(BeanUtils.toBean(pageResult, SmsChannelRespVO.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping({"/list-all-simple", "/simple-list"})
|
|
||||||
@Operation(summary = "获得短信渠道精简列表", description = "包含被禁用的短信渠道")
|
|
||||||
public CommonResult<List<SmsChannelSimpleRespVO>> getSimpleSmsChannelList() {
|
|
||||||
List<SmsChannelDO> list = smsChannelService.getSmsChannelList();
|
|
||||||
list.sort(Comparator.comparing(SmsChannelDO::getId));
|
|
||||||
return success(BeanUtils.toBean(list, SmsChannelSimpleRespVO.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.sms;
|
package com.cf.imes.module.system.controller.admin.sms;
|
||||||
|
|
||||||
|
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
||||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||||
import com.cf.imes.framework.common.pojo.PageParam;
|
import com.cf.imes.framework.common.pojo.PageParam;
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
@@ -96,7 +97,7 @@ public class SmsTemplateController {
|
|||||||
@Operation(summary = "发送短信")
|
@Operation(summary = "发送短信")
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-template:send-sms')")
|
@PreAuthorize("@ss.hasPermission('system:sms-template:send-sms')")
|
||||||
public CommonResult<Long> sendSms(@Valid @RequestBody SmsTemplateSendReqVO sendReqVO) {
|
public CommonResult<Long> sendSms(@Valid @RequestBody SmsTemplateSendReqVO sendReqVO) {
|
||||||
return success(smsSendService.sendSingleSmsToAdmin(sendReqVO.getMobile(), null,
|
return success(smsSendService.sendSingleSms(sendReqVO.getMobile(), null, UserTypeEnum.ADMIN.getValue(),
|
||||||
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
|
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.sms.vo.channel;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.PageParam;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 短信渠道分页 Request VO")
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class SmsChannelPageReqVO extends PageParam {
|
|
||||||
|
|
||||||
@Schema(description = "任务状态", example = "1")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
@Schema(description = "短信签名,模糊匹配", example = "晨丰科技")
|
|
||||||
private String signature;
|
|
||||||
|
|
||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
|
||||||
@Schema(description = "创建时间")
|
|
||||||
private LocalDateTime[] createTime;
|
|
||||||
|
|
||||||
}
|
|
||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.sms.vo.channel;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.hibernate.validator.constraints.URL;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 短信渠道 Response VO")
|
|
||||||
@Data
|
|
||||||
public class SmsChannelRespVO {
|
|
||||||
|
|
||||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰科技")
|
|
||||||
@NotNull(message = "短信签名不能为空")
|
|
||||||
private String signature;
|
|
||||||
|
|
||||||
@Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
@Schema(description = "启用状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
|
||||||
@NotNull(message = "启用状态不能为空")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
@Schema(description = "备注", example = "好吃!")
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
@Schema(description = "短信 API 的账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "chenfeng")
|
|
||||||
@NotNull(message = "短信 API 的账号不能为空")
|
|
||||||
private String apiKey;
|
|
||||||
|
|
||||||
@Schema(description = "短信 API 的密钥", example = "yuanma")
|
|
||||||
private String apiSecret;
|
|
||||||
|
|
||||||
@Schema(description = "短信发送回调 URL", example = "https://www.cf.com")
|
|
||||||
@URL(message = "回调 URL 格式不正确")
|
|
||||||
private String callbackUrl;
|
|
||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private LocalDateTime createTime;
|
|
||||||
|
|
||||||
}
|
|
||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.sms.vo.channel;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.hibernate.validator.constraints.URL;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 短信渠道创建/修改 Request VO")
|
|
||||||
@Data
|
|
||||||
public class SmsChannelSaveReqVO {
|
|
||||||
|
|
||||||
@Schema(description = "编号", example = "1024")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰科技")
|
|
||||||
@NotNull(message = "短信签名不能为空")
|
|
||||||
private String signature;
|
|
||||||
|
|
||||||
@Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
|
|
||||||
@NotNull(message = "渠道编码不能为空")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
@Schema(description = "启用状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
|
||||||
@NotNull(message = "启用状态不能为空")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
@Schema(description = "备注", example = "好吃!")
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
@Schema(description = "短信 API 的账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "chenfeng")
|
|
||||||
@NotNull(message = "短信 API 的账号不能为空")
|
|
||||||
private String apiKey;
|
|
||||||
|
|
||||||
@Schema(description = "短信 API 的密钥", example = "yuanma")
|
|
||||||
private String apiSecret;
|
|
||||||
|
|
||||||
@Schema(description = "短信发送回调 URL", example = "http://www.cf.com")
|
|
||||||
@URL(message = "回调 URL 格式不正确")
|
|
||||||
private String callbackUrl;
|
|
||||||
|
|
||||||
}
|
|
||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.sms.vo.channel;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 短信渠道精简 Response VO")
|
|
||||||
@Data
|
|
||||||
public class SmsChannelSimpleRespVO {
|
|
||||||
|
|
||||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰科技")
|
|
||||||
private String signature;
|
|
||||||
|
|
||||||
@Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
}
|
|
||||||
+6
-6
@@ -3,8 +3,8 @@ package com.cf.imes.module.system.controller.admin.sms.vo.template;
|
|||||||
import com.cf.imes.module.system.validation.common.CommonStatus;
|
import com.cf.imes.module.system.validation.common.CommonStatus;
|
||||||
import com.cf.imes.module.system.validation.sms.SmsTemplateTypeValid;
|
import com.cf.imes.module.system.validation.sms.SmsTemplateTypeValid;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.hibernate.validator.constraints.Length;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
@@ -27,26 +27,26 @@ public class SmsTemplateSaveReqVO {
|
|||||||
|
|
||||||
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
|
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
|
||||||
@NotNull(message = "模板编码不能为空")
|
@NotNull(message = "模板编码不能为空")
|
||||||
@Length(min = 1, max = 64, message = "模板编码长度不能超过64个字符")
|
@Size(min = 1, max = 64, message = "模板编码长度不能超过64个字符")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "chenfeng")
|
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "chenfeng")
|
||||||
@NotNull(message = "模板名称不能为空")
|
@NotNull(message = "模板名称不能为空")
|
||||||
@Length(min = 1, max = 64, message = "模板名称长度不能超过64个字符")
|
@Size(min = 1, max = 64, message = "模板名称长度不能超过64个字符")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "模板内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,{name}。你长的太{like}啦!")
|
@Schema(description = "模板内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,{name}。你长的太{like}啦!")
|
||||||
@NotNull(message = "模板内容不能为空")
|
@NotNull(message = "模板内容不能为空")
|
||||||
@Length(min = 1, max = 255, message = "模板内容长度不能超过255个字符")
|
@Size(min = 1, max = 255, message = "模板内容长度不能超过255个字符")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
@Schema(description = "备注", example = "哈哈哈")
|
@Schema(description = "备注", example = "哈哈哈")
|
||||||
@Length(max = 255, message = "备注长度不能超过255个字符")
|
@Size(max = 255, message = "备注长度不能超过255个字符")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
@Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4383920")
|
@Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4383920")
|
||||||
@NotNull(message = "短信 API 的模板编号不能为空")
|
@NotNull(message = "短信 API 的模板编号不能为空")
|
||||||
@Length(min = 1, max = 64, message = "短信 API 的模板编号长度不能超过64个字符")
|
@Size(min = 1, max = 64, message = "短信 API 的模板编号长度不能超过64个字符")
|
||||||
private String apiTemplateId;
|
private String apiTemplateId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-62
@@ -1,62 +0,0 @@
|
|||||||
package com.cf.imes.module.system.dal.dataobject.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
|
||||||
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
|
|
||||||
import com.cf.imes.module.system.framework.sms.core.enums.SmsChannelEnum;
|
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信渠道 DO
|
|
||||||
*
|
|
||||||
* @author zzf
|
|
||||||
* @since 2021-01-25
|
|
||||||
*/
|
|
||||||
@TableName(value = "system_sms_channel", autoResultMap = true)
|
|
||||||
@KeySequence("system_sms_channel_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class SmsChannelDO extends BaseDO {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 渠道编号
|
|
||||||
*/
|
|
||||||
private Long id;
|
|
||||||
/**
|
|
||||||
* 短信签名
|
|
||||||
*/
|
|
||||||
private String signature;
|
|
||||||
/**
|
|
||||||
* 渠道编码
|
|
||||||
*
|
|
||||||
* 枚举 {@link SmsChannelEnum}
|
|
||||||
*/
|
|
||||||
private String code;
|
|
||||||
/**
|
|
||||||
* 启用状态
|
|
||||||
*
|
|
||||||
* 枚举 {@link CommonStatusEnum}
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
private String remark;
|
|
||||||
/**
|
|
||||||
* 短信 API 的账号
|
|
||||||
*/
|
|
||||||
private String apiKey;
|
|
||||||
/**
|
|
||||||
* 短信 API 的密钥
|
|
||||||
*/
|
|
||||||
private String apiSecret;
|
|
||||||
/**
|
|
||||||
* 短信发送回调 URL
|
|
||||||
*/
|
|
||||||
private String callbackUrl;
|
|
||||||
|
|
||||||
}
|
|
||||||
-65
@@ -1,65 +0,0 @@
|
|||||||
package com.cf.imes.module.system.dal.dataobject.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
|
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手机验证码 DO
|
|
||||||
*
|
|
||||||
* idx_mobile 索引:基于 {@link #mobile} 字段
|
|
||||||
*
|
|
||||||
* @author 晨丰科技
|
|
||||||
*/
|
|
||||||
@TableName("system_sms_code")
|
|
||||||
@KeySequence("system_sms_code_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class SmsCodeDO extends BaseDO {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编号
|
|
||||||
*/
|
|
||||||
private Long id;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
private String mobile;
|
|
||||||
/**
|
|
||||||
* 验证码
|
|
||||||
*/
|
|
||||||
private String code;
|
|
||||||
/**
|
|
||||||
* 发送场景
|
|
||||||
*
|
|
||||||
* 枚举 {@link SmsCodeDO}
|
|
||||||
*/
|
|
||||||
private Integer scene;
|
|
||||||
/**
|
|
||||||
* 创建 IP
|
|
||||||
*/
|
|
||||||
private String createIp;
|
|
||||||
/**
|
|
||||||
* 今日发送的第几条
|
|
||||||
*/
|
|
||||||
private Integer todayIndex;
|
|
||||||
/**
|
|
||||||
* 是否使用
|
|
||||||
*/
|
|
||||||
private Boolean used;
|
|
||||||
/**
|
|
||||||
* 使用时间
|
|
||||||
*/
|
|
||||||
private LocalDateTime usedTime;
|
|
||||||
/**
|
|
||||||
* 使用 IP
|
|
||||||
*/
|
|
||||||
private String usedIp;
|
|
||||||
|
|
||||||
}
|
|
||||||
-2
@@ -41,13 +41,11 @@ public class SmsLogDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 短信渠道编号
|
* 短信渠道编号
|
||||||
*
|
*
|
||||||
* 关联 {@link SmsChannelDO#getId()}
|
|
||||||
*/
|
*/
|
||||||
private Long channelId;
|
private Long channelId;
|
||||||
/**
|
/**
|
||||||
* 短信渠道编码
|
* 短信渠道编码
|
||||||
*
|
*
|
||||||
* 冗余 {@link SmsChannelDO#getCode()}
|
|
||||||
*/
|
*/
|
||||||
private String channelCode;
|
private String channelCode;
|
||||||
|
|
||||||
|
|||||||
-2
@@ -80,13 +80,11 @@ public class SmsTemplateDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 短信渠道编号
|
* 短信渠道编号
|
||||||
*
|
*
|
||||||
* 关联 {@link SmsChannelDO#getId()}
|
|
||||||
*/
|
*/
|
||||||
private Long channelId;
|
private Long channelId;
|
||||||
/**
|
/**
|
||||||
* 短信渠道编码
|
* 短信渠道编码
|
||||||
*
|
*
|
||||||
* 冗余 {@link SmsChannelDO#getCode()}
|
|
||||||
*/
|
*/
|
||||||
private String channelCode;
|
private String channelCode;
|
||||||
|
|
||||||
|
|||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
package com.cf.imes.module.system.dal.mysql.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
|
||||||
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
|
|
||||||
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
|
|
||||||
|
|
||||||
default PageResult<SmsChannelDO> selectPage(SmsChannelPageReqVO reqVO) {
|
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<SmsChannelDO>()
|
|
||||||
.likeIfPresent(SmsChannelDO::getSignature, reqVO.getSignature())
|
|
||||||
.eqIfPresent(SmsChannelDO::getStatus, reqVO.getStatus())
|
|
||||||
.betweenIfPresent(SmsChannelDO::getCreateTime, reqVO.getCreateTime())
|
|
||||||
.orderByDesc(SmsChannelDO::getId));
|
|
||||||
}
|
|
||||||
|
|
||||||
default SmsChannelDO selectByCode(String code) {
|
|
||||||
return selectOne(SmsChannelDO::getCode, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
package com.cf.imes.module.system.dal.mysql.sms;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
|
|
||||||
import com.cf.imes.framework.mybatis.core.query.QueryWrapperX;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsCodeDO;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface SmsCodeMapper extends BaseMapperX<SmsCodeDO> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得手机号的最后一个手机验证码
|
|
||||||
*
|
|
||||||
* @param mobile 手机号
|
|
||||||
* @param scene 发送场景,选填
|
|
||||||
* @param code 验证码 选填
|
|
||||||
* @return 手机验证码
|
|
||||||
*/
|
|
||||||
default SmsCodeDO selectLastByMobile(String mobile, String code, Integer scene) {
|
|
||||||
return selectOne(new QueryWrapperX<SmsCodeDO>()
|
|
||||||
.eq("mobile", mobile)
|
|
||||||
.eqIfPresent("scene", scene)
|
|
||||||
.eqIfPresent("code", code)
|
|
||||||
.orderByDesc("id")
|
|
||||||
.limitN(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-8
@@ -9,14 +9,6 @@ import com.cf.imes.module.system.framework.sms.core.property.SmsProperties;
|
|||||||
* @since 2021/1/28 14:01
|
* @since 2021/1/28 14:01
|
||||||
*/
|
*/
|
||||||
public interface SmsClientFactory {
|
public interface SmsClientFactory {
|
||||||
/**
|
|
||||||
* 获得短信 Client
|
|
||||||
*
|
|
||||||
* @param channelCode 渠道编码
|
|
||||||
* @return 短信 Client
|
|
||||||
*/
|
|
||||||
SmsClient getSmsClient(String channelCode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得短信 Client
|
* 获得短信 Client
|
||||||
*
|
*
|
||||||
|
|||||||
-5
@@ -55,11 +55,6 @@ public class SmsClientFactoryImpl implements SmsClientFactory {
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SmsClient getSmsClient(String channelCode) {
|
|
||||||
return channelCodeClients.get(channelCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AbstractSmsClient createSmsClient(SmsProperties smsProperties) {
|
private AbstractSmsClient createSmsClient(SmsProperties smsProperties) {
|
||||||
String channel = smsProperties.getChannel();
|
String channel = smsProperties.getChannel();
|
||||||
SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(channel);
|
SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(channel);
|
||||||
|
|||||||
-68
@@ -1,13 +1,6 @@
|
|||||||
package com.cf.imes.module.system.service.sms;
|
package com.cf.imes.module.system.service.sms;
|
||||||
|
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 短信渠道 Service 接口
|
* 短信渠道 Service 接口
|
||||||
@@ -17,67 +10,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface SmsChannelService {
|
public interface SmsChannelService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建短信渠道
|
|
||||||
*
|
|
||||||
* @param createReqVO 创建信息
|
|
||||||
* @return 编号
|
|
||||||
*/
|
|
||||||
Long createSmsChannel(@Valid SmsChannelSaveReqVO createReqVO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新短信渠道
|
|
||||||
*
|
|
||||||
* @param updateReqVO 更新信息
|
|
||||||
*/
|
|
||||||
void updateSmsChannel(@Valid SmsChannelSaveReqVO updateReqVO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除短信渠道
|
|
||||||
*
|
|
||||||
* @param id 编号
|
|
||||||
*/
|
|
||||||
void deleteSmsChannel(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得短信渠道
|
|
||||||
*
|
|
||||||
* @param id 编号
|
|
||||||
* @return 短信渠道
|
|
||||||
*/
|
|
||||||
SmsChannelDO getSmsChannel(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得所有短信渠道列表
|
|
||||||
*
|
|
||||||
* @return 短信渠道列表
|
|
||||||
*/
|
|
||||||
List<SmsChannelDO> getSmsChannelList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得短信渠道分页
|
|
||||||
*
|
|
||||||
* @param pageReqVO 分页查询
|
|
||||||
* @return 短信渠道分页
|
|
||||||
*/
|
|
||||||
PageResult<SmsChannelDO> getSmsChannelPage(SmsChannelPageReqVO pageReqVO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得短信客户端
|
|
||||||
*
|
|
||||||
* @param id 编号
|
|
||||||
* @return 短信客户端
|
|
||||||
*/
|
|
||||||
SmsClient getSmsClient(Long id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得短信客户端
|
|
||||||
*
|
|
||||||
* @param code 编码
|
|
||||||
* @return 短信客户端
|
|
||||||
*/
|
|
||||||
SmsClient getSmsClient(String code);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据配置获得短信客户端
|
* 根据配置获得短信客户端
|
||||||
*
|
*
|
||||||
|
|||||||
-129
@@ -1,28 +1,13 @@
|
|||||||
package com.cf.imes.module.system.service.sms;
|
package com.cf.imes.module.system.service.sms;
|
||||||
|
|
||||||
import cn.hutool.core.text.CharSequenceUtil;
|
|
||||||
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
|
||||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClientFactory;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClientFactory;
|
||||||
import com.cf.imes.module.system.framework.sms.core.property.SmsProperties;
|
import com.cf.imes.module.system.framework.sms.core.property.SmsProperties;
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import com.cf.imes.module.system.dal.mysql.sms.SmsChannelMapper;
|
|
||||||
import com.cf.imes.module.system.enums.ErrorCodeConstants;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 短信渠道 Service 实现类
|
* 短信渠道 Service 实现类
|
||||||
@@ -36,123 +21,9 @@ public class SmsChannelServiceImpl implements SmsChannelService {
|
|||||||
@Resource
|
@Resource
|
||||||
private SmsClientFactory smsClientFactory;
|
private SmsClientFactory smsClientFactory;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SmsChannelMapper smsChannelMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SmsTemplateService smsTemplateService;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsProperties smsProperties;
|
private SmsProperties smsProperties;
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link SmsClient} 缓存,通过它异步刷新 smsClientFactory
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final LoadingCache<Long, SmsClient> idClientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
|
|
||||||
new CacheLoader<>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SmsClient load(Long id) {
|
|
||||||
return smsClientFactory.getSmsClient(smsProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link SmsClient} 缓存,通过它异步刷新 smsClientFactory
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final LoadingCache<String, SmsClient> codeClientCache = buildAsyncReloadingCache(Duration.ofSeconds(60L),
|
|
||||||
new CacheLoader<>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SmsClient load(String code) {
|
|
||||||
return smsClientFactory.getSmsClient(smsProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long createSmsChannel(SmsChannelSaveReqVO createReqVO) {
|
|
||||||
SmsChannelDO channel = BeanUtils.toBean(createReqVO, SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(channel);
|
|
||||||
return channel.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSmsChannel(SmsChannelSaveReqVO updateReqVO) {
|
|
||||||
// 校验存在
|
|
||||||
SmsChannelDO channel = validateSmsChannelExists(updateReqVO.getId());
|
|
||||||
// 更新
|
|
||||||
SmsChannelDO updateObj = BeanUtils.toBean(updateReqVO, SmsChannelDO.class);
|
|
||||||
smsChannelMapper.updateById(updateObj);
|
|
||||||
|
|
||||||
// 清空缓存
|
|
||||||
clearCache(updateReqVO.getId(), channel.getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteSmsChannel(Long id) {
|
|
||||||
// 校验存在
|
|
||||||
SmsChannelDO channel = validateSmsChannelExists(id);
|
|
||||||
// 校验是否有在使用该账号的模版
|
|
||||||
if (smsTemplateService.getSmsTemplateCountByChannelId(id) > 0) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN);
|
|
||||||
}
|
|
||||||
// 删除
|
|
||||||
smsChannelMapper.deleteById(id);
|
|
||||||
|
|
||||||
// 清空缓存
|
|
||||||
clearCache(id, channel.getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空指定渠道编号的缓存
|
|
||||||
*
|
|
||||||
* @param id 渠道编号
|
|
||||||
* @param code 渠道编码
|
|
||||||
*/
|
|
||||||
private void clearCache(Long id, String code) {
|
|
||||||
idClientCache.invalidate(id);
|
|
||||||
if (CharSequenceUtil.isNotEmpty(code)) {
|
|
||||||
codeClientCache.invalidate(code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SmsChannelDO validateSmsChannelExists(Long id) {
|
|
||||||
SmsChannelDO channel = smsChannelMapper.selectById(id);
|
|
||||||
if (channel == null) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SmsChannelDO getSmsChannel(Long id) {
|
|
||||||
return smsChannelMapper.selectById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<SmsChannelDO> getSmsChannelList() {
|
|
||||||
return smsChannelMapper.selectList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<SmsChannelDO> getSmsChannelPage(SmsChannelPageReqVO pageReqVO) {
|
|
||||||
return smsChannelMapper.selectPage(pageReqVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SmsClient getSmsClient(Long id) {
|
|
||||||
return idClientCache.getUnchecked(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SmsClient getSmsClient(String code) {
|
|
||||||
return smsClientFactory.getSmsClient(smsProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SmsClient getSmsClient() {
|
public SmsClient getSmsClient() {
|
||||||
return smsClientFactory.getSmsClient(smsProperties);
|
return smsClientFactory.getSmsClient(smsProperties);
|
||||||
|
|||||||
-8
@@ -3,7 +3,6 @@ package com.cf.imes.module.system.service.sms;
|
|||||||
import com.cf.imes.framework.common.exception.ServiceException;
|
import com.cf.imes.framework.common.exception.ServiceException;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO;
|
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
@@ -31,13 +30,6 @@ public interface SmsCodeService {
|
|||||||
*/
|
*/
|
||||||
void useSmsCode(@Valid SmsCodeUseReqDTO reqDTO);
|
void useSmsCode(@Valid SmsCodeUseReqDTO reqDTO);
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查验证码是否有效
|
|
||||||
*
|
|
||||||
* @param reqDTO 校验请求
|
|
||||||
*/
|
|
||||||
void validateSmsCode(@Valid SmsCodeValidateReqDTO reqDTO);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查验证码是否有效
|
* 检查验证码是否有效
|
||||||
*
|
*
|
||||||
|
|||||||
-32
@@ -1,6 +1,5 @@
|
|||||||
package com.cf.imes.module.system.service.sms;
|
package com.cf.imes.module.system.service.sms;
|
||||||
|
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
@@ -10,11 +9,8 @@ import com.cf.imes.framework.security.core.LoginUser;
|
|||||||
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO;
|
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsCodeDO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import com.cf.imes.module.system.dal.mysql.sms.SmsCodeMapper;
|
|
||||||
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
||||||
import com.cf.imes.module.system.enums.sms.SmsSceneEnum;
|
import com.cf.imes.module.system.enums.sms.SmsSceneEnum;
|
||||||
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
||||||
@@ -27,7 +23,6 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -45,9 +40,6 @@ public class SmsCodeServiceImpl implements SmsCodeService {
|
|||||||
@Resource
|
@Resource
|
||||||
private SmsCodeProperties smsCodeProperties;
|
private SmsCodeProperties smsCodeProperties;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SmsCodeMapper smsCodeMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsSendService smsSendService;
|
private SmsSendService smsSendService;
|
||||||
|
|
||||||
@@ -215,28 +207,4 @@ public class SmsCodeServiceImpl implements SmsCodeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validateSmsCode(SmsCodeValidateReqDTO reqDTO) {
|
|
||||||
validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene());
|
|
||||||
}
|
|
||||||
|
|
||||||
private SmsCodeDO validateSmsCode0(String mobile, String code, Integer scene) {
|
|
||||||
// 校验验证码
|
|
||||||
SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, code, scene);
|
|
||||||
// 若验证码不存在,抛出异常
|
|
||||||
if (lastSmsCode == null) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_NOT_FOUND);
|
|
||||||
}
|
|
||||||
// 超过时间
|
|
||||||
if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis()
|
|
||||||
>= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_EXPIRED);
|
|
||||||
}
|
|
||||||
// 判断验证码是否已被使用
|
|
||||||
if (Boolean.TRUE.equals(lastSmsCode.getUsed())) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_USED);
|
|
||||||
}
|
|
||||||
return lastSmsCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -32,8 +32,7 @@ public class SmsLogServiceImpl implements SmsLogService {
|
|||||||
SmsTemplateDO template, String templateContent, Map<String, Object> templateParams) {
|
SmsTemplateDO template, String templateContent, Map<String, Object> templateParams) {
|
||||||
SmsLogDO.SmsLogDOBuilder logBuilder = SmsLogDO.builder();
|
SmsLogDO.SmsLogDOBuilder logBuilder = SmsLogDO.builder();
|
||||||
// 根据是否要发送,设置状态
|
// 根据是否要发送,设置状态
|
||||||
logBuilder.sendStatus(Objects.equals(isSend, true) ? SmsSendStatusEnum.INIT.getStatus()
|
logBuilder.sendStatus(SmsSendStatusEnum.INIT.getStatus());
|
||||||
: SmsSendStatusEnum.IGNORE.getStatus());
|
|
||||||
// 设置手机相关字段
|
// 设置手机相关字段
|
||||||
logBuilder.mobile(mobile).userId(userId).userType(userType);
|
logBuilder.mobile(mobile).userId(userId).userType(userType);
|
||||||
// 设置模板相关字段
|
// 设置模板相关字段
|
||||||
|
|||||||
-29
@@ -11,35 +11,6 @@ import java.util.Map;
|
|||||||
* @author 晨丰科技
|
* @author 晨丰科技
|
||||||
*/
|
*/
|
||||||
public interface SmsSendService {
|
public interface SmsSendService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送单条短信给管理后台的用户
|
|
||||||
*
|
|
||||||
* 在 mobile 为空时,使用 userId 加载对应管理员的手机号
|
|
||||||
*
|
|
||||||
* @param mobile 手机号
|
|
||||||
* @param userId 用户编号
|
|
||||||
* @param templateCode 短信模板编号
|
|
||||||
* @param templateParams 短信模板参数
|
|
||||||
* @return 发送日志编号
|
|
||||||
*/
|
|
||||||
Long sendSingleSmsToAdmin(String mobile, Long userId,
|
|
||||||
String templateCode, Map<String, Object> templateParams);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送单条短信给用户 APP 的用户
|
|
||||||
*
|
|
||||||
* 在 mobile 为空时,使用 userId 加载对应会员的手机号
|
|
||||||
*
|
|
||||||
* @param mobile 手机号
|
|
||||||
* @param userId 用户编号
|
|
||||||
* @param templateCode 短信模板编号
|
|
||||||
* @param templateParams 短信模板参数
|
|
||||||
* @return 发送日志编号
|
|
||||||
*/
|
|
||||||
Long sendSingleSmsToMember(String mobile, Long userId,
|
|
||||||
String templateCode, Map<String, Object> templateParams);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送单条短信给用户
|
* 发送单条短信给用户
|
||||||
*
|
*
|
||||||
|
|||||||
+15
-37
@@ -5,22 +5,20 @@ import cn.hutool.core.exceptions.ExceptionUtil;
|
|||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import com.cf.imes.framework.common.core.KeyValue;
|
import com.cf.imes.framework.common.core.KeyValue;
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||||
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
|
||||||
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
||||||
|
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
||||||
|
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
|
||||||
import com.cf.imes.module.system.mq.message.sms.SmsSendMessage;
|
import com.cf.imes.module.system.mq.message.sms.SmsSendMessage;
|
||||||
import com.cf.imes.module.system.mq.producer.sms.SmsProducer;
|
import com.cf.imes.module.system.mq.producer.sms.SmsProducer;
|
||||||
import com.cf.imes.module.system.service.member.MemberService;
|
|
||||||
import com.cf.imes.module.system.service.sms.handler.SmsSendAfterSendHandler;
|
|
||||||
import com.cf.imes.module.system.service.user.AdminUserService;
|
|
||||||
import com.cf.imes.module.system.enums.ErrorCodeConstants;
|
import com.cf.imes.module.system.enums.ErrorCodeConstants;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -37,10 +35,6 @@ import java.util.stream.Collectors;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class SmsSendServiceImpl implements SmsSendService {
|
public class SmsSendServiceImpl implements SmsSendService {
|
||||||
|
|
||||||
@Resource
|
|
||||||
private AdminUserService adminUserService;
|
|
||||||
@Resource
|
|
||||||
private MemberService memberService;
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsChannelService smsChannelService;
|
private SmsChannelService smsChannelService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -52,30 +46,10 @@ public class SmsSendServiceImpl implements SmsSendService {
|
|||||||
private SmsProducer smsProducer;
|
private SmsProducer smsProducer;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private List<SmsSendAfterSendHandler> smsSendAfterSendHandlers;
|
private RedisTemplate redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Resource
|
||||||
public Long sendSingleSmsToAdmin(String mobile, Long userId, String templateCode, Map<String, Object> templateParams) {
|
private SmsCodeProperties smsCodeProperties;
|
||||||
// 如果 mobile 为空,则加载用户编号对应的手机号
|
|
||||||
if (StringUtils.isEmpty(mobile)) {
|
|
||||||
AdminUserDO user = adminUserService.getUser(userId);
|
|
||||||
if (user != null) {
|
|
||||||
mobile = user.getMobile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 执行发送
|
|
||||||
return sendSingleSms(mobile, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map<String, Object> templateParams) {
|
|
||||||
// 如果 mobile 为空,则加载用户编号对应的手机号
|
|
||||||
if (StringUtils.isEmpty(mobile)) {
|
|
||||||
mobile = memberService.getMemberUserMobile(userId);
|
|
||||||
}
|
|
||||||
// 执行发送
|
|
||||||
return sendSingleSms(mobile, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long sendSingleSms(String mobile, Long userId, Integer userType,
|
public Long sendSingleSms(String mobile, Long userId, Integer userType,
|
||||||
@@ -95,7 +69,9 @@ public class SmsSendServiceImpl implements SmsSendService {
|
|||||||
|
|
||||||
// 发送 MQ 消息,异步执行发送短信
|
// 发送 MQ 消息,异步执行发送短信
|
||||||
if (isSend) {
|
if (isSend) {
|
||||||
smsProducer.sendSmsSendMessage(sendLogId, mobile, template, newTemplateParams);
|
SmsSendMessage message = new SmsSendMessage().setLogId(sendLogId).setMobile(mobile);
|
||||||
|
message.setChannelId(template.getChannelId()).setApiTemplateId(template.getApiTemplateId()).setTemplateType(template.getType()).setTemplateParams(newTemplateParams);
|
||||||
|
doSendSms(message);
|
||||||
}
|
}
|
||||||
return sendLogId;
|
return sendLogId;
|
||||||
}
|
}
|
||||||
@@ -153,9 +129,11 @@ public class SmsSendServiceImpl implements SmsSendService {
|
|||||||
message.getApiTemplateId(), templateParams);
|
message.getApiTemplateId(), templateParams);
|
||||||
channelCode = sendResponse.getChannelCode();
|
channelCode = sendResponse.getChannelCode();
|
||||||
// 发送成功后操作
|
// 发送成功后操作
|
||||||
for (SmsSendAfterSendHandler afterSendHandler : smsSendAfterSendHandlers) {
|
if (sendResponse.getSuccess()) {
|
||||||
if (afterSendHandler.checkTemplateType(message.getTemplateType())) {
|
for (KeyValue<String, Object> keyValue : templateParams) {
|
||||||
afterSendHandler.afterSend(sendResponse, templateParams);
|
if ("code".equals(keyValue.getKey())) {
|
||||||
|
redisTemplate.opsForValue().set(String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, sendResponse.getMobile()), keyValue.getValue(), smsCodeProperties.getExpireTimes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(),
|
smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(),
|
||||||
@@ -171,7 +149,7 @@ public class SmsSendServiceImpl implements SmsSendService {
|
|||||||
@Override
|
@Override
|
||||||
public void receiveSmsStatus(String channelCode, String text) throws Throwable {
|
public void receiveSmsStatus(String channelCode, String text) throws Throwable {
|
||||||
// 获得渠道对应的 SmsClient 客户端
|
// 获得渠道对应的 SmsClient 客户端
|
||||||
SmsClient smsClient = smsChannelService.getSmsClient(channelCode);
|
SmsClient smsClient = smsChannelService.getSmsClient();
|
||||||
Assert.notNull(smsClient, "短信客户端({}) 不存在", channelCode);
|
Assert.notNull(smsClient, "短信客户端({}) 不存在", channelCode);
|
||||||
// 解析内容
|
// 解析内容
|
||||||
List<SmsReceiveRespDTO> receiveResults = smsClient.parseSmsReceiveStatus(text);
|
List<SmsReceiveRespDTO> receiveResults = smsClient.parseSmsReceiveStatus(text);
|
||||||
|
|||||||
+1
-14
@@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
|
||||||
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
import com.cf.imes.framework.common.util.object.BeanUtils;
|
||||||
@@ -14,7 +13,6 @@ import com.cf.imes.module.system.framework.sms.core.client.dto.SmsTemplateRespDT
|
|||||||
import com.cf.imes.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
import com.cf.imes.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
import com.cf.imes.module.system.dal.mysql.sms.SmsTemplateMapper;
|
import com.cf.imes.module.system.dal.mysql.sms.SmsTemplateMapper;
|
||||||
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
||||||
@@ -122,18 +120,6 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
|
|||||||
return smsTemplateMapper.selectCountByChannelId(channelId);
|
return smsTemplateMapper.selectCountByChannelId(channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public SmsChannelDO validateSmsChannel(Long channelId) {
|
|
||||||
SmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId);
|
|
||||||
if (channelDO == null) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
if (CommonStatusEnum.isDisable(channelDO.getStatus())) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CHANNEL_DISABLE);
|
|
||||||
}
|
|
||||||
return channelDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void validateSmsTemplateCodeDuplicate(Long id, String code) {
|
public void validateSmsTemplateCodeDuplicate(Long id, String code) {
|
||||||
SmsTemplateDO template = smsTemplateMapper.selectByCode(code);
|
SmsTemplateDO template = smsTemplateMapper.selectByCode(code);
|
||||||
@@ -154,6 +140,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
|
|||||||
*
|
*
|
||||||
* @param apiTemplateId API 模板编号
|
* @param apiTemplateId API 模板编号
|
||||||
*/
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
void validateApiTemplate(String apiTemplateId) {
|
void validateApiTemplate(String apiTemplateId) {
|
||||||
// 获得短信模板
|
// 获得短信模板
|
||||||
SmsClient smsClient = smsChannelService.getSmsClient();
|
SmsClient smsClient = smsChannelService.getSmsClient();
|
||||||
|
|||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
package com.cf.imes.module.system.service.sms.handler;
|
|
||||||
|
|
||||||
import com.cf.imes.framework.common.core.KeyValue;
|
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信发送后处理器接口
|
|
||||||
*
|
|
||||||
* @author Gqr
|
|
||||||
* @since 2024/8/12 18:42
|
|
||||||
*/
|
|
||||||
public interface SmsSendAfterSendHandler {
|
|
||||||
/**
|
|
||||||
* 校验消息模板类型
|
|
||||||
*
|
|
||||||
* @param templateType
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean checkTemplateType(Integer templateType);
|
|
||||||
|
|
||||||
|
|
||||||
void afterSend(SmsSendRespDTO sendResponse, List<KeyValue<String, Object>> params);
|
|
||||||
}
|
|
||||||
-46
@@ -1,46 +0,0 @@
|
|||||||
package com.cf.imes.module.system.service.sms.handler.impl;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import com.cf.imes.framework.common.core.KeyValue;
|
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
|
||||||
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
|
||||||
import com.cf.imes.module.system.enums.sms.SmsTemplateTypeEnum;
|
|
||||||
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
|
||||||
import com.cf.imes.module.system.service.sms.handler.SmsSendAfterSendHandler;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gqr
|
|
||||||
* @since 2024/8/12 18:49
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class SmsSendAfterSendHandlerImpl implements SmsSendAfterSendHandler {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SmsCodeProperties smsCodeProperties;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTemplateType(Integer templateType) {
|
|
||||||
SmsTemplateTypeEnum smsTemplateTypeEnum = SmsTemplateTypeEnum.valueOf(templateType);
|
|
||||||
return ObjectUtil.isNotNull(smsTemplateTypeEnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterSend(SmsSendRespDTO sendResponse, List<KeyValue<String, Object>> params) {
|
|
||||||
// 发送成功把验证码存入redis
|
|
||||||
if (sendResponse.getSuccess()) {
|
|
||||||
for (KeyValue<String, Object> keyValue : params) {
|
|
||||||
if ("code".equals(keyValue.getKey())) {
|
|
||||||
redisTemplate.opsForValue().set(String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, sendResponse.getMobile()), keyValue.getValue(), smsCodeProperties.getExpireTimes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -133,7 +133,6 @@ logging:
|
|||||||
# 配置自己写的 MyBatis Mapper 打印日志
|
# 配置自己写的 MyBatis Mapper 打印日志
|
||||||
com.cf.imes.module.system.dal.mysql: debug
|
com.cf.imes.module.system.dal.mysql: debug
|
||||||
com.cf.imes.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO # 配置 SensitiveWordMapper 的日志级别为 info
|
com.cf.imes.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO # 配置 SensitiveWordMapper 的日志级别为 info
|
||||||
com.cf.imes.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
|
|
||||||
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO :先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
|
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO :先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
|
||||||
|
|
||||||
--- #################### 微信公众号、小程序相关配置 ####################
|
--- #################### 微信公众号、小程序相关配置 ####################
|
||||||
|
|||||||
-2
@@ -1,6 +1,5 @@
|
|||||||
package com.cf.imes.module.system.controller.admin.dept;
|
package com.cf.imes.module.system.controller.admin.dept;
|
||||||
|
|
||||||
import com.cf.imes.framework.security.test.WithMockLoginUser;
|
|
||||||
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
||||||
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
|
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
|
||||||
@@ -59,7 +58,6 @@ public class DeptControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithMockLoginUser(isSuperAdmin = true)
|
|
||||||
void testCreateDept() throws Exception {
|
void testCreateDept() throws Exception {
|
||||||
when(deptService.createDept(any())).thenReturn(123L);
|
when(deptService.createDept(any())).thenReturn(123L);
|
||||||
|
|
||||||
|
|||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
package com.cf.imes.module.system.controller.admin.sms;
|
||||||
|
|
||||||
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
|
import com.cf.imes.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
|
||||||
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsLogDO;
|
||||||
|
import com.cf.imes.module.system.service.sms.SmsLogService;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/10/10 15:37
|
||||||
|
*/
|
||||||
|
@WebMvcTest(controllers = SmsLogController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
|
||||||
|
public class SmsLogControllerTest {
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@MockitoBean
|
||||||
|
private SmsLogService smsLogService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
/**
|
||||||
|
* 测试分页查询接口
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetSmsLogPage_success() throws Exception {
|
||||||
|
// mock service 层返回分页结果
|
||||||
|
SmsLogDO logDO = new SmsLogDO();
|
||||||
|
logDO.setId(1L);
|
||||||
|
logDO.setMobile("13800000000");
|
||||||
|
logDO.setSendStatus(1);
|
||||||
|
PageResult<SmsLogDO> pageResult = new PageResult<>(Collections.singletonList(logDO), 1L);
|
||||||
|
Mockito.when(smsLogService.getSmsLogPage(any())).thenReturn(pageResult);
|
||||||
|
|
||||||
|
// 构造查询参数
|
||||||
|
SmsLogPageReqVO reqVO = new SmsLogPageReqVO();
|
||||||
|
reqVO.setPageNo(1);
|
||||||
|
reqVO.setPageSize(10);
|
||||||
|
|
||||||
|
// 执行请求
|
||||||
|
mockMvc.perform(get("/system/sms-log/page")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.param("pageNo", "1")
|
||||||
|
.param("pageSize", "10"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data.list[0].mobile").value("13800000000"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试导出 Excel 接口
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testExportSmsLogExcel_success() throws Exception {
|
||||||
|
// mock service 层返回数据
|
||||||
|
SmsLogDO logDO = new SmsLogDO();
|
||||||
|
logDO.setId(2L);
|
||||||
|
logDO.setMobile("13900000000");
|
||||||
|
PageResult<SmsLogDO> pageResult = new PageResult<>(List.of(logDO), 1L);
|
||||||
|
Mockito.when(smsLogService.getSmsLogPage(any())).thenReturn(pageResult);
|
||||||
|
|
||||||
|
// 执行请求
|
||||||
|
mockMvc.perform(get("/system/sms-log/export")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.param("pageNo", "1")
|
||||||
|
.param("pageSize", "10"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
// 校验响应头是下载 Excel 文件
|
||||||
|
.andExpect(header().string("Content-Disposition", org.hamcrest.Matchers.containsString("attachment")));
|
||||||
|
}
|
||||||
|
}
|
||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
package com.cf.imes.module.system.controller.admin.sms;
|
||||||
|
|
||||||
|
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
|
||||||
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO;
|
||||||
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
|
import com.cf.imes.module.system.enums.sms.SmsTemplateTypeEnum;
|
||||||
|
import com.cf.imes.module.system.service.sms.SmsSendService;
|
||||||
|
import com.cf.imes.module.system.service.sms.SmsTemplateService;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyMap;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.isNull;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2025/10/11 16:26
|
||||||
|
*/
|
||||||
|
@WebMvcTest(controllers = SmsTemplateController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
|
||||||
|
public class SmsTemplateControllerTest {
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@MockitoBean
|
||||||
|
private SmsTemplateService smsTemplateService;
|
||||||
|
|
||||||
|
@MockitoBean
|
||||||
|
private SmsSendService smsSendService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
// ========== create ==========
|
||||||
|
@Test
|
||||||
|
void testCreateSmsTemplate() throws Exception {
|
||||||
|
SmsTemplateSaveReqVO req = new SmsTemplateSaveReqVO();
|
||||||
|
req.setCode("REGISTER_CODE");
|
||||||
|
req.setName("注册验证码");
|
||||||
|
req.setContent("您的验证码是{code}");
|
||||||
|
req.setType(SmsTemplateTypeEnum.NOTICE.getType());
|
||||||
|
req.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
req.setApiTemplateId("TEMPLATE_001");
|
||||||
|
|
||||||
|
when(smsTemplateService.createSmsTemplate(any())).thenReturn(1L);
|
||||||
|
|
||||||
|
mockMvc.perform(post("/system/sms-template/create")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(req)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data").value(1));
|
||||||
|
|
||||||
|
verify(smsTemplateService, times(1)).createSmsTemplate(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== update ==========
|
||||||
|
@Test
|
||||||
|
void testUpdateSmsTemplate() throws Exception {
|
||||||
|
SmsTemplateSaveReqVO req = new SmsTemplateSaveReqVO();
|
||||||
|
req.setId(100L);
|
||||||
|
req.setCode("REGISTER_CODE");
|
||||||
|
req.setName("注册验证码");
|
||||||
|
req.setContent("您的验证码是{code}");
|
||||||
|
req.setType(SmsTemplateTypeEnum.NOTICE.getType());
|
||||||
|
req.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
req.setApiTemplateId("TEMPLATE_001");
|
||||||
|
|
||||||
|
doNothing().when(smsTemplateService).updateSmsTemplate(any());
|
||||||
|
|
||||||
|
mockMvc.perform(put("/system/sms-template/update")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(req)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data").value(true));
|
||||||
|
|
||||||
|
verify(smsTemplateService, times(1)).updateSmsTemplate(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== delete ==========
|
||||||
|
@Test
|
||||||
|
void testDeleteSmsTemplate() throws Exception {
|
||||||
|
doNothing().when(smsTemplateService).deleteSmsTemplate(1L);
|
||||||
|
|
||||||
|
mockMvc.perform(delete("/system/sms-template/delete")
|
||||||
|
.param("id", "1"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data").value(true));
|
||||||
|
|
||||||
|
verify(smsTemplateService, times(1)).deleteSmsTemplate(1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== get ==========
|
||||||
|
@Test
|
||||||
|
void testGetSmsTemplate() throws Exception {
|
||||||
|
SmsTemplateDO templateDO = new SmsTemplateDO();
|
||||||
|
templateDO.setId(1L);
|
||||||
|
templateDO.setCode("REGISTER_CODE");
|
||||||
|
templateDO.setName("注册验证码");
|
||||||
|
when(smsTemplateService.getSmsTemplate(1L)).thenReturn(templateDO);
|
||||||
|
|
||||||
|
mockMvc.perform(get("/system/sms-template/get")
|
||||||
|
.param("id", "1"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data.code").value("REGISTER_CODE"))
|
||||||
|
.andExpect(jsonPath("$.data.name").value("注册验证码"));
|
||||||
|
|
||||||
|
verify(smsTemplateService, times(1)).getSmsTemplate(1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== page ==========
|
||||||
|
@Test
|
||||||
|
void testGetSmsTemplatePage() throws Exception {
|
||||||
|
SmsTemplateDO templateDO = new SmsTemplateDO();
|
||||||
|
templateDO.setCode("REGISTER_CODE");
|
||||||
|
PageResult<SmsTemplateDO> pageResult = new PageResult<>(List.of(templateDO), 1L);
|
||||||
|
when(smsTemplateService.getSmsTemplatePage(any())).thenReturn(pageResult);
|
||||||
|
|
||||||
|
mockMvc.perform(get("/system/sms-template/page")
|
||||||
|
.param("pageNo", "1")
|
||||||
|
.param("pageSize", "10"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data.list[0].code").value("REGISTER_CODE"));
|
||||||
|
|
||||||
|
verify(smsTemplateService, times(1)).getSmsTemplatePage(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== send-sms ==========
|
||||||
|
@Test
|
||||||
|
void testSendSms() throws Exception {
|
||||||
|
SmsTemplateSendReqVO sendReqVO = new SmsTemplateSendReqVO();
|
||||||
|
sendReqVO.setMobile("13800000000");
|
||||||
|
sendReqVO.setTemplateCode("SMS_CODE");
|
||||||
|
sendReqVO.setTemplateParams(Map.of("code", "123456"));
|
||||||
|
|
||||||
|
when(smsSendService.sendSingleSms(anyString(), isNull(), anyInt(), anyString(), anyMap()))
|
||||||
|
.thenReturn(123L);
|
||||||
|
|
||||||
|
mockMvc.perform(post("/system/sms-template/send-sms")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(sendReqVO)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data").value(123));
|
||||||
|
|
||||||
|
verify(smsSendService, times(1)).sendSingleSms(
|
||||||
|
eq("13800000000"),
|
||||||
|
isNull(),
|
||||||
|
anyInt(),
|
||||||
|
eq("SMS_CODE"),
|
||||||
|
anyMap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== export ==========
|
||||||
|
@Test
|
||||||
|
void testExportSmsTemplateExcel() throws Exception {
|
||||||
|
SmsTemplateDO templateDO = new SmsTemplateDO();
|
||||||
|
templateDO.setId(1L);
|
||||||
|
templateDO.setCode("REGISTER_CODE");
|
||||||
|
templateDO.setName("注册验证码");
|
||||||
|
PageResult<SmsTemplateDO> pageResult = new PageResult<>(List.of(templateDO), 1L);
|
||||||
|
when(smsTemplateService.getSmsTemplatePage(any())).thenReturn(pageResult);
|
||||||
|
mockMvc.perform(get("/system/sms-template/export-excel")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.param("pageNo", "1")
|
||||||
|
.param("pageSize", "10"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
// 校验响应头是下载 Excel 文件
|
||||||
|
.andExpect(header().string("Content-Disposition", org.hamcrest.Matchers.containsString("attachment")));
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
-38
@@ -1,7 +1,6 @@
|
|||||||
package com.cf.imes.module.system.service.organ;
|
package com.cf.imes.module.system.service.organ;
|
||||||
|
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||||
import com.cf.imes.framework.common.exception.ServiceException;
|
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
import com.cf.imes.framework.organ.config.OrganProperties;
|
import com.cf.imes.framework.organ.config.OrganProperties;
|
||||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||||
@@ -14,27 +13,25 @@ import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
|||||||
import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO;
|
import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO;
|
||||||
import com.cf.imes.module.system.dal.mysql.organ.OrganMapper;
|
import com.cf.imes.module.system.dal.mysql.organ.OrganMapper;
|
||||||
import com.cf.imes.module.system.enums.permission.RoleCodeEnum;
|
import com.cf.imes.module.system.enums.permission.RoleCodeEnum;
|
||||||
import com.cf.imes.module.system.enums.permission.RoleTypeEnum;
|
|
||||||
import com.cf.imes.module.system.service.permission.MenuService;
|
import com.cf.imes.module.system.service.permission.MenuService;
|
||||||
import com.cf.imes.module.system.service.permission.PermissionService;
|
import com.cf.imes.module.system.service.permission.PermissionService;
|
||||||
import com.cf.imes.module.system.service.permission.RoleService;
|
import com.cf.imes.module.system.service.permission.RoleService;
|
||||||
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
|
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
|
||||||
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
|
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
|
||||||
import com.cf.imes.module.system.service.user.AdminUserService;
|
import com.cf.imes.module.system.service.user.AdminUserService;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
||||||
import static com.cf.imes.framework.common.util.collection.SetUtils.asSet;
|
import static com.cf.imes.framework.common.util.collection.SetUtils.asSet;
|
||||||
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
|
||||||
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||||
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
@@ -60,27 +57,27 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
@Resource
|
@Resource
|
||||||
private OrganMapper tenantMapper;
|
private OrganMapper tenantMapper;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private OrganProperties tenantProperties;
|
private OrganProperties tenantProperties;
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private TenantPackageService tenantPackageService;
|
private TenantPackageService tenantPackageService;
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private AdminUserService userService;
|
private AdminUserService userService;
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private RoleService roleService;
|
private RoleService roleService;
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private MenuService menuService;
|
private MenuService menuService;
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
void setUp() {
|
||||||
// 清理组织上下文
|
// 清理组织上下文
|
||||||
OrganContextHolder.clear();
|
OrganContextHolder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testgetOrganIdList() {
|
void testgetOrganIdList() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L));
|
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L));
|
||||||
tenantMapper.insert(tenant);
|
tenantMapper.insert(tenant);
|
||||||
@@ -91,12 +88,12 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidTenant_notExists() {
|
void testValidTenant_notExists() {
|
||||||
assertServiceException(() -> tenantService.validOrgan(randomLongId()), ORGAN_NOT_EXISTS);
|
assertServiceException(() -> tenantService.validOrgan(randomLongId()), ORGAN_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidTenant_disable() {
|
void testValidTenant_disable() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
||||||
tenantMapper.insert(tenant);
|
tenantMapper.insert(tenant);
|
||||||
@@ -106,10 +103,10 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidTenant_expired() {
|
void testValidTenant_expired() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
|
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
|
||||||
.setExpireTime(buildTime(2020, 2, 2)));
|
.setExpireTime(LocalDate.now().minusDays(1)));
|
||||||
tenantMapper.insert(tenant);
|
tenantMapper.insert(tenant);
|
||||||
|
|
||||||
// 调用,并断言业务异常
|
// 调用,并断言业务异常
|
||||||
@@ -117,10 +114,10 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidTenant_success() {
|
void testValidTenant_success() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
|
OrganizationDO tenant = randomPojo(OrganizationDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
|
||||||
.setExpireTime(LocalDateTime.now().plusDays(1)));
|
.setExpireTime(LocalDate.now().plusDays(1)));
|
||||||
tenantMapper.insert(tenant);
|
tenantMapper.insert(tenant);
|
||||||
|
|
||||||
// 调用,并断言业务异常
|
// 调用,并断言业务异常
|
||||||
@@ -128,7 +125,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateTenant() {
|
void testCreateTenant() {
|
||||||
// mock 套餐 100L
|
// mock 套餐 100L
|
||||||
TenantPackageDO tenantPackage = randomPojo(TenantPackageDO.class, o -> o.setId(100L));
|
TenantPackageDO tenantPackage = randomPojo(TenantPackageDO.class, o -> o.setId(100L));
|
||||||
when(tenantPackageService.validTenantPackage(eq(100L))).thenReturn(tenantPackage);
|
when(tenantPackageService.validTenantPackage(eq(100L))).thenReturn(tenantPackage);
|
||||||
@@ -175,7 +172,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateTenant_success() {
|
void testUpdateTenant_success() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setStatus(randomCommonStatus()));
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setStatus(randomCommonStatus()));
|
||||||
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -210,7 +207,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateTenant_notExists() {
|
void testUpdateTenant_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OrganSaveReqVO reqVO = randomPojo(OrganSaveReqVO.class);
|
OrganSaveReqVO reqVO = randomPojo(OrganSaveReqVO.class);
|
||||||
|
|
||||||
@@ -219,7 +216,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateTenant_system() {
|
void testUpdateTenant_system() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setPackageId(OrganizationDO.PACKAGE_ID_SYSTEM));
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setPackageId(OrganizationDO.PACKAGE_ID_SYSTEM));
|
||||||
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -233,7 +230,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteTenant_success() {
|
void testDeleteTenant_success() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class,
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class,
|
||||||
o -> o.setStatus(randomCommonStatus()));
|
o -> o.setStatus(randomCommonStatus()));
|
||||||
@@ -248,7 +245,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteTenant_notExists() {
|
void testDeleteTenant_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long id = randomLongId();
|
Long id = randomLongId();
|
||||||
|
|
||||||
@@ -257,7 +254,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteTenant_system() {
|
void testDeleteTenant_system() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setPackageId(OrganizationDO.PACKAGE_ID_SYSTEM));
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setPackageId(OrganizationDO.PACKAGE_ID_SYSTEM));
|
||||||
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -269,7 +266,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTenant() {
|
void testGetTenant() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class);
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class);
|
||||||
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -283,7 +280,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTenantPage() {
|
void testGetTenantPage() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> { // 等会查询到
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> { // 等会查询到
|
||||||
o.setName("晨丰科技");
|
o.setName("晨丰科技");
|
||||||
@@ -319,7 +316,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTenantByName() {
|
void testGetTenantByName() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setName("晨丰"));
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setName("晨丰"));
|
||||||
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -331,7 +328,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTenantByWebsite() {
|
void testGetTenantByWebsite() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setWebsite("https://www.cf.com"));
|
OrganizationDO dbTenant = randomPojo(OrganizationDO.class, o -> o.setWebsite("https://www.cf.com"));
|
||||||
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -343,7 +340,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTenantListByPackageId() {
|
void testGetTenantListByPackageId() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant1 = randomPojo(OrganizationDO.class, o -> o.setPackageId(1L));
|
OrganizationDO dbTenant1 = randomPojo(OrganizationDO.class, o -> o.setPackageId(1L));
|
||||||
tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -357,7 +354,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTenantCountByPackageId() {
|
void testGetTenantCountByPackageId() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OrganizationDO dbTenant1 = randomPojo(OrganizationDO.class, o -> o.setPackageId(1L));
|
OrganizationDO dbTenant1 = randomPojo(OrganizationDO.class, o -> o.setPackageId(1L));
|
||||||
tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
|
tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -370,7 +367,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandleTenantInfo_disable() {
|
void testHandleTenantInfo_disable() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OrganInfoHandler handler = mock(OrganInfoHandler.class);
|
OrganInfoHandler handler = mock(OrganInfoHandler.class);
|
||||||
// mock 禁用
|
// mock 禁用
|
||||||
@@ -383,7 +380,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandleTenantInfo_success() {
|
void testHandleTenantInfo_success() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OrganInfoHandler handler = mock(OrganInfoHandler.class);
|
OrganInfoHandler handler = mock(OrganInfoHandler.class);
|
||||||
// mock 未禁用
|
// mock 未禁用
|
||||||
@@ -403,7 +400,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandleTenantMenu_disable() {
|
void testHandleTenantMenu_disable() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OrganMenuHandler handler = mock(OrganMenuHandler.class);
|
OrganMenuHandler handler = mock(OrganMenuHandler.class);
|
||||||
// mock 禁用
|
// mock 禁用
|
||||||
@@ -416,7 +413,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test // 系统组织的情况
|
@Test // 系统组织的情况
|
||||||
public void testHandleTenantMenu_system() {
|
void testHandleTenantMenu_system() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OrganMenuHandler handler = mock(OrganMenuHandler.class);
|
OrganMenuHandler handler = mock(OrganMenuHandler.class);
|
||||||
// mock 未禁用
|
// mock 未禁用
|
||||||
@@ -436,7 +433,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test // 普通组织的情况
|
@Test // 普通组织的情况
|
||||||
public void testHandleTenantMenu_normal() {
|
void testHandleTenantMenu_normal() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OrganMenuHandler handler = mock(OrganMenuHandler.class);
|
OrganMenuHandler handler = mock(OrganMenuHandler.class);
|
||||||
// mock 未禁用
|
// mock 未禁用
|
||||||
|
|||||||
+18
-206
@@ -1,229 +1,41 @@
|
|||||||
package com.cf.imes.module.system.service.sms;
|
package com.cf.imes.module.system.service.sms;
|
||||||
|
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
import com.cf.imes.module.system.framework.sms.config.ChenfengSmsAutoConfiguration;
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClientFactory;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClientFactory;
|
||||||
|
import com.cf.imes.module.system.framework.sms.core.client.impl.aliyun.AliyunSmsClient;
|
||||||
|
import com.cf.imes.module.system.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient;
|
||||||
import com.cf.imes.module.system.framework.sms.core.enums.SmsChannelEnum;
|
import com.cf.imes.module.system.framework.sms.core.enums.SmsChannelEnum;
|
||||||
import com.cf.imes.module.system.framework.sms.core.property.SmsChannelProperties;
|
import com.cf.imes.module.system.framework.sms.core.property.SmsProperties;
|
||||||
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import com.cf.imes.module.system.dal.mysql.sms.SmsChannelMapper;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
|
||||||
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
|
||||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
|
|
||||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
|
||||||
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
|
||||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
|
|
||||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
@Import(SmsChannelServiceImpl.class)
|
|
||||||
|
@Import({SmsChannelServiceImpl.class, ChenfengSmsAutoConfiguration.class})
|
||||||
public class SmsChannelServiceTest extends BaseDbUnitTest {
|
public class SmsChannelServiceTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsChannelServiceImpl smsChannelService;
|
private SmsChannelServiceImpl smsChannelService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsChannelMapper smsChannelMapper;
|
private SmsProperties smsProperties; // 真实 Bean
|
||||||
|
|
||||||
@MockBean
|
@Resource
|
||||||
private SmsClientFactory smsClientFactory;
|
private SmsClientFactory smsClientFactory; // 真实 Bean
|
||||||
@MockBean
|
|
||||||
private SmsTemplateService smsTemplateService;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateSmsChannel_success() {
|
void testGetSmsClient_aliyun() {
|
||||||
// 准备参数
|
smsProperties.setChannel(SmsChannelEnum.ALIYUN.getCode());
|
||||||
SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class, o -> o.setStatus(randomCommonStatus()))
|
SmsClient aliyunClient = smsChannelService.getSmsClient();
|
||||||
.setId(null); // 防止 id 被赋值
|
assertThat(aliyunClient).isInstanceOf(AliyunSmsClient.class);
|
||||||
|
|
||||||
// 调用
|
smsProperties.setChannel(SmsChannelEnum.DEBUG_DING_TALK.getCode());
|
||||||
Long smsChannelId = smsChannelService.createSmsChannel(reqVO);
|
SmsClient dingDingClient = smsChannelService.getSmsClient();
|
||||||
// 断言
|
assertThat(dingDingClient).isInstanceOf(DebugDingTalkSmsClient.class);
|
||||||
assertNotNull(smsChannelId);
|
|
||||||
// 校验记录的属性是否正确
|
|
||||||
SmsChannelDO smsChannel = smsChannelMapper.selectById(smsChannelId);
|
|
||||||
assertPojoEquals(reqVO, smsChannel, "id");
|
|
||||||
// 断言 cache
|
|
||||||
assertNull(smsChannelService.getIdClientCache().getIfPresent(smsChannel.getId()));
|
|
||||||
assertNull(smsChannelService.getCodeClientCache().getIfPresent(smsChannel.getCode()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateSmsChannel_success() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据
|
|
||||||
// 准备参数
|
|
||||||
SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class, o -> {
|
|
||||||
o.setId(dbSmsChannel.getId()); // 设置更新的 ID
|
|
||||||
o.setStatus(randomCommonStatus());
|
|
||||||
o.setCallbackUrl(randomString());
|
|
||||||
});
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
smsChannelService.updateSmsChannel(reqVO);
|
|
||||||
// 校验是否更新正确
|
|
||||||
SmsChannelDO smsChannel = smsChannelMapper.selectById(reqVO.getId()); // 获取最新的
|
|
||||||
assertPojoEquals(reqVO, smsChannel);
|
|
||||||
// 断言 cache
|
|
||||||
assertNull(smsChannelService.getIdClientCache().getIfPresent(smsChannel.getId()));
|
|
||||||
assertNull(smsChannelService.getCodeClientCache().getIfPresent(smsChannel.getCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateSmsChannel_notExists() {
|
|
||||||
// 准备参数
|
|
||||||
SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class);
|
|
||||||
|
|
||||||
// 调用, 并断言异常
|
|
||||||
assertServiceException(() -> smsChannelService.updateSmsChannel(reqVO), SMS_CHANNEL_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeleteSmsChannel_success() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据
|
|
||||||
// 准备参数
|
|
||||||
Long id = dbSmsChannel.getId();
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
smsChannelService.deleteSmsChannel(id);
|
|
||||||
// 校验数据不存在了
|
|
||||||
assertNull(smsChannelMapper.selectById(id));
|
|
||||||
// 断言 cache
|
|
||||||
assertNull(smsChannelService.getIdClientCache().getIfPresent(dbSmsChannel.getId()));
|
|
||||||
assertNull(smsChannelService.getCodeClientCache().getIfPresent(dbSmsChannel.getCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeleteSmsChannel_notExists() {
|
|
||||||
// 准备参数
|
|
||||||
Long id = randomLongId();
|
|
||||||
|
|
||||||
// 调用, 并断言异常
|
|
||||||
assertServiceException(() -> smsChannelService.deleteSmsChannel(id), SMS_CHANNEL_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeleteSmsChannel_hasChildren() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据
|
|
||||||
// 准备参数
|
|
||||||
Long id = dbSmsChannel.getId();
|
|
||||||
// mock 方法
|
|
||||||
when(smsTemplateService.getSmsTemplateCountByChannelId(eq(id))).thenReturn(10L);
|
|
||||||
|
|
||||||
// 调用, 并断言异常
|
|
||||||
assertServiceException(() -> smsChannelService.deleteSmsChannel(id), SMS_CHANNEL_HAS_CHILDREN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSmsChannel() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(dbSmsChannel); // @Sql: 先插入出一条存在的数据
|
|
||||||
// 准备参数
|
|
||||||
Long id = dbSmsChannel.getId();
|
|
||||||
|
|
||||||
// 调用,并断言
|
|
||||||
assertPojoEquals(dbSmsChannel, smsChannelService.getSmsChannel(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSmsChannelList() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO dbSmsChannel01 = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(dbSmsChannel01);
|
|
||||||
SmsChannelDO dbSmsChannel02 = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(dbSmsChannel02);
|
|
||||||
// 准备参数
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
List<SmsChannelDO> list = smsChannelService.getSmsChannelList();
|
|
||||||
// 断言
|
|
||||||
assertEquals(2, list.size());
|
|
||||||
assertPojoEquals(dbSmsChannel01, list.get(0));
|
|
||||||
assertPojoEquals(dbSmsChannel02, list.get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSmsChannelPage() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到
|
|
||||||
o.setSignature("晨丰科技");
|
|
||||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
|
||||||
o.setCreateTime(buildTime(2020, 12, 12));
|
|
||||||
});
|
|
||||||
smsChannelMapper.insert(dbSmsChannel);
|
|
||||||
// 测试 signature 不匹配
|
|
||||||
smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码")));
|
|
||||||
// 测试 status 不匹配
|
|
||||||
smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
|
||||||
// 测试 createTime 不匹配
|
|
||||||
smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11))));
|
|
||||||
// 准备参数
|
|
||||||
SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO();
|
|
||||||
reqVO.setSignature("晨丰");
|
|
||||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
|
||||||
reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24));
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
PageResult<SmsChannelDO> pageResult = smsChannelService.getSmsChannelPage(reqVO);
|
|
||||||
// 断言
|
|
||||||
assertEquals(1, pageResult.getTotal());
|
|
||||||
assertEquals(1, pageResult.getList().size());
|
|
||||||
assertPojoEquals(dbSmsChannel, pageResult.getList().get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSmsClient_id() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO channel = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(channel);
|
|
||||||
// mock 参数
|
|
||||||
Long id = channel.getId();
|
|
||||||
// mock 方法
|
|
||||||
SmsClient mockClient = mock(SmsClient.class);
|
|
||||||
when(smsClientFactory.getSmsClient(eq(SmsChannelEnum.ALIYUN.getCode()))).thenReturn(mockClient);
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
SmsClient client = smsChannelService.getSmsClient(id);
|
|
||||||
// 断言
|
|
||||||
assertSame(client, mockClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSmsClient_code() {
|
|
||||||
// mock 数据
|
|
||||||
SmsChannelDO channel = randomPojo(SmsChannelDO.class);
|
|
||||||
smsChannelMapper.insert(channel);
|
|
||||||
// mock 参数
|
|
||||||
String code = channel.getCode();
|
|
||||||
// mock 方法
|
|
||||||
SmsClient mockClient = mock(SmsClient.class);
|
|
||||||
when(smsClientFactory.getSmsClient(eq(code))).thenReturn(mockClient);
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
SmsClient client = smsChannelService.getSmsClient(code);
|
|
||||||
// 断言
|
|
||||||
assertSame(client, mockClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+291
-147
@@ -1,209 +1,353 @@
|
|||||||
package com.cf.imes.module.system.service.sms;
|
package com.cf.imes.module.system.service.sms;
|
||||||
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
import com.cf.imes.framework.mybatis.core.enums.SqlConstants;
|
import com.cf.imes.framework.security.test.WithMockLoginUser;
|
||||||
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
|
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||||
|
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
|
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsCodeDO;
|
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import com.cf.imes.module.system.dal.mysql.sms.SmsCodeMapper;
|
|
||||||
import com.cf.imes.module.system.enums.sms.SmsSceneEnum;
|
import com.cf.imes.module.system.enums.sms.SmsSceneEnum;
|
||||||
|
import com.cf.imes.module.system.framework.sms.config.SmsCodeConfiguration;
|
||||||
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
||||||
import com.baomidou.mybatisplus.annotation.DbType;
|
import com.cf.imes.module.system.service.user.AdminUserService;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.mockito.Mockito;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.time.Duration;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import java.time.LocalDateTime;
|
import org.springframework.data.redis.core.ValueOperations;
|
||||||
|
import org.springframework.data.redis.core.ZSetOperations;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
|
||||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
|
|
||||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS;
|
||||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.AUTH_MOBILE_NO_CHANGE;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SMS_CODE_IS_VALID;
|
||||||
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SMS_CODE_NOT_CORRECT;
|
||||||
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SMS_CODE_NOT_FOUND;
|
||||||
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SMS_CODE_SEND_TOO_FAST;
|
||||||
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyMap;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.isNull;
|
import static org.mockito.ArgumentMatchers.isNull;
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@Import(SmsCodeServiceImpl.class)
|
@Import({SmsCodeServiceImpl.class, SmsCodeConfiguration.class})
|
||||||
public class SmsCodeServiceImplTest extends BaseDbUnitTest {
|
public class SmsCodeServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsCodeServiceImpl smsCodeService;
|
private SmsCodeServiceImpl smsCodeService;
|
||||||
|
|
||||||
@Resource
|
@MockitoBean
|
||||||
private SmsCodeMapper smsCodeMapper;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
|
private ZSetOperations<String, Object> zSetOperations;
|
||||||
|
|
||||||
|
@MockitoBean
|
||||||
|
private ValueOperations<String, Object> valueOperations;
|
||||||
|
|
||||||
|
@MockitoBean
|
||||||
|
private AdminUserService userService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
private SmsCodeProperties smsCodeProperties;
|
private SmsCodeProperties smsCodeProperties;
|
||||||
@MockBean
|
|
||||||
|
@MockitoBean
|
||||||
private SmsSendService smsSendService;
|
private SmsSendService smsSendService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
void setup() {
|
||||||
when(smsCodeProperties.getExpireTimes()).thenReturn(Duration.ofMinutes(5));
|
when(redisTemplate.opsForZSet()).thenReturn(zSetOperations);
|
||||||
when(smsCodeProperties.getSendFrequency()).thenReturn(Duration.ofMinutes(1));
|
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
||||||
when(smsCodeProperties.getSendMaximumQuantityPerDay()).thenReturn(10);
|
|
||||||
when(smsCodeProperties.getBeginCode()).thenReturn(9999);
|
|
||||||
when(smsCodeProperties.getEndCode()).thenReturn(9999);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendSmsCode_success() {
|
@WithMockLoginUser(userId = 1L)
|
||||||
// 准备参数
|
void testSendSmsCode_userUpdateMobile_noChange() {
|
||||||
SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
o.setMobile("15601691300");
|
reqDTO.setMobile("12345678901");
|
||||||
o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene());
|
reqDTO.setScene(SmsSceneEnum.USER_UPDATE_MOBILE.getScene());
|
||||||
});
|
|
||||||
// mock 方法
|
AdminUserDO user = new AdminUserDO();
|
||||||
SqlConstants.init(DbType.MYSQL);
|
user.setId(1L);
|
||||||
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(user);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), AUTH_MOBILE_NO_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSendSmsCode_notLogin() {
|
||||||
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
|
reqDTO.setMobile("12345678901");
|
||||||
|
reqDTO.setScene(SmsSceneEnum.USER_UPDATE_MOBILE.getScene());
|
||||||
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(null);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockLoginUser
|
||||||
|
void testSendSmsCode_userUpdateMobile_exists() {
|
||||||
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
|
reqDTO.setMobile("12345678901");
|
||||||
|
reqDTO.setScene(SmsSceneEnum.USER_UPDATE_MOBILE.getScene());
|
||||||
|
|
||||||
|
AdminUserDO user = new AdminUserDO();
|
||||||
|
user.setId(2L);
|
||||||
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(user);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), USER_MOBILE_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockLoginUser
|
||||||
|
void testSendSmsCode_nonUpdateMobile_userNotExist() {
|
||||||
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
|
reqDTO.setMobile("12345678901");
|
||||||
|
reqDTO.setScene(SmsSceneEnum.USER_RESET_PASSWORD.getScene());
|
||||||
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(null);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), AUTH_MOBILE_NOT_EXISTS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockLoginUser
|
||||||
|
void testSendSmsCode_userUpdateMobile_success() {
|
||||||
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
|
reqDTO.setMobile("12345678901");
|
||||||
|
reqDTO.setScene(SmsSceneEnum.USER_UPDATE_MOBILE.getScene());
|
||||||
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(null);
|
||||||
|
|
||||||
// 调用
|
|
||||||
smsCodeService.sendSmsCode(reqDTO);
|
smsCodeService.sendSmsCode(reqDTO);
|
||||||
// 断言 code 验证码
|
|
||||||
SmsCodeDO smsCodeDO = smsCodeMapper.selectOne(null);
|
Mockito.verify(smsSendService).sendSingleSms(eq("12345678901"), isNull(), isNull(), anyString(), anyMap());
|
||||||
assertPojoEquals(reqDTO, smsCodeDO);
|
|
||||||
assertEquals("9999", smsCodeDO.getCode());
|
|
||||||
assertEquals(1, smsCodeDO.getTodayIndex());
|
|
||||||
assertFalse(smsCodeDO.getUsed());
|
|
||||||
// 断言调用
|
|
||||||
verify(smsSendService).sendSingleSms(eq(reqDTO.getMobile()), isNull(), isNull(),
|
|
||||||
eq("user-sms-login"), eq(MapUtil.of("code", "9999")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendSmsCode_tooFast() {
|
@WithMockLoginUser
|
||||||
// mock 数据
|
void testSendSmsCode_success() {
|
||||||
SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class,
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
o -> o.setMobile("15601691300").setTodayIndex(1));
|
reqDTO.setMobile("12345678901");
|
||||||
smsCodeMapper.insert(smsCodeDO);
|
reqDTO.setScene(SmsSceneEnum.USER_RESET_PASSWORD.getScene());
|
||||||
// 准备参数
|
reqDTO.setCreateIp("127.0.0.1");
|
||||||
SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
|
|
||||||
o.setMobile("15601691300");
|
|
||||||
o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene());
|
|
||||||
});
|
|
||||||
// mock 方法
|
|
||||||
SqlConstants.init(DbType.MYSQL);
|
|
||||||
|
|
||||||
// 调用,并断言异常
|
AdminUserDO user = new AdminUserDO();
|
||||||
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO),
|
user.setId(1L);
|
||||||
SMS_CODE_SEND_TOO_FAST);
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(user);
|
||||||
|
|
||||||
|
when(redisTemplate.hasKey(anyString())).thenReturn(false);
|
||||||
|
when(zSetOperations.zCard(anyString())).thenReturn(0L);
|
||||||
|
when(zSetOperations.add(anyString(), any(), anyDouble())).thenReturn(true);
|
||||||
|
when(redisTemplate.expire(anyString(), anyLong(), any(TimeUnit.class))).thenReturn(true);
|
||||||
|
|
||||||
|
when(smsSendService.sendSingleSms(
|
||||||
|
Mockito.eq("12345678901"),
|
||||||
|
Mockito.isNull(),
|
||||||
|
Mockito.isNull(),
|
||||||
|
Mockito.anyString(),
|
||||||
|
Mockito.anyMap()
|
||||||
|
)).thenReturn(123L); // 返回一个模拟的日志ID
|
||||||
|
|
||||||
|
smsCodeService.sendSmsCode(reqDTO);
|
||||||
|
|
||||||
|
Mockito.verify(smsSendService).sendSingleSms(eq("12345678901"), isNull(), isNull(), anyString(), anyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendSmsCode_exceedDay() {
|
@WithMockLoginUser
|
||||||
// mock 数据
|
void testSendSmsCode_moblibe_sendToFast() {
|
||||||
SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class,
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
o -> o.setMobile("15601691300").setTodayIndex(10).setCreateTime(LocalDateTime.now()));
|
reqDTO.setMobile("12345678901");
|
||||||
smsCodeMapper.insert(smsCodeDO);
|
reqDTO.setScene(SmsSceneEnum.USER_RESET_PASSWORD.getScene());
|
||||||
// 准备参数
|
reqDTO.setCreateIp("127.0.0.1");
|
||||||
SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
|
|
||||||
o.setMobile("15601691300");
|
AdminUserDO user = new AdminUserDO();
|
||||||
o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene());
|
user.setId(1L);
|
||||||
});
|
|
||||||
// mock 方法
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
SqlConstants.init(DbType.MYSQL);
|
.thenReturn(user);
|
||||||
when(smsCodeProperties.getSendFrequency()).thenReturn(Duration.ofMillis(0));
|
|
||||||
|
// 模拟redis校验发送次数为6次
|
||||||
|
when(zSetOperations.zCard(anyString())).thenReturn(6L);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), SMS_CODE_SEND_TOO_FAST);
|
||||||
|
|
||||||
// 调用,并断言异常
|
|
||||||
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO),
|
|
||||||
SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUseSmsCode_success() {
|
@WithMockLoginUser
|
||||||
// 准备参数
|
void testSendSmsCode_ip_sendToFast() {
|
||||||
SmsCodeUseReqDTO reqDTO = randomPojo(SmsCodeUseReqDTO.class, o -> {
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
o.setMobile("15601691300");
|
reqDTO.setMobile("12345678901");
|
||||||
o.setScene(randomEle(SmsSceneEnum.values()).getScene());
|
reqDTO.setScene(SmsSceneEnum.USER_RESET_PASSWORD.getScene());
|
||||||
});
|
reqDTO.setCreateIp("127.0.0.1");
|
||||||
// mock 数据
|
|
||||||
SqlConstants.init(DbType.MYSQL);
|
AdminUserDO user = new AdminUserDO();
|
||||||
smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> {
|
user.setId(1L);
|
||||||
o.setMobile(reqDTO.getMobile()).setScene(reqDTO.getScene())
|
|
||||||
.setCode(reqDTO.getCode()).setUsed(false);
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
}));
|
.thenReturn(user);
|
||||||
|
|
||||||
|
// 模拟redis校验发送次数为6次
|
||||||
|
when(zSetOperations.zCard(anyString())).thenReturn(6L);
|
||||||
|
|
||||||
|
SmsCodeServiceImpl spyService = Mockito.spy(smsCodeService);
|
||||||
|
|
||||||
|
// 首次手机号校验发送次数返回true
|
||||||
|
Mockito.doReturn(true)
|
||||||
|
.doReturn(false)
|
||||||
|
.when(spyService)
|
||||||
|
.slidingWindowRateLimit(Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt());
|
||||||
|
|
||||||
|
assertServiceException(() -> spyService.sendSmsCode(reqDTO), SMS_CODE_SEND_TOO_FAST);
|
||||||
|
|
||||||
// 调用
|
|
||||||
smsCodeService.useSmsCode(reqDTO);
|
|
||||||
// 断言
|
|
||||||
SmsCodeDO smsCodeDO = smsCodeMapper.selectOne(null);
|
|
||||||
assertTrue(smsCodeDO.getUsed());
|
|
||||||
assertNotNull(smsCodeDO.getUsedTime());
|
|
||||||
assertEquals(reqDTO.getUsedIp(), smsCodeDO.getUsedIp());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateSmsCode_success() {
|
void testSendSmsCode_codeExists() {
|
||||||
// 准备参数
|
SmsCodeSendReqDTO reqDTO = new SmsCodeSendReqDTO();
|
||||||
SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
|
reqDTO.setMobile("12345678901");
|
||||||
o.setMobile("15601691300");
|
reqDTO.setScene(SmsSceneEnum.USER_RESET_PASSWORD.getScene());
|
||||||
o.setScene(randomEle(SmsSceneEnum.values()).getScene());
|
|
||||||
});
|
|
||||||
// mock 数据
|
|
||||||
SqlConstants.init(DbType.MYSQL);
|
|
||||||
smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile())
|
|
||||||
.setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(false)));
|
|
||||||
|
|
||||||
// 调用
|
AdminUserDO user = new AdminUserDO();
|
||||||
smsCodeService.validateSmsCode(reqDTO);
|
user.setId(1L);
|
||||||
|
|
||||||
|
when(userService.getUserByUsernameAndOrganId(anyString(), any()))
|
||||||
|
.thenReturn(user);
|
||||||
|
|
||||||
|
// 模拟验证码已存在
|
||||||
|
when(redisTemplate.hasKey(anyString())).thenReturn(true);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), SMS_CODE_IS_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateSmsCode_notFound() {
|
void testUseSmsCode_userNotExists() {
|
||||||
// 准备参数
|
SmsCodeUseReqDTO req = SmsCodeUseReqDTO.builder()
|
||||||
SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
|
.mobile("13800000000")
|
||||||
o.setMobile("15601691300");
|
.build();
|
||||||
o.setScene(randomEle(SmsSceneEnum.values()).getScene());
|
|
||||||
});
|
|
||||||
// mock 数据
|
|
||||||
SqlConstants.init(DbType.MYSQL);
|
|
||||||
|
|
||||||
// 调用,并断言异常
|
when(userService.getUserUniqueByUserName(req.getMobile())).thenReturn(null);
|
||||||
assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO),
|
|
||||||
SMS_CODE_NOT_FOUND);
|
assertServiceException(() -> smsCodeService.useSmsCode(req), AUTH_MOBILE_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateSmsCode_expired() {
|
void testUseSmsCode_codeNotFound() {
|
||||||
// 准备参数
|
SmsCodeUseReqDTO req = SmsCodeUseReqDTO.builder()
|
||||||
SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
|
.mobile("13800000000")
|
||||||
o.setMobile("15601691300");
|
.scene(SmsSceneEnum.USER_RESET_PASSWORD.getScene())
|
||||||
o.setScene(randomEle(SmsSceneEnum.values()).getScene());
|
.code("123456")
|
||||||
});
|
.build();
|
||||||
// mock 数据
|
|
||||||
SqlConstants.init(DbType.MYSQL);
|
|
||||||
smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile())
|
|
||||||
.setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(false)
|
|
||||||
.setCreateTime(LocalDateTime.now().minusMinutes(6))));
|
|
||||||
|
|
||||||
// 调用,并断言异常
|
when(userService.getUserUniqueByUserName(req.getMobile())).thenReturn(new AdminUserDO());
|
||||||
assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO),
|
when(valueOperations.get(Mockito.anyString())).thenReturn(null);
|
||||||
SMS_CODE_EXPIRED);
|
|
||||||
|
assertServiceException(() -> smsCodeService.useSmsCode(req), SMS_CODE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateSmsCode_used() {
|
void testUseSmsCode_codeIncorrect_shouldThrow() {
|
||||||
// 准备参数
|
SmsCodeUseReqDTO req = SmsCodeUseReqDTO.builder()
|
||||||
SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
|
.mobile("13800000000")
|
||||||
o.setMobile("15601691300");
|
.scene(SmsSceneEnum.USER_RESET_PASSWORD.getScene())
|
||||||
o.setScene(randomEle(SmsSceneEnum.values()).getScene());
|
.code("654321")
|
||||||
});
|
.build();
|
||||||
// mock 数据
|
|
||||||
SqlConstants.init(DbType.MYSQL);
|
|
||||||
smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile())
|
|
||||||
.setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(true)
|
|
||||||
.setCreateTime(LocalDateTime.now())));
|
|
||||||
|
|
||||||
// 调用,并断言异常
|
when(userService.getUserUniqueByUserName(req.getMobile())).thenReturn(new AdminUserDO());
|
||||||
assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO),
|
when(valueOperations.get(Mockito.anyString())).thenReturn("123456");
|
||||||
SMS_CODE_USED);
|
|
||||||
|
assertServiceException(() -> smsCodeService.useSmsCode(req), SMS_CODE_NOT_CORRECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUseSmsCode_success() {
|
||||||
|
SmsCodeUseReqDTO req = SmsCodeUseReqDTO.builder()
|
||||||
|
.mobile("13800000000")
|
||||||
|
.scene(SmsSceneEnum.USER_UPDATE_MOBILE.getScene())
|
||||||
|
.code("123456")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
when(userService.getUserUniqueByUserName(req.getMobile())).thenReturn(null);
|
||||||
|
when(valueOperations.get(Mockito.anyString())).thenReturn("123456");
|
||||||
|
|
||||||
|
smsCodeService.useSmsCode(req);
|
||||||
|
|
||||||
|
Mockito.verify(redisTemplate).delete(Mockito.anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testValidateSmsCode_userNotExists_shouldThrowAuthMobileNotExists() {
|
||||||
|
AuthLoginSmsCheckReqVO reqVO = new AuthLoginSmsCheckReqVO();
|
||||||
|
reqVO.setMobile("13800000000");
|
||||||
|
|
||||||
|
when(userService.getUserUniqueByUserName("13800000000")).thenReturn(null);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.validateSmsCode(reqVO), AUTH_MOBILE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testValidateSmsCode_smsCodeNotFound_shouldThrowSmsCodeNotFound() {
|
||||||
|
AuthLoginSmsCheckReqVO reqVO = new AuthLoginSmsCheckReqVO();
|
||||||
|
reqVO.setMobile("13800000000");
|
||||||
|
|
||||||
|
when(userService.getUserUniqueByUserName("13800000000")).thenReturn(new AdminUserDO());
|
||||||
|
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
||||||
|
when(valueOperations.get(anyString())).thenReturn(null);
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.validateSmsCode(reqVO), SMS_CODE_NOT_FOUND);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testValidateSmsCode_smsCodeNotCorrect_shouldThrowSmsCodeNotCorrect() {
|
||||||
|
AuthLoginSmsCheckReqVO reqVO = new AuthLoginSmsCheckReqVO();
|
||||||
|
reqVO.setMobile("13800000000");
|
||||||
|
reqVO.setSmsCaptchaVerification("123456");
|
||||||
|
|
||||||
|
when(userService.getUserUniqueByUserName("13800000000")).thenReturn(new AdminUserDO());
|
||||||
|
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
||||||
|
when(valueOperations.get(anyString())).thenReturn("999999");
|
||||||
|
|
||||||
|
assertServiceException(() -> smsCodeService.validateSmsCode(reqVO), SMS_CODE_NOT_CORRECT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testValidateSmsCode_smsCodeCorrect_shouldPass() {
|
||||||
|
AuthLoginSmsCheckReqVO reqVO = new AuthLoginSmsCheckReqVO();
|
||||||
|
reqVO.setMobile("13800000000");
|
||||||
|
reqVO.setSmsCaptchaVerification("123456");
|
||||||
|
|
||||||
|
when(userService.getUserUniqueByUserName("13800000000")).thenReturn(new AdminUserDO());
|
||||||
|
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
||||||
|
when(valueOperations.get(anyString())).thenReturn("123456");
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> smsCodeService.validateSmsCode(reqVO));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-18
@@ -4,7 +4,7 @@ import cn.hutool.core.map.MapUtil;
|
|||||||
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
import com.cf.imes.framework.common.util.collection.ArrayUtils;
|
import com.cf.imes.framework.common.util.collection.ArrayUtils;
|
||||||
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
|
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
|
import com.cf.imes.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsLogDO;
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsLogDO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
@@ -16,6 +16,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -31,7 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
@Import(SmsLogServiceImpl.class)
|
@Import(SmsLogServiceImpl.class)
|
||||||
public class SmsLogServiceImplTest extends BaseDbUnitTest {
|
public class SmsLogServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsLogServiceImpl smsLogService;
|
private SmsLogServiceImpl smsLogService;
|
||||||
@@ -40,7 +41,7 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest {
|
|||||||
private SmsLogMapper smsLogMapper;
|
private SmsLogMapper smsLogMapper;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSmsLogPage() {
|
void testGetSmsLogPage() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到
|
SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到
|
||||||
o.setChannelId(1L);
|
o.setChannelId(1L);
|
||||||
@@ -85,7 +86,7 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateSmsLog() {
|
void testCreateSmsLog() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String mobile = randomString();
|
String mobile = randomString();
|
||||||
Long userId = randomLongId();
|
Long userId = randomLongId();
|
||||||
@@ -102,30 +103,26 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest {
|
|||||||
templateDO, templateContent, templateParams);
|
templateDO, templateContent, templateParams);
|
||||||
// 断言
|
// 断言
|
||||||
SmsLogDO logDO = smsLogMapper.selectById(logId);
|
SmsLogDO logDO = smsLogMapper.selectById(logId);
|
||||||
assertEquals(isSend ? SmsSendStatusEnum.INIT.getStatus() : SmsSendStatusEnum.IGNORE.getStatus(),
|
assertEquals(SmsSendStatusEnum.INIT.getStatus(), logDO.getSendStatus());
|
||||||
logDO.getSendStatus());
|
|
||||||
assertEquals(mobile, logDO.getMobile());
|
assertEquals(mobile, logDO.getMobile());
|
||||||
assertEquals(userType, logDO.getUserType());
|
assertEquals(userType, logDO.getUserType());
|
||||||
assertEquals(userId, logDO.getUserId());
|
assertEquals(userId, logDO.getUserId());
|
||||||
assertEquals(templateDO.getId(), logDO.getTemplateId());
|
assertEquals(templateDO.getId(), logDO.getTemplateId());
|
||||||
assertEquals(templateDO.getCode(), logDO.getTemplateCode());
|
assertEquals(templateDO.getCode(), logDO.getTemplateCode());
|
||||||
assertEquals(templateDO.getType(), logDO.getTemplateType());
|
assertEquals(templateDO.getType(), logDO.getTemplateType());
|
||||||
assertEquals(templateDO.getChannelId(), logDO.getChannelId());
|
|
||||||
assertEquals(templateDO.getChannelCode(), logDO.getChannelCode());
|
|
||||||
assertEquals(templateContent, logDO.getTemplateContent());
|
assertEquals(templateContent, logDO.getTemplateContent());
|
||||||
assertEquals(templateParams, logDO.getTemplateParams());
|
assertEquals(templateParams, logDO.getTemplateParams());
|
||||||
assertEquals(SmsReceiveStatusEnum.INIT.getStatus(), logDO.getReceiveStatus());
|
assertEquals(SmsReceiveStatusEnum.INIT.getStatus(), logDO.getReceiveStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateSmsSendResult() {
|
void testUpdateSmsSendResult() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsLogDO dbSmsLog = randomSmsLogDO(
|
SmsLogDO dbSmsLog = randomSmsLogDO(
|
||||||
o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()));
|
o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()));
|
||||||
smsLogMapper.insert(dbSmsLog);
|
smsLogMapper.insert(dbSmsLog);
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long id = dbSmsLog.getId();
|
Long id = dbSmsLog.getId();
|
||||||
Boolean success = randomBoolean();
|
|
||||||
String apiSendCode = randomString();
|
String apiSendCode = randomString();
|
||||||
String apiSendMsg = randomString();
|
String apiSendMsg = randomString();
|
||||||
String apiRequestId = randomString();
|
String apiRequestId = randomString();
|
||||||
@@ -133,41 +130,51 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest {
|
|||||||
String channelCode = randomString();
|
String channelCode = randomString();
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
smsLogService.updateSmsSendResult(id, success,
|
smsLogService.updateSmsSendResult(id, true,
|
||||||
apiSendCode, apiSendMsg, apiRequestId, apiSerialNo, channelCode);
|
apiSendCode, apiSendMsg, apiRequestId, apiSerialNo, channelCode);
|
||||||
// 断言
|
// 断言
|
||||||
dbSmsLog = smsLogMapper.selectById(id);
|
dbSmsLog = smsLogMapper.selectById(id);
|
||||||
assertEquals(success ? SmsSendStatusEnum.SUCCESS.getStatus() : SmsSendStatusEnum.FAILURE.getStatus(),
|
assertEquals(SmsSendStatusEnum.SUCCESS.getStatus(), dbSmsLog.getSendStatus());
|
||||||
dbSmsLog.getSendStatus());
|
|
||||||
assertNotNull(dbSmsLog.getSendTime());
|
assertNotNull(dbSmsLog.getSendTime());
|
||||||
assertEquals(apiSendCode, dbSmsLog.getApiSendCode());
|
assertEquals(apiSendCode, dbSmsLog.getApiSendCode());
|
||||||
assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg());
|
assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg());
|
||||||
assertEquals(apiRequestId, dbSmsLog.getApiRequestId());
|
assertEquals(apiRequestId, dbSmsLog.getApiRequestId());
|
||||||
assertEquals(apiSerialNo, dbSmsLog.getApiSerialNo());
|
assertEquals(apiSerialNo, dbSmsLog.getApiSerialNo());
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
smsLogService.updateSmsSendResult(id, false,
|
||||||
|
apiSendCode, apiSendMsg, apiRequestId, apiSerialNo, channelCode);
|
||||||
|
// 断言
|
||||||
|
dbSmsLog = smsLogMapper.selectById(id);
|
||||||
|
assertEquals(SmsSendStatusEnum.FAILURE.getStatus(), dbSmsLog.getSendStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateSmsReceiveResult() {
|
void testUpdateSmsReceiveResult() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsLogDO dbSmsLog = randomSmsLogDO(
|
SmsLogDO dbSmsLog = randomSmsLogDO(
|
||||||
o -> o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()));
|
o -> o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()));
|
||||||
smsLogMapper.insert(dbSmsLog);
|
smsLogMapper.insert(dbSmsLog);
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long id = dbSmsLog.getId();
|
Long id = dbSmsLog.getId();
|
||||||
Boolean success = randomBoolean();
|
|
||||||
LocalDateTime receiveTime = randomLocalDateTime();
|
LocalDateTime receiveTime = randomLocalDateTime();
|
||||||
String apiReceiveCode = randomString();
|
String apiReceiveCode = randomString();
|
||||||
String apiReceiveMsg = randomString();
|
String apiReceiveMsg = randomString();
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
smsLogService.updateSmsReceiveResult(id, success, receiveTime, apiReceiveCode, apiReceiveMsg);
|
smsLogService.updateSmsReceiveResult(id, true, receiveTime, apiReceiveCode, apiReceiveMsg);
|
||||||
// 断言
|
// 断言
|
||||||
dbSmsLog = smsLogMapper.selectById(id);
|
dbSmsLog = smsLogMapper.selectById(id);
|
||||||
assertEquals(success ? SmsReceiveStatusEnum.SUCCESS.getStatus()
|
assertEquals(SmsReceiveStatusEnum.SUCCESS.getStatus(), dbSmsLog.getReceiveStatus());
|
||||||
: SmsReceiveStatusEnum.FAILURE.getStatus(), dbSmsLog.getReceiveStatus());
|
|
||||||
assertEquals(receiveTime, dbSmsLog.getReceiveTime());
|
assertEquals(receiveTime, dbSmsLog.getReceiveTime());
|
||||||
assertEquals(apiReceiveCode, dbSmsLog.getApiReceiveCode());
|
assertEquals(apiReceiveCode, dbSmsLog.getApiReceiveCode());
|
||||||
assertEquals(apiReceiveMsg, dbSmsLog.getApiReceiveMsg());
|
assertEquals(apiReceiveMsg, dbSmsLog.getApiReceiveMsg());
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
smsLogService.updateSmsReceiveResult(id, false, receiveTime, apiReceiveCode, apiReceiveMsg);
|
||||||
|
// 断言
|
||||||
|
dbSmsLog = smsLogMapper.selectById(id);
|
||||||
|
assertEquals(SmsReceiveStatusEnum.FAILURE.getStatus(), dbSmsLog.getReceiveStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 随机对象 ==========
|
// ========== 随机对象 ==========
|
||||||
|
|||||||
+97
-111
@@ -4,23 +4,26 @@ import cn.hutool.core.map.MapUtil;
|
|||||||
import com.cf.imes.framework.common.core.KeyValue;
|
import com.cf.imes.framework.common.core.KeyValue;
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||||
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
||||||
|
import com.cf.imes.framework.test.core.ut.BaseRedisUnitTest;
|
||||||
|
import com.cf.imes.module.system.framework.sms.config.SmsCodeConfiguration;
|
||||||
|
import com.cf.imes.module.system.framework.sms.config.SmsCodeProperties;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||||
import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
|
||||||
import com.cf.imes.module.system.mq.message.sms.SmsSendMessage;
|
import com.cf.imes.module.system.mq.message.sms.SmsSendMessage;
|
||||||
import com.cf.imes.module.system.mq.producer.sms.SmsProducer;
|
import com.cf.imes.module.system.mq.producer.sms.SmsProducer;
|
||||||
import com.cf.imes.module.system.service.member.MemberService;
|
import jakarta.annotation.Resource;
|
||||||
import com.cf.imes.module.system.service.user.AdminUserService;
|
|
||||||
import org.assertj.core.util.Lists;
|
import org.assertj.core.util.Lists;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InjectMocks;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.mockito.Mock;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.ValueOperations;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -29,110 +32,46 @@ import static cn.hutool.core.util.RandomUtil.randomEle;
|
|||||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
||||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
@Import({SmsSendServiceImpl.class, SmsCodeConfiguration.class})
|
||||||
|
public class SmsSendServiceImplTest extends BaseRedisUnitTest {
|
||||||
|
|
||||||
@InjectMocks
|
@Resource
|
||||||
private SmsSendServiceImpl smsSendService;
|
private SmsSendServiceImpl smsSendService;
|
||||||
|
|
||||||
@Mock
|
@MockitoBean
|
||||||
private AdminUserService adminUserService;
|
|
||||||
@Mock
|
|
||||||
private MemberService memberService;
|
|
||||||
@Mock
|
|
||||||
private SmsChannelService smsChannelService;
|
private SmsChannelService smsChannelService;
|
||||||
@Mock
|
@MockitoBean
|
||||||
private SmsTemplateService smsTemplateService;
|
private SmsTemplateService smsTemplateService;
|
||||||
@Mock
|
@MockitoBean
|
||||||
private SmsLogService smsLogService;
|
private SmsLogService smsLogService;
|
||||||
@Mock
|
@MockitoBean
|
||||||
private SmsProducer smsProducer;
|
private SmsProducer smsProducer;
|
||||||
|
|
||||||
@Test
|
@Resource
|
||||||
public void testSendSingleSmsToAdmin() {
|
private SmsCodeProperties smsCodeProperties;
|
||||||
// 准备参数
|
|
||||||
Long userId = randomLongId();
|
|
||||||
String templateCode = randomString();
|
|
||||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
|
||||||
.put("op", "login").build();
|
|
||||||
// mock adminUserService 的方法
|
|
||||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setMobile("15601691300"));
|
|
||||||
when(adminUserService.getUser(eq(userId))).thenReturn(user);
|
|
||||||
|
|
||||||
// mock SmsTemplateService 的方法
|
@MockitoBean
|
||||||
SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> {
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
|
||||||
o.setContent("验证码为{code}, 操作为{op}");
|
|
||||||
o.setParams(Lists.newArrayList("code", "op"));
|
|
||||||
});
|
|
||||||
when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
|
||||||
String content = randomString();
|
|
||||||
when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
|
|
||||||
.thenReturn(content);
|
|
||||||
// mock SmsChannelService 的方法
|
|
||||||
SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
||||||
when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
|
|
||||||
// mock SmsLogService 的方法
|
|
||||||
Long smsLogId = randomLongId();
|
|
||||||
when(smsLogService.createSmsLog(eq(user.getMobile()), eq(userId), eq(UserTypeEnum.ADMIN.getValue()), eq(Boolean.TRUE), eq(template),
|
|
||||||
eq(content), eq(templateParams))).thenReturn(smsLogId);
|
|
||||||
|
|
||||||
// 调用
|
@MockitoBean
|
||||||
Long resultSmsLogId = smsSendService.sendSingleSmsToAdmin(null, userId, templateCode, templateParams);
|
private ValueOperations<String, Object> valueOperations;
|
||||||
// 断言
|
|
||||||
assertEquals(smsLogId, resultSmsLogId);
|
|
||||||
// 断言调用
|
|
||||||
verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(user.getMobile()), eq(template),
|
|
||||||
eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login"))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSendSingleSmsToUser() {
|
|
||||||
// 准备参数
|
|
||||||
Long userId = randomLongId();
|
|
||||||
String templateCode = randomString();
|
|
||||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
|
||||||
.put("op", "login").build();
|
|
||||||
// mock memberService 的方法
|
|
||||||
String mobile = "15601691300";
|
|
||||||
when(memberService.getMemberUserMobile(eq(userId))).thenReturn(mobile);
|
|
||||||
|
|
||||||
// mock SmsTemplateService 的方法
|
@BeforeEach
|
||||||
SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> {
|
void setUp() {
|
||||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
||||||
o.setContent("验证码为{code}, 操作为{op}");
|
|
||||||
o.setParams(Lists.newArrayList("code", "op"));
|
|
||||||
});
|
|
||||||
when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
|
||||||
String content = randomString();
|
|
||||||
when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
|
|
||||||
.thenReturn(content);
|
|
||||||
// mock SmsChannelService 的方法
|
|
||||||
SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
||||||
when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
|
|
||||||
// mock SmsLogService 的方法
|
|
||||||
Long smsLogId = randomLongId();
|
|
||||||
when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(UserTypeEnum.MEMBER.getValue()), eq(Boolean.TRUE), eq(template),
|
|
||||||
eq(content), eq(templateParams))).thenReturn(smsLogId);
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
Long resultSmsLogId = smsSendService.sendSingleSmsToMember(null, userId, templateCode, templateParams);
|
|
||||||
// 断言
|
|
||||||
assertEquals(smsLogId, resultSmsLogId);
|
|
||||||
// 断言调用
|
|
||||||
verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), eq(template),
|
|
||||||
eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送成功,当短信模板开启时
|
* 发送成功,当短信模板开启时
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSendSingleSms_successWhenSmsTemplateEnable() {
|
void testSendSingleSms_successWhenSmsTemplateEnable() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String mobile = randomString();
|
String mobile = randomString();
|
||||||
Long userId = randomLongId();
|
Long userId = randomLongId();
|
||||||
@@ -150,9 +89,6 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
String content = randomString();
|
String content = randomString();
|
||||||
when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
|
when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||||
.thenReturn(content);
|
.thenReturn(content);
|
||||||
// mock SmsChannelService 的方法
|
|
||||||
SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
||||||
when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
|
|
||||||
// mock SmsLogService 的方法
|
// mock SmsLogService 的方法
|
||||||
Long smsLogId = randomLongId();
|
Long smsLogId = randomLongId();
|
||||||
when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.TRUE), eq(template),
|
when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.TRUE), eq(template),
|
||||||
@@ -171,7 +107,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
* 发送成功,当短信模板关闭时
|
* 发送成功,当短信模板关闭时
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSendSingleSms_successWhenSmsTemplateDisable() {
|
void testSendSingleSms_successWhenSmsTemplateDisable() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String mobile = randomString();
|
String mobile = randomString();
|
||||||
Long userId = randomLongId();
|
Long userId = randomLongId();
|
||||||
@@ -189,9 +125,6 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
String content = randomString();
|
String content = randomString();
|
||||||
when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
|
when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||||
.thenReturn(content);
|
.thenReturn(content);
|
||||||
// mock SmsChannelService 的方法
|
|
||||||
SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
||||||
when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
|
|
||||||
// mock SmsLogService 的方法
|
// mock SmsLogService 的方法
|
||||||
Long smsLogId = randomLongId();
|
Long smsLogId = randomLongId();
|
||||||
when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.FALSE), eq(template),
|
when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.FALSE), eq(template),
|
||||||
@@ -206,7 +139,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckSmsTemplateValid_notExists() {
|
void testCheckSmsTemplateValid_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String templateCode = randomString();
|
String templateCode = randomString();
|
||||||
// mock 方法
|
// mock 方法
|
||||||
@@ -217,7 +150,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildTemplateParams_paramMiss() {
|
void testBuildTemplateParams_paramMiss() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
SmsTemplateDO template = randomPojo(SmsTemplateDO.class,
|
SmsTemplateDO template = randomPojo(SmsTemplateDO.class,
|
||||||
o -> o.setParams(Lists.newArrayList("code")));
|
o -> o.setParams(Lists.newArrayList("code")));
|
||||||
@@ -230,7 +163,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckMobile_notExists() {
|
void testCheckMobile_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
// mock 方法
|
// mock 方法
|
||||||
|
|
||||||
@@ -240,7 +173,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSendBatchNotify() {
|
void testSendBatchNotify() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
// mock 方法
|
// mock 方法
|
||||||
|
|
||||||
@@ -255,38 +188,91 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testDoSendSms() throws Throwable {
|
void testDoSendSms() throws Throwable {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
SmsSendMessage message = randomPojo(SmsSendMessage.class);
|
SmsSendMessage message = randomPojo(SmsSendMessage.class);
|
||||||
|
message.setMobile("15601691300");
|
||||||
|
message.setTemplateParams(List.of(new KeyValue<>("code", "123456")));
|
||||||
// mock SmsClientFactory 的方法
|
// mock SmsClientFactory 的方法
|
||||||
SmsClient smsClient = spy(SmsClient.class);
|
SmsClient smsClient = mock(SmsClient.class);
|
||||||
when(smsChannelService.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient);
|
when(smsChannelService.getSmsClient()).thenReturn(smsClient);
|
||||||
|
SmsSendRespDTO sendResp = randomPojo(SmsSendRespDTO.class, dto -> dto.setSuccess(true));
|
||||||
|
|
||||||
// mock SmsClient 的方法
|
// mock SmsClient 的方法
|
||||||
SmsSendRespDTO sendResult = randomPojo(SmsSendRespDTO.class);
|
|
||||||
when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()),
|
when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()),
|
||||||
eq(message.getTemplateParams()))).thenReturn(sendResult);
|
eq(message.getTemplateParams()))).thenReturn(sendResp);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
smsSendService.doSendSms(message);
|
smsSendService.doSendSms(message);
|
||||||
|
|
||||||
// 断言
|
// 断言
|
||||||
verify(smsLogService).updateSmsSendResult(eq(message.getLogId()),
|
verify(valueOperations).set(
|
||||||
eq(sendResult.getSuccess()), eq(sendResult.getApiCode()),
|
contains("sms_captcha_verification"),
|
||||||
eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getSerialNo()), eq(sendResult.getChannelCode()));
|
eq("123456"),
|
||||||
|
eq(Duration.ofMinutes(5))
|
||||||
|
);
|
||||||
|
verify(smsLogService).updateSmsSendResult(
|
||||||
|
eq(message.getLogId()), eq(true),
|
||||||
|
eq(sendResp.getApiCode()), eq(sendResp.getApiMsg()),
|
||||||
|
eq(sendResp.getApiRequestId()), eq(sendResp.getSerialNo()), eq(sendResp.getChannelCode())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveSmsStatus() throws Throwable {
|
void testDoSendSms_fail() throws Throwable {
|
||||||
|
SmsSendMessage message = randomPojo(SmsSendMessage.class);
|
||||||
|
message.setTemplateParams(List.of(new KeyValue<>("code", "999999")));
|
||||||
|
// mock SmsClientFactory 的方法
|
||||||
|
SmsClient smsClient = spy(SmsClient.class);
|
||||||
|
when(smsChannelService.getSmsClient()).thenReturn(smsClient);
|
||||||
|
SmsSendRespDTO sendResp = randomPojo(SmsSendRespDTO.class, dto -> dto.setSuccess(false));
|
||||||
|
when(smsClient.sendSms(anyLong(), anyString(), anyString(), anyList())).thenReturn(sendResp);
|
||||||
|
|
||||||
|
smsSendService.doSendSms(message);
|
||||||
|
|
||||||
|
// 不应写 redis
|
||||||
|
verify(redisTemplate, never()).opsForValue();
|
||||||
|
verify(smsLogService).updateSmsSendResult(
|
||||||
|
eq(message.getLogId()), eq(false),
|
||||||
|
eq(sendResp.getApiCode()), eq(sendResp.getApiMsg()),
|
||||||
|
eq(sendResp.getApiRequestId()), eq(sendResp.getSerialNo()), eq(sendResp.getChannelCode())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDoSendSms_throwExceptionDuringSend() throws Throwable {
|
||||||
|
SmsSendMessage message = randomPojo(SmsSendMessage.class);
|
||||||
|
// mock SmsClientFactory 的方法
|
||||||
|
SmsClient smsClient = spy(SmsClient.class);
|
||||||
|
when(smsChannelService.getSmsClient()).thenReturn(smsClient);
|
||||||
|
when(smsClient.sendSms(anyLong(), anyString(), anyString(), anyList()))
|
||||||
|
.thenThrow(new RuntimeException("发送异常"));
|
||||||
|
|
||||||
|
smsSendService.doSendSms(message);
|
||||||
|
|
||||||
|
verify(smsLogService).updateSmsSendResult(
|
||||||
|
eq(message.getLogId()), eq(false),
|
||||||
|
eq("EXCEPTION"), contains("发送异常"),
|
||||||
|
isNull(), isNull(), isNull()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testReceiveSmsStatus() throws Throwable {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String channelCode = randomString();
|
String channelCode = randomString();
|
||||||
String text = randomString();
|
String text = randomString();
|
||||||
// mock SmsClientFactory 的方法
|
// mock SmsClientFactory 的方法
|
||||||
SmsClient smsClient = spy(SmsClient.class);
|
SmsClient smsClient = spy(SmsClient.class);
|
||||||
when(smsChannelService.getSmsClient(eq(channelCode))).thenReturn(smsClient);
|
when(smsChannelService.getSmsClient()).thenReturn(smsClient);
|
||||||
// mock SmsClient 的方法
|
// mock SmsClient 的方法
|
||||||
List<SmsReceiveRespDTO> receiveResults = randomPojoList(SmsReceiveRespDTO.class);
|
List<SmsReceiveRespDTO> receiveResults = randomPojoList(SmsReceiveRespDTO.class);
|
||||||
|
when(smsClient.parseSmsReceiveStatus(text)).thenReturn(receiveResults);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
assertThrows(Throwable.class, () -> smsSendService.receiveSmsStatus(channelCode, text));
|
assertDoesNotThrow(() -> smsSendService.receiveSmsStatus(channelCode, text));
|
||||||
// 断言
|
// 断言
|
||||||
receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()),
|
receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()),
|
||||||
eq(result.getReceiveTime()), eq(result.getErrorCode()), eq(result.getErrorCode())));
|
eq(result.getReceiveTime()), eq(result.getErrorCode()), eq(result.getErrorCode())));
|
||||||
|
|||||||
+72
-68
@@ -2,25 +2,28 @@ package com.cf.imes.module.system.service.sms;
|
|||||||
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.cf.imes.framework.common.exception.ServiceException;
|
||||||
import com.cf.imes.framework.common.pojo.PageResult;
|
import com.cf.imes.framework.common.pojo.PageResult;
|
||||||
import com.cf.imes.framework.common.util.collection.ArrayUtils;
|
import com.cf.imes.framework.common.util.collection.ArrayUtils;
|
||||||
import com.cf.imes.framework.common.util.object.ObjectUtils;
|
import com.cf.imes.framework.common.util.object.ObjectUtils;
|
||||||
|
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||||
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO;
|
||||||
|
import com.cf.imes.module.system.enums.ErrorCodeConstants;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
import com.cf.imes.module.system.framework.sms.core.client.SmsClient;
|
||||||
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
import com.cf.imes.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||||
import com.cf.imes.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
import com.cf.imes.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||||
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
|
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
|
||||||
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
|
import com.cf.imes.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
import com.cf.imes.module.system.dal.mysql.sms.SmsTemplateMapper;
|
import com.cf.imes.module.system.dal.mysql.sms.SmsTemplateMapper;
|
||||||
import com.cf.imes.module.system.enums.sms.SmsTemplateTypeEnum;
|
import com.cf.imes.module.system.enums.sms.SmsTemplateTypeEnum;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -34,10 +37,12 @@ import static com.cf.imes.framework.test.core.util.RandomUtils.*;
|
|||||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@Import(SmsTemplateServiceImpl.class)
|
@Import(SmsTemplateServiceImpl.class)
|
||||||
public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
public class SmsTemplateServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsTemplateServiceImpl smsTemplateService;
|
private SmsTemplateServiceImpl smsTemplateService;
|
||||||
@@ -45,13 +50,14 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
@Resource
|
@Resource
|
||||||
private SmsTemplateMapper smsTemplateMapper;
|
private SmsTemplateMapper smsTemplateMapper;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private SmsChannelService smsChannelService;
|
private SmsChannelService smsChannelService;
|
||||||
@MockBean
|
|
||||||
|
@MockitoBean
|
||||||
private SmsClient smsClient;
|
private SmsClient smsClient;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFormatSmsTemplateContent() {
|
void testFormatSmsTemplateContent() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String content = "正在进行登录操作{operation},您的验证码是{code}";
|
String content = "正在进行登录操作{operation},您的验证码是{code}";
|
||||||
Map<String, Object> params = MapUtil.<String, Object>builder("operation", "登录")
|
Map<String, Object> params = MapUtil.<String, Object>builder("operation", "登录")
|
||||||
@@ -64,7 +70,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseTemplateContentParams() {
|
void testParseTemplateContentParams() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String content = "正在进行登录操作{operation},您的验证码是{code}";
|
String content = "正在进行登录操作{operation},您的验证码是{code}";
|
||||||
// mock 方法
|
// mock 方法
|
||||||
@@ -77,7 +83,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testCreateSmsTemplate_success() throws Throwable {
|
void testCreateSmsTemplate_success() throws Throwable {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> {
|
SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> {
|
||||||
o.setContent("正在进行登录操作{operation},您的验证码是{code}");
|
o.setContent("正在进行登录操作{operation},您的验证码是{code}");
|
||||||
@@ -101,7 +107,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testUpdateSmsTemplate_success() throws Throwable {
|
void testUpdateSmsTemplate_success() throws Throwable {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
||||||
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -126,7 +132,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateSmsTemplate_notExists() {
|
void testUpdateSmsTemplate_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class);
|
SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class);
|
||||||
|
|
||||||
@@ -135,7 +141,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteSmsTemplate_success() {
|
void testDeleteSmsTemplate_success() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
||||||
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -149,7 +155,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteSmsTemplate_notExists() {
|
void testDeleteSmsTemplate_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long id = randomLongId();
|
Long id = randomLongId();
|
||||||
|
|
||||||
@@ -158,7 +164,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSmsTemplate() {
|
void testGetSmsTemplate() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
||||||
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -172,7 +178,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSmsTemplateByCodeFromCache() {
|
void testGetSmsTemplateByCodeFromCache() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
|
||||||
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
|
||||||
@@ -186,7 +192,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSmsTemplatePage() {
|
void testGetSmsTemplatePage() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到
|
SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到
|
||||||
o.setType(SmsTemplateTypeEnum.PROMOTION.getType());
|
o.setType(SmsTemplateTypeEnum.PROMOTION.getType());
|
||||||
@@ -194,7 +200,6 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
o.setCode("tudou");
|
o.setCode("tudou");
|
||||||
o.setContent("晨丰科技");
|
o.setContent("晨丰科技");
|
||||||
o.setApiTemplateId("yunai");
|
o.setApiTemplateId("yunai");
|
||||||
o.setChannelId(1L);
|
|
||||||
o.setCreateTime(buildTime(2021, 11, 11));
|
o.setCreateTime(buildTime(2021, 11, 11));
|
||||||
});
|
});
|
||||||
smsTemplateMapper.insert(dbSmsTemplate);
|
smsTemplateMapper.insert(dbSmsTemplate);
|
||||||
@@ -204,12 +209,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||||
// 测试 code 不匹配
|
// 测试 code 不匹配
|
||||||
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
|
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
|
||||||
// 测试 content 不匹配
|
|
||||||
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
|
|
||||||
// 测试 apiTemplateId 不匹配
|
// 测试 apiTemplateId 不匹配
|
||||||
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
|
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
|
||||||
// 测试 channelId 不匹配
|
|
||||||
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
|
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
|
smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
|
||||||
// 准备参数
|
// 准备参数
|
||||||
@@ -229,7 +230,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSmsTemplateCountByChannelId() {
|
void testGetSmsTemplateCountByChannelId() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> o.setChannelId(1L));
|
SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> o.setChannelId(1L));
|
||||||
smsTemplateMapper.insert(dbSmsTemplate);
|
smsTemplateMapper.insert(dbSmsTemplate);
|
||||||
@@ -245,56 +246,13 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateSmsChannel_success() {
|
void testValidateDictDataValueUnique_success() {
|
||||||
// 准备参数
|
|
||||||
Long channelId = randomLongId();
|
|
||||||
// mock 方法
|
|
||||||
SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
|
|
||||||
o.setId(channelId);
|
|
||||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
|
|
||||||
});
|
|
||||||
when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO);
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
SmsChannelDO returnChannelDO = smsTemplateService.validateSmsChannel(channelId);
|
|
||||||
// 断言
|
|
||||||
assertPojoEquals(returnChannelDO, channelDO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateSmsChannel_notExists() {
|
|
||||||
// 准备参数
|
|
||||||
Long channelId = randomLongId();
|
|
||||||
|
|
||||||
// 调用,校验异常
|
|
||||||
assertServiceException(() -> smsTemplateService.validateSmsChannel(channelId),
|
|
||||||
SMS_CHANNEL_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateSmsChannel_disable() {
|
|
||||||
// 准备参数
|
|
||||||
Long channelId = randomLongId();
|
|
||||||
// mock 方法
|
|
||||||
SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
|
|
||||||
o.setId(channelId);
|
|
||||||
o.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 保证 status 禁用,触发失败
|
|
||||||
});
|
|
||||||
when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO);
|
|
||||||
|
|
||||||
// 调用,校验异常
|
|
||||||
assertServiceException(() -> smsTemplateService.validateSmsChannel(channelId),
|
|
||||||
SMS_CHANNEL_DISABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateDictDataValueUnique_success() {
|
|
||||||
// 调用,成功
|
// 调用,成功
|
||||||
smsTemplateService.validateSmsTemplateCodeDuplicate(randomLongId(), randomString());
|
smsTemplateService.validateSmsTemplateCodeDuplicate(randomLongId(), randomString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateSmsTemplateCodeDuplicate_valueDuplicateForCreate() {
|
void testValidateSmsTemplateCodeDuplicate_valueDuplicateForCreate() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
String code = randomString();
|
String code = randomString();
|
||||||
// mock 数据
|
// mock 数据
|
||||||
@@ -306,7 +264,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateDictDataValueUnique_valueDuplicateForUpdate() {
|
void testValidateDictDataValueUnique_valueDuplicateForUpdate() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long id = randomLongId();
|
Long id = randomLongId();
|
||||||
String code = randomString();
|
String code = randomString();
|
||||||
@@ -329,4 +287,50 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
|
|||||||
return randomPojo(SmsTemplateDO.class, ArrayUtils.append(consumer, consumers));
|
return randomPojo(SmsTemplateDO.class, ArrayUtils.append(consumer, consumers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testValidateApiTemplate_allBranches() throws Throwable {
|
||||||
|
String apiTemplateId = "tpl-123";
|
||||||
|
|
||||||
|
// 1. smsClient 为 null
|
||||||
|
doReturn(null).when(smsChannelService).getSmsClient();
|
||||||
|
ServiceException ex1 = assertThrows(ServiceException.class,
|
||||||
|
() -> smsTemplateService.validateApiTemplate(apiTemplateId));
|
||||||
|
assertEquals(ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS.getCode(), ex1.getCode());
|
||||||
|
|
||||||
|
// 2. smsClient 不为 null,但 getSmsTemplate 抛异常
|
||||||
|
doReturn(smsClient).when(smsChannelService).getSmsClient();
|
||||||
|
doThrow(new RuntimeException("api error")).when(smsClient).getSmsTemplate(apiTemplateId);
|
||||||
|
ServiceException ex2 = assertThrows(ServiceException.class,
|
||||||
|
() -> smsTemplateService.validateApiTemplate(apiTemplateId));
|
||||||
|
assertEquals(ErrorCodeConstants.SMS_TEMPLATE_API_ERROR.getCode(), ex2.getCode());
|
||||||
|
|
||||||
|
// 3. 返回 null 模板
|
||||||
|
doReturn(null).when(smsClient).getSmsTemplate(apiTemplateId);
|
||||||
|
ServiceException ex3 = assertThrows(ServiceException.class,
|
||||||
|
() -> smsTemplateService.validateApiTemplate(apiTemplateId));
|
||||||
|
assertEquals(ErrorCodeConstants.SMS_TEMPLATE_API_NOT_FOUND.getCode(), ex3.getCode());
|
||||||
|
|
||||||
|
// 4. 审核中
|
||||||
|
SmsTemplateRespDTO checkingTpl = new SmsTemplateRespDTO();
|
||||||
|
checkingTpl.setAuditStatus(SmsTemplateAuditStatusEnum.CHECKING.getStatus());
|
||||||
|
doReturn(checkingTpl).when(smsClient).getSmsTemplate(apiTemplateId);
|
||||||
|
ServiceException ex4 = assertThrows(ServiceException.class,
|
||||||
|
() -> smsTemplateService.validateApiTemplate(apiTemplateId));
|
||||||
|
assertEquals(ErrorCodeConstants.SMS_TEMPLATE_API_AUDIT_CHECKING.getCode(), ex4.getCode());
|
||||||
|
|
||||||
|
// 5. 审核失败
|
||||||
|
SmsTemplateRespDTO failTpl = new SmsTemplateRespDTO();
|
||||||
|
failTpl.setAuditStatus(SmsTemplateAuditStatusEnum.FAIL.getStatus());
|
||||||
|
failTpl.setAuditReason("reason");
|
||||||
|
doReturn(failTpl).when(smsClient).getSmsTemplate(apiTemplateId);
|
||||||
|
ServiceException ex5 = assertThrows(ServiceException.class,
|
||||||
|
() -> smsTemplateService.validateApiTemplate(apiTemplateId));
|
||||||
|
assertEquals(ErrorCodeConstants.SMS_TEMPLATE_API_AUDIT_FAIL.getCode(), ex5.getCode());
|
||||||
|
|
||||||
|
// 6. 审核成功,Assert.equals 分支
|
||||||
|
SmsTemplateRespDTO successTpl = new SmsTemplateRespDTO();
|
||||||
|
successTpl.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus());
|
||||||
|
doReturn(successTpl).when(smsClient).getSmsTemplate(apiTemplateId);
|
||||||
|
assertDoesNotThrow(() -> smsTemplateService.validateApiTemplate(apiTemplateId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,8 +278,8 @@ CREATE TABLE IF NOT EXISTS "system_sms_template" (
|
|||||||
"params" varchar(255) NOT NULL,
|
"params" varchar(255) NOT NULL,
|
||||||
"remark" varchar(255) DEFAULT NULL,
|
"remark" varchar(255) DEFAULT NULL,
|
||||||
"api_template_id" varchar(63) NOT NULL,
|
"api_template_id" varchar(63) NOT NULL,
|
||||||
"channel_id" bigint NOT NULL,
|
"channel_id" bigint NULL,
|
||||||
"channel_code" varchar(63) NOT NULL,
|
"channel_code" varchar(63) NULL,
|
||||||
"creator" varchar(64) DEFAULT '',
|
"creator" varchar(64) DEFAULT '',
|
||||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updater" varchar(64) DEFAULT '',
|
"updater" varchar(64) DEFAULT '',
|
||||||
@@ -290,8 +290,8 @@ CREATE TABLE IF NOT EXISTS "system_sms_template" (
|
|||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "system_sms_log" (
|
CREATE TABLE IF NOT EXISTS "system_sms_log" (
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"channel_id" bigint NOT NULL,
|
"channel_id" bigint NULL,
|
||||||
"channel_code" varchar(63) NOT NULL,
|
"channel_code" varchar(63) NULL,
|
||||||
"template_id" bigint NOT NULL,
|
"template_id" bigint NOT NULL,
|
||||||
"template_code" varchar(63) NOT NULL,
|
"template_code" varchar(63) NOT NULL,
|
||||||
"template_type" tinyint NOT NULL,
|
"template_type" tinyint NOT NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user