书接上文,需要做一个通用的验证码发送,发送操作还是以上篇文章为主,这里主要是对验证码发送进行一个重构
https://blog.csdn.net/MinisterOL/article/details/136750920
- 通过统一的验证码接口请求进入系统
- 在业务实现中,遍历 实现了 CaptchaHandler接口的组件信息
ApiCaptchaBizServiceImpl.java
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.extra.spring.SpringUtil;
import com..captcha.common.handler.CaptchaHandler;
import com..captcha.service.biz.ApiCaptchaBizService;
import com..captcha.model.req.SendCaptchaReq;
import com.ruoyi.common.exception.GlobalException;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* ApiCaptchaBizServiceImpl
*
* @author SERVER-ZJ
* @since 2023/10/25 8:30
*/
@Service
public class ApiCaptchaBizServiceImpl implements ApiCaptchaBizService {
@Override
public void captcha(SendCaptchaReq req) {
if (!Validator.isMobile(req.getMobile())) {
throw new GlobalException("手机号格式错误");
}
Map<String, CaptchaHandler> captchaHandlerBeansByNameMap
= SpringUtil.getBeansOfType(CaptchaHandler.class);
if (CollectionUtil.isEmpty(captchaHandlerBeansByNameMap)) {
throw new GlobalException("业务不存在!");
}
CaptchaHandler currentCaptchaHandler;
CaptchaHandler targetCaptchaHandler = null;
for (Map.Entry<String, CaptchaHandler> captchaHandlerBeansByNameMapEntry
: captchaHandlerBeansByNameMap.entrySet()) {
currentCaptchaHandler = captchaHandlerBeansByNameMapEntry.getValue();
if (req.getTypeCode().equals(currentCaptchaHandler.getCode())) {
targetCaptchaHandler = currentCaptchaHandler;
}
}
if (targetCaptchaHandler == null) {
throw new GlobalException("业务不存在!");
}
targetCaptchaHandler.send(req.getMobile());
}
}
CaptchaHandler.java
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com..captcha.common.cont.CaptchaConst;
import com..captcha.common.manager.CaptchaManager;
import com..captcha.model.extend.Captcha;
import com..sms.SmsSender;
import com..sms.common.cont.PlatformEnum;
import com..sms.model.base.BaseSendParam;
import com.ruoyi.common.exception.GlobalException;
import java.util.Date;
/**
* CaptchaHandler
*
* @author SERVER
* @since 2024/3/28 11:37
*/
public interface CaptchaHandler {
/**
* 获取验证码管理器
*
* @return 验证码管理器
*/
default CaptchaManager getCaptchaManager() {
Object captchaManager = SpringUtil.getBean("CaptchaManager");
if (ObjectUtil.isNull(captchaManager) ||
!(captchaManager instanceof CaptchaManager)) {
throw new GlobalException("验证码管理器暂未注册");
}
return (CaptchaManager) captchaManager;
}
/**
* 对应处理编码
*
* @return 验证模块编码
*/
default String getCode() {
return "";
}
/**
* 发送
*/
default void send(String mobile) {
this.beforeSend(mobile);
// 2、查看缓存中是否有对应的手机号验证码缓存
Captcha captcha
= this.getCaptchaManager().getCaptcha(this.getCode(), mobile);
// 3、判断是不是超过60s
if (captcha != null) {
long captchaSendingIntervalSecond = DateUtil.between(new Date(), captcha.getCreateTime(), DateUnit.SECOND);
if (captchaSendingIntervalSecond < CaptchaConst.CAPTCHA_SENDING_INTERVAL_LIMIT_SECOND) {
throw new GlobalException("验证码已发送,请 " + (CaptchaConst.CAPTCHA_SENDING_INTERVAL_LIMIT_SECOND - captchaSendingIntervalSecond) + "s 后再试");
}
}
// 4、重新生成验证码
captcha = this.getCaptchaManager().createCaptcha(this.getCode(), mobile);
// 5、发送短信
SmsSender.send(PlatformEnum.ALI_DA_YU, mobile, this.createCaptchaSmsBody(captcha));
}
/**
* 短信发送前置处理
*
* @param mobile 手机号
*/
void beforeSend(String mobile);
/**
* 根据验证码创建短信body
*
* @param captcha 验证码
* @return 发送短信体
*/
BaseSendParam createCaptchaSmsBody(Captcha captcha);
/**
* 校验验证码
*
* @param mobile 手机号
* @param captchaCode 校验验证码
*/
default void verify(String mobile, String captchaCode) {
Captcha captcha = this.getCaptchaManager().getCaptcha(this.getCode(), mobile);
if (captcha == null || !captcha.getMobile().equals(mobile)) {
throw new GlobalException("验证码无效!");
}
if (!captcha.getCaptcha().equals(captchaCode)) {
throw new GlobalException("验证码错误!");
}
}
}
实现举例:
RegisterCaptchaHandler.class
import com..captcha.common.handler.CaptchaHandler;
import com..captcha.model.extend.Captcha;
import com..recruit.api.account.common.checker.AccountChecker;
import com..recruit.api.common.common.sms.model.CaptchaTemplateParam;
import com..sms.common.template.AliDaYuTemplate;
import com..sms.model.base.BaseSendParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* AccountCaptchaHandler
*
* @author SERVER
* @since 2024/3/28 13:27
*/
@Component
public class AccountRegisterCaptchaHandler implements CaptchaHandler {
@Autowired
private AccountChecker accountChecker;
@Override
public String getCode() {
return "accountRegister";
}
@Override
public void beforeSend(String mobile) {
accountChecker.checkRegisterMobile(mobile);
}
@Override
public BaseSendParam createCaptchaSmsBody(Captcha captcha) {
AliDaYuTemplate template = new AliDaYuTemplate("XXXX科技", "SMS_14238XXXXX");
return template.createSmsBody(new CaptchaTemplateParam(captcha.getCaptcha()));
}
}