1.添加手机号验证码登录
This commit is contained in:
@@ -2,6 +2,7 @@ package com.ruoyi.framework.web.service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.cms.domain.vo.WechatAuthVO;
|
||||
@@ -9,12 +10,15 @@ import com.ruoyi.cms.service.IAppUserService;
|
||||
import com.ruoyi.cms.util.StringUtil;
|
||||
import com.ruoyi.cms.util.WechatUtil;
|
||||
import com.ruoyi.cms.util.encrypt.QuickValidUtils;
|
||||
import com.ruoyi.common.config.SmsRequestClient;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
import com.ruoyi.common.core.domain.entity.SmsRequestDTO;
|
||||
import com.ruoyi.common.core.domain.model.LoginBody;
|
||||
import com.ruoyi.common.core.domain.model.LoginSiteUser;
|
||||
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||
import com.ruoyi.common.core.redis.DistributedLockUtil;
|
||||
import com.ruoyi.common.core.redis.RedisUtils;
|
||||
import com.ruoyi.common.utils.*;
|
||||
import com.ruoyi.framework.web.exception.ParamErrorConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -77,6 +81,8 @@ public class SysLoginService
|
||||
private IAppUserService appUserService;
|
||||
@Autowired
|
||||
private DistributedLockUtil distributedLockUtil;
|
||||
@Autowired
|
||||
private SmsRequestClient smsRequestClient;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
@@ -321,6 +327,168 @@ public class SysLoginService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过微信授权登录获取手机号
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
public AjaxResult getWxPhone(LoginBody dto){
|
||||
AjaxResult validateResult = validateBaseParam(dto);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
try {
|
||||
WechatAuthVO wechatAuthVO = getWechatAuthInfo(dto.getCode());
|
||||
if (wechatAuthVO == null) {
|
||||
System.err.println("微信授权返回null");
|
||||
return AjaxResult.error("微信授权失败");
|
||||
}
|
||||
String openid = wechatAuthVO.getOpenid();
|
||||
String unionid = wechatAuthVO.getUnionid();
|
||||
String sessionKey = wechatAuthVO.getSessionKey();
|
||||
if (StringUtils.isEmpty(openid)) {
|
||||
System.err.println("微信授权返回openid为空");
|
||||
return AjaxResult.error("微信授权失败");
|
||||
}
|
||||
//解密获取手机号
|
||||
String phone = decryptPhone(dto, sessionKey);
|
||||
if (phone == null) {
|
||||
System.err.println("手机号解密失败,openid=" + openid);
|
||||
return AjaxResult.error("获取手机号失败");
|
||||
}
|
||||
|
||||
//发送短信,并缓存
|
||||
AjaxResult smsResult=sendSmsAndCache(phone);
|
||||
if (!smsResult.isSuccess()) {
|
||||
return smsResult;
|
||||
}
|
||||
|
||||
AjaxResult ajax = AjaxResult.success("获取手机号成功");
|
||||
ajax.put("phone", phone);
|
||||
ajax.put("openid",openid);
|
||||
ajax.put("unionid",unionid);
|
||||
return ajax;
|
||||
} catch (Exception e) {
|
||||
System.err.println("获取手机号异常:" + e.getMessage());
|
||||
return AjaxResult.error("获取手机号异常,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信并缓存
|
||||
* @param phone
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult sendSmsAndCache(String phone) {
|
||||
if (Boolean.TRUE.equals(redisCache.hasKey(RedisUtils.SMS_SEND_LOCK + phone))) {
|
||||
return AjaxResult.error("验证码发送频繁,请60秒后重试");
|
||||
}
|
||||
// 生成6位验证码
|
||||
String code = RandomUtil.randomNumbers(6);
|
||||
// 缓存验证码
|
||||
redisCache.setCacheObject(RedisUtils.SMS_CODE_KEY + phone, code, RedisUtils.SMS_EXPIRE, TimeUnit.MINUTES);
|
||||
// 缓存发送锁(防重)
|
||||
redisCache.setCacheObject(RedisUtils.SMS_SEND_LOCK + phone, 1, RedisUtils.LOCK_EXPIRE, TimeUnit.SECONDS);
|
||||
|
||||
try {
|
||||
SmsRequestDTO requestDTO=new SmsRequestDTO();
|
||||
requestDTO.setMobile(phone);
|
||||
String[] tmpValues={code,String.valueOf(RedisUtils.SMS_EXPIRE)};
|
||||
requestDTO.setTemplateVars(tmpValues);
|
||||
AjaxResult result=smsRequestClient.sendSms(requestDTO);
|
||||
//判断是否成功
|
||||
if(!result.isSuccess()){
|
||||
return result;
|
||||
}
|
||||
System.out.println("短信发送成功 → phone=" + phone + ",code=" + code);
|
||||
return AjaxResult.success("验证码发送成功");
|
||||
} catch (Exception e) {
|
||||
// 发送失败,删除缓存
|
||||
redisCache.deleteObject(RedisUtils.SMS_CODE_KEY + phone);
|
||||
redisCache.deleteObject(RedisUtils.SMS_SEND_LOCK + phone);
|
||||
System.err.println("短信发送失败:" + e.getMessage());
|
||||
return AjaxResult.error("短信发送失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码-验证
|
||||
* @param phone
|
||||
* @param smsCode
|
||||
* @return
|
||||
*/
|
||||
public AjaxResult checkSmsCode(String phone, String smsCode) {
|
||||
if (StringUtils.isBlank(smsCode)) {
|
||||
return AjaxResult.error("请输入验证码");
|
||||
}
|
||||
|
||||
String cacheCode = redisCache.getCacheObject(RedisUtils.SMS_CODE_KEY + phone);
|
||||
if (cacheCode == null) {
|
||||
return AjaxResult.error("验证码已过期");
|
||||
}
|
||||
|
||||
if (!cacheCode.equals(smsCode.trim())) {
|
||||
return AjaxResult.error("验证码错误");
|
||||
}
|
||||
// 验证通过,删除
|
||||
redisCache.deleteObject(RedisUtils.SMS_CODE_KEY + phone);
|
||||
redisCache.deleteObject(RedisUtils.SMS_SEND_LOCK + phone);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序登录主逻辑
|
||||
* 核心逻辑:优先处理网格员(is_company_user=2),再处理普通招聘者/求职者
|
||||
*/
|
||||
public AjaxResult appLoginTwo(LoginBody dto) {
|
||||
// 1. 验证基础参数(前端userType仅0/1,拦截非法参数)
|
||||
AjaxResult validateResult = validateBaseParam(dto);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
//添加验证码验证
|
||||
AjaxResult smsValid = checkSmsCode(dto.getPhone(), dto.getSmsCode());
|
||||
if (!smsValid.isSuccess()) {
|
||||
return smsValid;
|
||||
}
|
||||
|
||||
try {
|
||||
// 3. 第一步:通过OpenID优先查询网格员(无需解密手机号,效率更高)
|
||||
AppUser openidSpecialUser = appUserService.selectByOpenid(dto.getOpenid(), StringUtil.IS_GRID_USER);
|
||||
if (openidSpecialUser != null) {
|
||||
System.out.printf("小程序登录-匹配到OpenID网格员:openid=%s, phone=%s%n",
|
||||
openidSpecialUser.getOpenid(), openidSpecialUser.getPhone());
|
||||
return handleSpecialUserLogin(openidSpecialUser);
|
||||
}
|
||||
|
||||
// 5. 第二步:通过手机号查询网格员(OpenID未匹配时兜底)
|
||||
AppUser phoneSpecialUser = appUserService.getPhoneAndUserType(dto.getPhone(), StringUtil.IS_GRID_USER);
|
||||
if (phoneSpecialUser != null) {
|
||||
System.out.printf("小程序登录-匹配到手机号网格员:phone=%s, openid=%s%n",
|
||||
phoneSpecialUser.getPhone(), phoneSpecialUser.getOpenid());
|
||||
return handleSpecialUserLogin(phoneSpecialUser);
|
||||
}
|
||||
|
||||
// 6. 非网格员:处理普通用户(招聘者/求职者)登录逻辑
|
||||
String userType = dto.getUserType();
|
||||
// 6.1 优先匹配「OpenID+前端传入角色」的老用户
|
||||
AppUser existingUser = appUserService.selectByOpenid(dto.getOpenid(), userType);
|
||||
if (existingUser != null) {
|
||||
System.out.printf("小程序登录-匹配到普通老用户:openid=%s, userType=%s%n", dto.getOpenid(), userType, dto.getOrgType());
|
||||
return handleExistingUser(existingUser, userType,dto.getOrgType());
|
||||
}
|
||||
|
||||
// 6.2 处理普通用户的匹配与注册(手机号绑定、新用户创建等)
|
||||
return handleUserMatchAndRegister(dto.getOpenid(), dto.getUnionid(), dto.getPhone(), userType,dto.getOrgType());
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("小程序登录异常:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("登录失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序登录主逻辑
|
||||
* 核心逻辑:优先处理网格员(is_company_user=2),再处理普通招聘者/求职者
|
||||
|
||||
Reference in New Issue
Block a user