@@ -0,0 +1,29 @@
|
||||
package com.jy.xiaoyishu.auth.constant;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title RedisKeyConstants
|
||||
* @description Redis key 常量
|
||||
* @date 2026/01/15 18:45
|
||||
*/
|
||||
|
||||
public class RedisKeyConstants {
|
||||
|
||||
/**
|
||||
* 验证码 KEY 前缀
|
||||
*/
|
||||
private static final String VERIFICATION_CODE_KEY_PREFIX = "verification_code:";
|
||||
|
||||
/**
|
||||
* 构建验证码 KEY
|
||||
*
|
||||
* @param phone 手机号
|
||||
* @return 验证码 KEY
|
||||
*/
|
||||
public static String buildVerificationCodeKey(String phone) {
|
||||
return VERIFICATION_CODE_KEY_PREFIX + phone;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.jy.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import com.jy.framework.common.response.Response;
|
||||
import com.jy.xiaoyishu.auth.vo.User;
|
||||
import com.jy.xiaoyishu.auth.model.vo.User;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.jy.xiaoyishu.auth.controller;
|
||||
|
||||
import com.jy.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import com.jy.framework.common.response.Response;
|
||||
import com.jy.xiaoyishu.auth.model.vo.verificationcode.SendVerificationCodeReqVO;
|
||||
import com.jy.xiaoyishu.auth.service.VerificationCodeService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title VerificationCodeController
|
||||
* @date 2026/01/15
|
||||
* @description 验证码控制器
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class VerificationCodeController {
|
||||
@Resource
|
||||
private VerificationCodeService verificationCodeService;
|
||||
|
||||
@PostMapping("/verification/code/send")
|
||||
@ApiOperationLog(description = "发送短信验证码")
|
||||
public Response<?> send(@Validated @RequestBody SendVerificationCodeReqVO sendVerificationCodeReqVO) {
|
||||
return verificationCodeService.send(sendVerificationCodeReqVO);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,9 @@ import com.jy.framework.common.exception.BaseExceptionInterface;
|
||||
@AllArgsConstructor
|
||||
public enum ResponseCodeEnum implements BaseExceptionInterface {
|
||||
// -------- 通用异常状态码 --------
|
||||
SYSTEM_ERROR("AUTH-10000", "系统错误"), PARAM_NOT_VALID("AUTH-10001", "参数错误");
|
||||
SYSTEM_ERROR("AUTH-10000", "系统错误"),
|
||||
PARAM_NOT_VALID("AUTH-10001", "参数错误"),
|
||||
VERIFICATION_CODE_SEND_FREQUENTLY("AUTH-20000", "请求太频繁,请3分钟后再试");
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
|
||||
@@ -15,6 +15,15 @@ import com.jy.xiaoyishu.auth.enums.ResponseCodeEnum;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title GlobalExceptionHandler
|
||||
* @description 全局异常处理器
|
||||
* @date 2026/01/15 18:40
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.jy.xiaoyishu.auth.vo;
|
||||
package com.jy.xiaoyishu.auth.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.jy.xiaoyishu.auth.model.vo.verificationcode;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title SendVerificationCodeReqVO
|
||||
* @description 发送验证码请求参数
|
||||
* @date 2026/01/15 18:39
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SendVerificationCodeReqVO {
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@NotBlank(message = "手机号不能为空")
|
||||
private String phone;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.jy.xiaoyishu.auth.service;
|
||||
|
||||
import com.jy.framework.common.response.Response;
|
||||
import com.jy.xiaoyishu.auth.model.vo.verificationcode.SendVerificationCodeReqVO;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title VerificationCodeService
|
||||
* @description 验证码服务
|
||||
* @date 2026/01/15 18:48
|
||||
*/
|
||||
|
||||
public interface VerificationCodeService {
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
*
|
||||
* @param sendVerificationCodeReqVO 发送验证码请求参数
|
||||
* @return 响应结果
|
||||
*/
|
||||
Response<?> send(SendVerificationCodeReqVO sendVerificationCodeReqVO);
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.jy.xiaoyishu.auth.service.impl;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.jy.framework.common.exception.BizException;
|
||||
import com.jy.framework.common.response.Response;
|
||||
import com.jy.xiaoyishu.auth.constant.RedisKeyConstants;
|
||||
import com.jy.xiaoyishu.auth.enums.ResponseCodeEnum;
|
||||
import com.jy.xiaoyishu.auth.model.vo.verificationcode.SendVerificationCodeReqVO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.jy.xiaoyishu.auth.service.VerificationCodeService;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class VerificationCodeServiceImpl implements VerificationCodeService {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public Response<?> send(SendVerificationCodeReqVO sendVerificationCodeReqVO) {
|
||||
// 手机号
|
||||
String phone = sendVerificationCodeReqVO.getPhone();
|
||||
|
||||
// 构建验证码 redis key
|
||||
String key = RedisKeyConstants.buildVerificationCodeKey(phone);
|
||||
|
||||
// 判断是否已发送验证码
|
||||
boolean isSent = redisTemplate.hasKey(key);
|
||||
if (isSent) {
|
||||
// 若之前发送的验证码未过期,则提示发送频繁
|
||||
throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_SEND_FREQUENTLY);
|
||||
}
|
||||
|
||||
// 生成 6 位随机数字验证码
|
||||
String verificationCode = RandomUtil.randomNumbers(6);
|
||||
|
||||
// todo: 调用第三方短信发送服务
|
||||
|
||||
log.info("==> 手机号: {}, 已发送验证码:【{}】", phone, verificationCode);
|
||||
|
||||
// 存储验证码到 redis, 并设置过期时间为 3 分钟
|
||||
redisTemplate.opsForValue().set(key, verificationCode, 3, TimeUnit.MINUTES);
|
||||
|
||||
return Response.success();
|
||||
}
|
||||
}
|
||||
@@ -55,9 +55,9 @@ spring:
|
||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
max-idle: 10 # 连接池中的最大空闲连接
|
||||
# output:
|
||||
# ansi:
|
||||
# enabled: always
|
||||
output:
|
||||
ansi:
|
||||
enabled: always
|
||||
application:
|
||||
name: xiaoyishu-auth
|
||||
|
||||
|
||||
Reference in New Issue
Block a user