首次提交

This commit is contained in:
guotao 2026-01-09 12:20:24 +08:00
commit 1101681331
131 changed files with 7017 additions and 0 deletions

View file

@ -0,0 +1,76 @@
package com.xjhs.findmemerchant.security.sms;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.Random;
@Slf4j
@Service
@RequiredArgsConstructor
public class SmsCodeService {
/** Redis key 前缀sms:code:{scene}:{phone} */
private static final String SMS_CODE_KEY_PREFIX = "sms:code:";
/** 验证码有效期5 分钟 */
private static final Duration SMS_CODE_TTL = Duration.ofMinutes(5);
private final StringRedisTemplate redisTemplate;
private final Random random = new Random();
private Object smsSender; // 你自己的短信通道接口
private String buildKey(String phone, String scene) {
return SMS_CODE_KEY_PREFIX + scene + ":" + phone;
}
/**
* 生成 6 位数字验证码
*/
private String generateCode() {
return String.format("%06d", random.nextInt(1_000_000));
}
/**
* 发送短信验证码生成 -> Redis -> 调短信通道发出去
*/
public void sendVerificationCode(String phone, String scene) {
var code = generateCode();
var key = buildKey(phone, scene);
// 存到 Redis设置 TTL
redisTemplate.opsForValue().set(key, code, SMS_CODE_TTL);
// TODO:调用你自己的短信通道阿里云腾讯云等
// smsSender.sendSmsCode(phone, scene, code);
// 开发阶段也可以打印一下方便调试
log.debug("send sms code, phone={},scene={},code={}", phone,scene, code);
}
/**
* 校验验证码
* - key 不存在 => 过期 / 未发送 => SmsCodeExpiredException
* - code 不匹配 => SmsCodeInvalidException
* - 匹配 => 删除 key一次性
*/
public void verifyCode(String phone, String scene, String inputCode) throws Exception {
String key = buildKey(phone, scene);
String realCode = redisTemplate.opsForValue().get(key);
if (realCode == null) {
// 对齐 Go 里的 ErrSMSCodeExpired
throw new Exception("验证码已过期或未发送");
}
if (!realCode.equals(inputCode)) {
// 不正确但不删除让用户继续尝试错误次数由 AuthService 控制
throw new Exception("验证码错误");
}
// 验证通过删除验证码一次性
redisTemplate.delete(key);
}
}