短信相关逻辑,仅仅接口状态标记
This commit is contained in:
@@ -26,8 +26,8 @@ public class LoginController {
|
|||||||
private LoginService loginService;
|
private LoginService loginService;
|
||||||
|
|
||||||
@PostMapping("/sms/sendCode")
|
@PostMapping("/sms/sendCode")
|
||||||
public boolean sendCode(@RequestParam @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") String mobileNumber) {
|
public void sendCode(@RequestParam @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") String mobileNumber) {
|
||||||
return loginService.sendCode(mobileNumber);
|
loginService.sendCode(mobileNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login/smsLogin")
|
@PostMapping("/login/smsLogin")
|
||||||
|
|||||||
@@ -66,16 +66,16 @@ public class LoginService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送短信验证码
|
* 发送短信验证码
|
||||||
* <p>1. 生成6位随机验证码 2. 委托SmsService发送</p>
|
* <p>1. 生成6位随机验证码 2. 委托SmsService发送,失败抛异常</p>
|
||||||
*/
|
*/
|
||||||
public boolean sendCode(String mobileNumber) {
|
public void sendCode(String mobileNumber) {
|
||||||
Assert.hasText(mobileNumber, "手机号不能为空");
|
Assert.hasText(mobileNumber, "手机号不能为空");
|
||||||
|
|
||||||
UniversalSmsVariable variable = new UniversalSmsVariable();
|
UniversalSmsVariable variable = new UniversalSmsVariable();
|
||||||
String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
|
String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
|
||||||
variable.setCode(code);
|
variable.setCode(code);
|
||||||
|
|
||||||
return smsService.send(mobileNumber, SmsTemplateEnum.UNIVERSAL, variable);
|
smsService.send(mobileNumber, SmsTemplateEnum.UNIVERSAL, variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.jiayunet.constant.SmsTemplateEnum;
|
import org.jiayunet.constant.SmsTemplateEnum;
|
||||||
import org.jiayunet.constant.sms.SmsVariableAllows;
|
import org.jiayunet.constant.sms.SmsVariableAllows;
|
||||||
import org.jiayunet.constant.sms.UniversalSmsVariable;
|
import org.jiayunet.constant.sms.UniversalSmsVariable;
|
||||||
|
import org.jiayunet.exception.BusinessException;
|
||||||
|
import org.jiayunet.exception.BusinessExpCodeEnum;
|
||||||
import org.jiayunet.sms.AliYunSmsAbility;
|
import org.jiayunet.sms.AliYunSmsAbility;
|
||||||
import org.jiayunet.tool.server.RedisServerTool;
|
import org.jiayunet.tool.server.RedisServerTool;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -41,10 +43,9 @@ public class SmsService {
|
|||||||
* @param phone 目标手机号,不能为空
|
* @param phone 目标手机号,不能为空
|
||||||
* @param template 短信模板枚举,必须与 {@code variable} 的类型匹配
|
* @param template 短信模板枚举,必须与 {@code variable} 的类型匹配
|
||||||
* @param variable 短信参数对象,可能是 {@link UniversalSmsVariable}(验证码)或其他实现
|
* @param variable 短信参数对象,可能是 {@link UniversalSmsVariable}(验证码)或其他实现
|
||||||
* @return {@code true} 表示短信发送成功,{@code false} 表示发送失败或前置参数校验未通过
|
* @throws BusinessException 发送失败时抛出业务异常
|
||||||
*/
|
*/
|
||||||
public boolean send(String phone, SmsTemplateEnum template, SmsVariableAllows variable) {
|
public void send(String phone, SmsTemplateEnum template, SmsVariableAllows variable) {
|
||||||
try {
|
|
||||||
Assert.hasText(phone, "手机号不能为空");
|
Assert.hasText(phone, "手机号不能为空");
|
||||||
Assert.notNull(template, "短信模板不能为空");
|
Assert.notNull(template, "短信模板不能为空");
|
||||||
Assert.notNull(variable, "短信参数不能为空");
|
Assert.notNull(variable, "短信参数不能为空");
|
||||||
@@ -52,21 +53,16 @@ public class SmsService {
|
|||||||
// 校验参数类型是否匹配
|
// 校验参数类型是否匹配
|
||||||
if (!template.getVariableClass().isInstance(variable)) {
|
if (!template.getVariableClass().isInstance(variable)) {
|
||||||
log.error("短信参数类型不匹配: template={}, expectedClass={}, actualClass={}", template.name(), template.getVariableClass().getName(), variable.getClass().getName());
|
log.error("短信参数类型不匹配: template={}, expectedClass={}, actualClass={}", template.name(), template.getVariableClass().getName(), variable.getClass().getName());
|
||||||
throw new RuntimeException("短信发送失败");
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "短信发送失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否激活验证码模式
|
// 判断是否激活验证码模式
|
||||||
boolean isVerifyMode = isVerifyCodeMode(template, variable);
|
boolean isVerifyMode = isVerifyCodeMode(template, variable);
|
||||||
|
|
||||||
if (isVerifyMode) {
|
if (isVerifyMode) {
|
||||||
return sendVerifyCode(phone, template, (UniversalSmsVariable) variable);
|
sendVerifyCode(phone, template, (UniversalSmsVariable) variable);
|
||||||
} else {
|
} else {
|
||||||
return sendNormalSms(phone, template, variable);
|
sendNormalSms(phone, template, variable);
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("发送短信异常: phone={}, template={}", phone, template.name(), e);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +159,7 @@ public class SmsService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送验证码短信。
|
* 发送验证码短信。
|
||||||
*
|
*
|
||||||
* 在发送前先检查 Redis 中是否已有未过期的验证码,防止重复发送。
|
* 在发送前先检查 Redis 中是否已有未过期的验证码,防止重复发送。
|
||||||
@@ -172,9 +168,9 @@ public class SmsService {
|
|||||||
* @param phone 目标手机号,不能为空
|
* @param phone 目标手机号,不能为空
|
||||||
* @param template 短信模板枚举,必须包含验证码相关配置(如有效时间)
|
* @param template 短信模板枚举,必须包含验证码相关配置(如有效时间)
|
||||||
* @param variable {@link UniversalSmsVariable},其中必须包含非空的 {@code code}
|
* @param variable {@link UniversalSmsVariable},其中必须包含非空的 {@code code}
|
||||||
* @return {@code true} 表示短信发送及缓存成功,{@code false} 表示发送被拦截或失败
|
* @throws BusinessException 发送被拦截或失败时抛出业务异常
|
||||||
*/
|
*/
|
||||||
private boolean sendVerifyCode(String phone, SmsTemplateEnum template, UniversalSmsVariable variable) {
|
private void sendVerifyCode(String phone, SmsTemplateEnum template, UniversalSmsVariable variable) {
|
||||||
String key = buildVerifyCodeKey(template, phone);
|
String key = buildVerifyCodeKey(template, phone);
|
||||||
|
|
||||||
// 检查是否允许重发
|
// 检查是否允许重发
|
||||||
@@ -185,7 +181,7 @@ public class SmsService {
|
|||||||
long elapsedSeconds = template.getEffectiveTime() * 60L - (remainSeconds != null ? remainSeconds : 0L);
|
long elapsedSeconds = template.getEffectiveTime() * 60L - (remainSeconds != null ? remainSeconds : 0L);
|
||||||
if (elapsedSeconds < template.getRetryTime() * 60L) {
|
if (elapsedSeconds < template.getRetryTime() * 60L) {
|
||||||
log.warn("重发间隔未到,请{}分钟后再试: phone={}, template={}", template.getRetryTime(), phone, template.name());
|
log.warn("重发间隔未到,请{}分钟后再试: phone={}, template={}", template.getRetryTime(), phone, template.name());
|
||||||
throw new RuntimeException("请勿重复发送");
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "请勿重复发送");
|
||||||
}
|
}
|
||||||
// 已超过重发间隔,允许重新发送,后续会覆盖旧验证码
|
// 已超过重发间隔,允许重新发送,后续会覆盖旧验证码
|
||||||
}
|
}
|
||||||
@@ -203,30 +199,34 @@ public class SmsService {
|
|||||||
variableMap
|
variableMap
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "短信发送失败,请稍后重试");
|
||||||
|
}
|
||||||
|
|
||||||
// 发送成功后存储验证码
|
// 发送成功后存储验证码
|
||||||
if (success) {
|
|
||||||
redisServerTool.set(key, variable.getCode(), template.getEffectiveTime(), TimeUnit.MINUTES);
|
redisServerTool.set(key, variable.getCode(), template.getEffectiveTime(), TimeUnit.MINUTES);
|
||||||
log.info("验证码已存储: phone={}, template={}, effectiveTime={}分钟",
|
log.info("验证码已存储: phone={}, template={}, effectiveTime={}分钟",
|
||||||
phone, template.name(), template.getEffectiveTime());
|
phone, template.name(), template.getEffectiveTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送普通短信
|
* 发送普通短信
|
||||||
*/
|
*/
|
||||||
private boolean sendNormalSms(String phone, SmsTemplateEnum template, SmsVariableAllows variable) {
|
private void sendNormalSms(String phone, SmsTemplateEnum template, SmsVariableAllows variable) {
|
||||||
// 转换参数对象为 Map<String, String>
|
// 转换参数对象为 Map<String, String>
|
||||||
Map<String, String> variableMap = objectMapper.convertValue(variable, new com.fasterxml.jackson.core.type.TypeReference<Map<String, String>>() {});
|
Map<String, String> variableMap = objectMapper.convertValue(variable, new com.fasterxml.jackson.core.type.TypeReference<Map<String, String>>() {});
|
||||||
|
|
||||||
// 直接发送短信
|
// 直接发送短信
|
||||||
return aliYunSmsAbility.sendSms(
|
boolean success = aliYunSmsAbility.sendSms(
|
||||||
phone,
|
phone,
|
||||||
template.getSignName(),
|
template.getSignName(),
|
||||||
template.getTemplateCode(),
|
template.getTemplateCode(),
|
||||||
variableMap
|
variableMap
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "短信发送失败,请稍后重试");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user