编写短信验证码发送接口
Sync All Branches to GitHub / sync (push) Successful in 2s

This commit is contained in:
2026-01-15 22:59:58 +08:00
parent c32f06239e
commit 3cba48728d
13 changed files with 226 additions and 9 deletions
+3 -3
View File
@@ -23,8 +23,8 @@
" * @author ${1:}", " * @author ${1:}",
" * @version V1.0", " * @version V1.0",
" * @title ${TM_FILENAME_BASE}", " * @title ${TM_FILENAME_BASE}",
" * @description ${2:}",
" * @date ${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}", " * @date ${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}",
" * @description ${2:}",
" */", " */",
"" ""
], ],
@@ -38,8 +38,8 @@
" * @author ${1:}", " * @author ${1:}",
" * @version V1.0", " * @version V1.0",
" * @title ${TM_FILENAME_BASE}", " * @title ${TM_FILENAME_BASE}",
" * @description ${2:}",
" * @date ${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}", " * @date ${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}",
" * @description ${2:}",
" */", " */",
"" ""
], ],
@@ -53,8 +53,8 @@
" * @author ${1:}", " * @author ${1:}",
" * @version V1.0", " * @version V1.0",
" * @title ${TM_FILENAME_BASE}", " * @title ${TM_FILENAME_BASE}",
" * @description ${2:}",
" * @date ${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}", " * @date ${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}",
" * @description ${2:}",
" */", " */",
"" ""
], ],
+22
View File
@@ -45,6 +45,9 @@
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
<jansi.version>1.18</jansi.version> <jansi.version>1.18</jansi.version>
<sa-token.version>1.38.0</sa-token.version> <sa-token.version>1.38.0</sa-token.version>
<guava.version>33.0.0-jre</guava.version>
<hutool.version>5.8.26</hutool.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
</properties> </properties>
<!-- 统一依赖管理 --> <!-- 统一依赖管理 -->
@@ -146,6 +149,25 @@
<artifactId>jansi</artifactId> <artifactId>jansi</artifactId>
<version>${jansi.version}</version> <version>${jansi.version}</version>
</dependency> </dependency>
<!-- 常用工具类 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@@ -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 org.springframework.web.bind.annotation.RestController;
import com.jy.framework.biz.operationlog.aspect.ApiOperationLog; import com.jy.framework.biz.operationlog.aspect.ApiOperationLog;
import com.jy.framework.common.response.Response; 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; import cn.dev33.satoken.stp.StpUtil;
@@ -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 @AllArgsConstructor
public enum ResponseCodeEnum implements BaseExceptionInterface { 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 jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/**
*
* @author ayi
* @version V1.0
* @title GlobalExceptionHandler
* @description 全局异常处理器
* @date 2026/01/15 18:40
*/
@Slf4j @Slf4j
@ControllerAdvice @ControllerAdvice
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
@@ -1,4 +1,4 @@
package com.jy.xiaoyishu.auth.vo; package com.jy.xiaoyishu.auth.model.vo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@@ -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);
}
@@ -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 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最小空闲连接
max-idle: 10 # 连接池中的最大空闲连接 max-idle: 10 # 连接池中的最大空闲连接
# output: output:
# ansi: ansi:
# enabled: always enabled: always
application: application:
name: xiaoyishu-auth name: xiaoyishu-auth
+16
View File
@@ -57,6 +57,22 @@
<groupId>org.hibernate.validator</groupId> <groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
</dependency> </dependency>
<!-- 工具类 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>