findme-backend-merchant-java/src/main/java/com/xjhs/findmemerchant/security/sms/SmsCodeService.java
2026-01-09 12:20:24 +08:00

76 lines
2.5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}