修改小程序登录逻辑
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.cms.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class WechatAuthVO {
|
||||
private String openid;
|
||||
private String unionid;
|
||||
private String sessionKey;
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.ruoyi.common.core.domain.entity.AppUserShow;
|
||||
import com.ruoyi.common.core.domain.entity.MyChart;
|
||||
import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* APP用户Mapper接口
|
||||
@@ -26,15 +27,15 @@ public interface AppUserMapper extends BaseMapper<AppUser>
|
||||
|
||||
List<AppUser> selectByJobId(Long jobId);
|
||||
|
||||
AppUser selectByOpenid(String openid);
|
||||
AppUser selectByOpenid(@Param("openid")String openid, @Param("userType") String userType);
|
||||
|
||||
int insertSysUserRole(Map<String,Object> map);
|
||||
|
||||
int insertSysUser(SysUser sysUser);
|
||||
|
||||
MyChart getMyTj(Long userId);
|
||||
MyChart getMyTj(@Param("userId") Long userId);
|
||||
|
||||
SysUser selectSysUserIdcard(String idCard);
|
||||
SysUser selectSysUserIdcard(@Param("idCard") String idCard);
|
||||
|
||||
List<AppUserShow> selectUserApplyList(AppUser appUser);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,11 @@ public interface IAppUserService
|
||||
|
||||
public AppUser getPhone(String phone);
|
||||
|
||||
AppUser selectByOpenid(String openid);
|
||||
public AppUser getPhoneAndNoRole(String phone);
|
||||
|
||||
public AppUser getPhoneAndUserType(String phone,String userType);
|
||||
|
||||
AppUser selectByOpenid(String openid,String userType);
|
||||
|
||||
public AppUser registerAppUser(RegisterBody registerBody);
|
||||
|
||||
|
||||
@@ -185,8 +185,20 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper,AppUser> imple
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppUser selectByOpenid(String openid) {
|
||||
return appUserMapper.selectByOpenid(openid);
|
||||
public AppUser getPhoneAndNoRole(String phone) {
|
||||
return appUserMapper.selectOne(new LambdaQueryWrapper<AppUser>()
|
||||
.eq(AppUser::getPhone, phone).eq(AppUser::getDelFlag,"0").isNull(AppUser::getIsCompanyUser).orderByDesc(AppUser::getUpdateTime).last("LIMIT 1"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppUser getPhoneAndUserType(String phone,String userType) {
|
||||
return appUserMapper.selectOne(new LambdaQueryWrapper<AppUser>()
|
||||
.eq(AppUser::getPhone, phone).eq(AppUser::getIsCompanyUser,userType).eq(AppUser::getDelFlag,"0").orderByDesc(AppUser::getUpdateTime).last("LIMIT 1"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppUser selectByOpenid(String openid,String userType) {
|
||||
return appUserMapper.selectByOpenid(openid,userType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -68,7 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectByOpenid" resultType="com.ruoyi.common.core.domain.entity.AppUser">
|
||||
<include refid="selectAppUserVo"/> WHERE DEL_FLAG = '0' and openid=#{openid} LIMIT 1
|
||||
<include refid="selectAppUserVo"/> WHERE DEL_FLAG = '0' and openid=#{openid} and is_company_user=#{userType} LIMIT 1
|
||||
</select>
|
||||
|
||||
<insert id="insertSysUserRole" parameterType="java.util.Map">
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.ruoyi.common.core.redis;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* JDK 1.8 兼容版分布式锁工具类(基于 Redis)
|
||||
*/
|
||||
@Component
|
||||
public class DistributedLockUtil {
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
// 锁默认配置
|
||||
private static final long DEFAULT_EXPIRE_SECONDS = 30;
|
||||
private static final long DEFAULT_ACQUIRE_TIMEOUT_SECONDS = 5;
|
||||
private static final long RENEW_INTERVAL_SECONDS = DEFAULT_EXPIRE_SECONDS / 3;
|
||||
|
||||
// 续期线程池
|
||||
private final ScheduledExecutorService renewExecutor = Executors.newScheduledThreadPool(
|
||||
Runtime.getRuntime().availableProcessors(),
|
||||
new ThreadFactory() {
|
||||
private final AtomicBoolean init = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, "distributed-lock-renewer");
|
||||
thread.setDaemon(true);
|
||||
if (init.compareAndSet(false, true)) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
renewExecutor.shutdown();
|
||||
}
|
||||
}));
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 释放锁 Lua 脚本(原子操作)
|
||||
private static final String RELEASE_LOCK_LUA_SCRIPT =
|
||||
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
|
||||
" return redis.call('del', KEYS[1]) " +
|
||||
"else " +
|
||||
" return 0 " +
|
||||
"end";
|
||||
private final DefaultRedisScript<Long> releaseScript = new DefaultRedisScript<>();
|
||||
|
||||
// 初始化 Lua 脚本
|
||||
{
|
||||
releaseScript.setScriptText(RELEASE_LOCK_LUA_SCRIPT);
|
||||
releaseScript.setResultType(Long.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取锁(带自动续期)
|
||||
*/
|
||||
public String acquireLockWithRenewal(String lockKey) {
|
||||
return acquireLockWithRenewal(lockKey, DEFAULT_EXPIRE_SECONDS, DEFAULT_ACQUIRE_TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义参数获取锁
|
||||
*/
|
||||
public String acquireLockWithRenewal(String lockKey, long expireSeconds, long acquireTimeoutSeconds) {
|
||||
String identifier = UUID.randomUUID().toString();
|
||||
long endTime = System.currentTimeMillis() + acquireTimeoutSeconds * 1000;
|
||||
|
||||
while (System.currentTimeMillis() < endTime) {
|
||||
boolean locked = tryLockOnce(lockKey, identifier, expireSeconds);
|
||||
if (locked) {
|
||||
startRenewal(lockKey, identifier, expireSeconds);
|
||||
return identifier;
|
||||
}
|
||||
|
||||
// 指数退避重试
|
||||
try {
|
||||
long sleepMs = calculateBackoffSleep(System.currentTimeMillis() - (endTime - acquireTimeoutSeconds * 1000));
|
||||
Thread.sleep(sleepMs);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 原子释放锁
|
||||
*/
|
||||
public boolean releaseLockSafely(String lockKey, String identifier) {
|
||||
if (identifier == null) {
|
||||
return false;
|
||||
}
|
||||
Long result = (Long) redisCache.redisTemplate.execute(
|
||||
releaseScript,
|
||||
Collections.singletonList(lockKey),
|
||||
identifier
|
||||
);
|
||||
return result != null && result > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取一次锁
|
||||
*/
|
||||
private boolean tryLockOnce(String lockKey, String identifier, long expireSeconds) {
|
||||
try {
|
||||
if (!redisCache.hasKey(lockKey)) {
|
||||
redisCache.setCacheObject(lockKey, identifier, (int) expireSeconds, TimeUnit.SECONDS);
|
||||
String storedId = redisCache.getCacheObject(lockKey);
|
||||
return identifier.equals(storedId);
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动锁自动续期
|
||||
*/
|
||||
private void startRenewal(final String lockKey, final String identifier, final long expireSeconds) {
|
||||
final AtomicReference<ScheduledFuture<?>> futureRef = new AtomicReference<>();
|
||||
Runnable renewalTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String storedId = redisCache.getCacheObject(lockKey);
|
||||
if (identifier.equals(storedId)) {
|
||||
redisCache.expire(lockKey, expireSeconds);
|
||||
} else {
|
||||
cancelFuture();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
cancelFuture();
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelFuture() {
|
||||
ScheduledFuture<?> future = futureRef.get();
|
||||
if (future != null && !future.isCancelled()) {
|
||||
future.cancel(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ScheduledFuture<?> future = renewExecutor.scheduleAtFixedRate(
|
||||
renewalTask,
|
||||
RENEW_INTERVAL_SECONDS,
|
||||
RENEW_INTERVAL_SECONDS,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
futureRef.set(future);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指数退避算法(计算重试间隔)
|
||||
*/
|
||||
private long calculateBackoffSleep(long elapsedMs) {
|
||||
int retryCount = (int) (elapsedMs / 100);
|
||||
long sleepMs = 100L * (1 << Math.min(retryCount, 10));
|
||||
return Math.min(sleepMs, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动释放锁工具(支持 try-with-resources)
|
||||
*/
|
||||
public static class AutoReleaseLock implements AutoCloseable {
|
||||
private final DistributedLockUtil lockUtil;
|
||||
private final String lockKey;
|
||||
private final String identifier;
|
||||
|
||||
public AutoReleaseLock(DistributedLockUtil lockUtil, String lockKey, String identifier) {
|
||||
this.lockUtil = lockUtil;
|
||||
this.lockKey = lockKey;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return identifier != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (isLocked()) {
|
||||
lockUtil.releaseLockSafely(lockKey, identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化锁使用
|
||||
*/
|
||||
public AutoReleaseLock tryLock(String lockKey) {
|
||||
String identifier = acquireLockWithRenewal(lockKey);
|
||||
return new AutoReleaseLock(this, lockKey, identifier);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import javax.annotation.Resource;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.cms.domain.vo.WechatAuthVO;
|
||||
import com.ruoyi.cms.service.IAppUserService;
|
||||
import com.ruoyi.cms.util.StringUtil;
|
||||
import com.ruoyi.cms.util.WechatUtil;
|
||||
@@ -12,6 +13,7 @@ import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
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.utils.*;
|
||||
import com.ruoyi.framework.web.exception.ParamErrorConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -69,6 +71,9 @@ public class SysLoginService
|
||||
WechatUtil wechatUtil;
|
||||
@Autowired
|
||||
private IAppUserService appUserService;
|
||||
@Autowired
|
||||
private DistributedLockUtil distributedLockUtil;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
@@ -258,7 +263,7 @@ public class SysLoginService
|
||||
return AjaxResult.error("微信授权失败");
|
||||
}
|
||||
//验证是否登录过
|
||||
AppUser existingUser=appUserService.selectByOpenid(openid);
|
||||
AppUser existingUser=appUserService.selectByOpenid(openid,dto.getUserType());
|
||||
if(existingUser!=null){
|
||||
if(StringUtils.isEmpty(existingUser.getIsCompanyUser())){
|
||||
updateAppUserCommon(existingUser,openid,unionid,dto.getUserType());
|
||||
@@ -316,44 +321,37 @@ public class SysLoginService
|
||||
* 小程序登录主逻辑
|
||||
*/
|
||||
public AjaxResult appLoginNew(LoginBody dto) {
|
||||
AjaxResult validateResult = validateLoginParam(dto, false);
|
||||
//1.验证基础参数
|
||||
AjaxResult validateResult = validateBaseParam(dto);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject sessionInfo = wechatUtil.code2Session(dto.getCode());
|
||||
String openid = sessionInfo.getString("openid");
|
||||
String unionid = sessionInfo.getString("unionid");
|
||||
String sessionKey = sessionInfo.getString("session_key");
|
||||
|
||||
if (openid == null) {
|
||||
//2. 微信授权获取OpenID/UnionID/SessionKey
|
||||
WechatAuthVO wechatAuthVO = getWechatAuthInfo(dto.getCode());
|
||||
if (wechatAuthVO == null) {
|
||||
return AjaxResult.error("微信授权失败");
|
||||
}
|
||||
String openid = wechatAuthVO.getOpenid();
|
||||
String unionid = wechatAuthVO.getUnionid();
|
||||
String sessionKey = wechatAuthVO.getSessionKey();
|
||||
|
||||
AppUser existingUser = appUserService.selectByOpenid(openid);
|
||||
String userType = dto.getUserType();
|
||||
//3. 优先匹配「OpenID+角色」的老用户
|
||||
AppUser existingUser = appUserService.selectByOpenid(openid,userType);
|
||||
if (existingUser != null) {
|
||||
return handleExistingUser(existingUser, dto.getUserType());
|
||||
return handleExistingUser(existingUser, userType);
|
||||
}
|
||||
|
||||
validateResult = validateLoginParam(dto, true);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
JSONObject phoneInfo = wechatUtil.decryptPhoneNumber(dto.getEncryptedData(), sessionKey, dto.getIv());
|
||||
String phone = phoneInfo.getString("phoneNumber");
|
||||
|
||||
// 4. 解密获取手机号(含二次校验)
|
||||
String phone = decryptPhone(dto, sessionKey);
|
||||
if (phone == null) {
|
||||
return AjaxResult.error("获取手机号失败");
|
||||
}
|
||||
|
||||
AppUser phoneUser = appUserService.getPhone(phone);
|
||||
if (phoneUser != null) {
|
||||
return handlePhoneBoundUser(phoneUser, openid, unionid, dto.getUserType());
|
||||
} else {
|
||||
return handleNewUser(openid, unionid, phone, dto.getUserType());
|
||||
}
|
||||
// 5. 处理用户匹配与注册(核心逻辑拆分到独立方法)
|
||||
return handleUserMatchAndRegister(openid, unionid, phone, userType);
|
||||
} catch (Exception e) {
|
||||
System.err.println("登录失败:" + e.getMessage());
|
||||
return AjaxResult.error("登录失败,请稍后重试");
|
||||
@@ -361,9 +359,11 @@ public class SysLoginService
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数校验方法(仅返回错误信息,补充userType校验)
|
||||
* 1-基础参数校验(原validateLoginParam false场景)
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult validateLoginParam(LoginBody dto, boolean needDecryptPhone) {
|
||||
private AjaxResult validateBaseParam(LoginBody dto) {
|
||||
if (dto == null) {
|
||||
return AjaxResult.error(ParamErrorConstants.PARAM_NULL_MSG);
|
||||
}
|
||||
@@ -376,17 +376,134 @@ public class SysLoginService
|
||||
!StringUtil.IS_JOB_REQUEST_USER.equals(userType)) {
|
||||
return AjaxResult.error(ParamErrorConstants.USER_TYPE_INVALID_MSG);
|
||||
}
|
||||
if (needDecryptPhone) {
|
||||
if (StringUtils.isEmpty(dto.getEncryptedData())) {
|
||||
return AjaxResult.error(ParamErrorConstants.ENCRYPTED_DATA_EMPTY_MSG);
|
||||
}
|
||||
if (StringUtils.isEmpty(dto.getIv())) {
|
||||
return AjaxResult.error(ParamErrorConstants.IV_EMPTY_MSG);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2-微信授权信息获取(封装code2Session逻辑)
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
private WechatAuthVO getWechatAuthInfo(String code) {
|
||||
JSONObject sessionInfo = wechatUtil.code2Session(code);
|
||||
if (sessionInfo == null || sessionInfo.getString("openid") == null) {
|
||||
return null;
|
||||
}
|
||||
WechatAuthVO authVO = new WechatAuthVO();
|
||||
authVO.setOpenid(sessionInfo.getString("openid"));
|
||||
authVO.setUnionid(StringUtils.isBlank(sessionInfo.getString("unionid")) ? "" : sessionInfo.getString("unionid"));
|
||||
authVO.setSessionKey(sessionInfo.getString("session_key"));
|
||||
return authVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3-手机号解密(含二次参数校验)
|
||||
* @param dto
|
||||
* @param sessionKey
|
||||
* @return
|
||||
*/
|
||||
private String decryptPhone(LoginBody dto, String sessionKey) {
|
||||
// 二次校验(解密相关参数)
|
||||
AjaxResult validateResult = validateDecryptParam(dto);
|
||||
if (validateResult != null) {
|
||||
return null;
|
||||
}
|
||||
// 解密手机号
|
||||
JSONObject phoneInfo = wechatUtil.decryptPhoneNumber(dto.getEncryptedData(), sessionKey, dto.getIv());
|
||||
String phone = phoneInfo.getString("phoneNumber");
|
||||
if (phone == null || phone.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return phone.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 4-解密参数校验(原validateLoginParam true场景)
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult validateDecryptParam(LoginBody dto) {
|
||||
if (StringUtils.isEmpty(dto.getEncryptedData())) {
|
||||
return AjaxResult.error(ParamErrorConstants.ENCRYPTED_DATA_EMPTY_MSG);
|
||||
}
|
||||
if (StringUtils.isEmpty(dto.getIv())) {
|
||||
return AjaxResult.error(ParamErrorConstants.IV_EMPTY_MSG);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 5-用户匹配与注册(含锁逻辑、无角色数据处理)
|
||||
* @param openid
|
||||
* @param unionid
|
||||
* @param phone
|
||||
* @param userType
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult handleUserMatchAndRegister(String openid, String unionid, String phone, String userType) {
|
||||
// 匹配「手机号+角色」的用户
|
||||
AppUser phoneRoleUser = appUserService.getPhoneAndUserType(phone, userType);
|
||||
if (phoneRoleUser != null) {
|
||||
return handlePhoneBoundUser(phoneRoleUser, openid, unionid, userType);
|
||||
}
|
||||
|
||||
// 匹配无角色历史数据
|
||||
AppUser noRoleUser = appUserService.getPhoneAndNoRole(phone);
|
||||
if (noRoleUser != null) {
|
||||
return handleNoRoleUserBinding(openid, unionid, phone, userType, noRoleUser);
|
||||
}
|
||||
|
||||
// 全新用户注册
|
||||
return handleNewUserRegistration(openid, unionid, phone, userType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 6-无角色用户绑定(含分布式锁)
|
||||
* @param openid
|
||||
* @param unionid
|
||||
* @param phone
|
||||
* @param userType
|
||||
* @param noRoleUser
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult handleNoRoleUserBinding(String openid, String unionid, String phone, String userType, AppUser noRoleUser) {
|
||||
String lockKey = "login_no_role_bind_" + phone + "_" + userType;
|
||||
try (DistributedLockUtil.AutoReleaseLock lock = distributedLockUtil.tryLock(lockKey)) {
|
||||
if (!lock.isLocked()) {
|
||||
return AjaxResult.error("登录请求过于频繁,请稍后重试");
|
||||
}
|
||||
// 双重检查
|
||||
AppUser doubleCheck = appUserService.getPhoneAndUserType(phone, userType);
|
||||
if (doubleCheck != null) {
|
||||
return handlePhoneBoundUser(doubleCheck, openid, unionid, userType);
|
||||
}
|
||||
return handlePhoneBoundUser(noRoleUser, openid, unionid, userType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 7-新用户注册(含分布式锁)
|
||||
* @param openid
|
||||
* @param unionid
|
||||
* @param phone
|
||||
* @param userType
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult handleNewUserRegistration(String openid, String unionid, String phone, String userType) {
|
||||
String createLockKey = "login_create_" + phone + "_" + userType;
|
||||
try (DistributedLockUtil.AutoReleaseLock lock = distributedLockUtil.tryLock(createLockKey)) {
|
||||
if (!lock.isLocked()) {
|
||||
return AjaxResult.error("登录请求过于频繁,请稍后重试");
|
||||
}
|
||||
// 双重检查
|
||||
AppUser checkNew = appUserService.getPhoneAndUserType(phone, userType);
|
||||
if (checkNew != null) {
|
||||
return handlePhoneBoundUser(checkNew, openid, unionid, userType);
|
||||
}
|
||||
return handleNewUser(openid, unionid, phone, userType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理老用户登录(日志用println)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user