package com.ytpm.handle; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.ytpm.agent.enums.UserStatusEnum; import com.ytpm.app.enums.LoginType; import com.ytpm.app.model.YtDyzLoginRecord; import com.ytpm.app.model.YtDyzUser; import com.ytpm.app.param.LoginParam; import com.ytpm.app.view.WxDefaultConfig; import com.ytpm.general.RepMessage; import com.ytpm.general.Result; import com.ytpm.util.IPUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.CollectionUtils; import javax.servlet.http.HttpServletRequest; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; /** *

登陆模板

* 兼容多登陆模式及风控校验 *

需重写方法:
* 1.登陆参数校验 validateParams * 2.根据设备及渠道ID查询用户 queryUserByDeviceAndDitch * 3.获取登陆默认配置 getLoginConfig * 4.根据登陆参数获取系统用户 queryDyzUserByParam * 5.用户新注册逻辑 registryUser * 6.已注册用户处理逻辑 deadWithUserCrud * 7.登陆记录保存 saveLoginRecord * 8.远程调用风控 remoteCheckLoginRisk * 9.远程调用风控 remoteCheckRegRisk *

* *

回调方法:
* 1.用户注册时回调 beforeRegistryUser
* 2.用户登陆时回调 beforeDeadWithUserCrud *

* *

可选重写方法:
* 1.第三方登陆调用处理及参数传递 setThirdPartyLoginInfo
* 2.登陆成功后调用风控服务校验 ytRiskValidate * 3.登陆用户信息配置额外信息 setExtInfo *

* * @author lih * @date 2025/9/4 */ @Slf4j public abstract class AbstractLoginService { @Value("${risk.config.banned.tips}") private String tips; @Value("${spring.application.name:}") private String applicationName; protected abstract LoginType getLoginType(); /** * 登陆逻辑处理 * @param loginParam 登陆参数 * @param request request * @return YtDyzUser */ public final YtDyzUser loginHandle(LoginParam loginParam, HttpServletRequest request) { loginParam.setLoginIp(IPUtil.getClientIp(request)); // 获取默认配置 WxDefaultConfig defaultConfig = getLoginConfig(loginParam.getAppType()); if (Objects.isNull(defaultConfig)) { throw new CommonException(StrUtil.format("{}登录失败,未找到相应配置!", getLoginType().getTypeName())); } loginParam.setAppId(defaultConfig.getPlatformAppId()); // 参数校验 validateParams(loginParam, request); // 获取第三方登陆信息 如微信授权码、微信登陆后授权信息 Map paramMap = setThirdPartyLoginInfo(loginParam, defaultConfig, request); YtDyzUser ytDyzUser; if (getLoginType() == LoginType.VISITOR) { // 游客模式 paramMap.put("defaultConfig", defaultConfig); ytDyzUser = visitorLoginHandle(loginParam, paramMap); } else { ytDyzUser = clientLoginHandle(loginParam, paramMap); } // 配置额外信息 setExtInfo(ytDyzUser, paramMap); // 添加用户登录记录 addLoginRecord(loginParam,ytDyzUser); // 调用风控服务校验默认风控配置 ytRiskValidate(ytDyzUser, paramMap); // 游客登陆 校验通过 更新用户状态为正常 if (getLoginType() == LoginType.VISITOR) { updateUserStatus(ytDyzUser, UserStatusEnum.NORMAL, null); } return ytDyzUser; } protected abstract void updateUserStatus(YtDyzUser ytDyzUser, UserStatusEnum statusEnum, String reason); /** * 登陆参数校验 */ protected abstract void validateParams(LoginParam loginParam, HttpServletRequest request); /** * 微信端/IOS端登陆 */ private YtDyzUser clientLoginHandle(LoginParam loginParam, Map paramMap) { YtDyzUser ytDyzUser; List ytDyzUsers = queryDyzUserByParam(loginParam, paramMap); if (CollectionUtils.isEmpty(ytDyzUsers)) { beforeRegistryUser(loginParam, paramMap); ytDyzUser = new YtDyzUser(); registryUser(loginParam, ytDyzUser, paramMap); } else { ytDyzUser = ytDyzUsers.get(0); beforeDeadWithUserCrud(loginParam, ytDyzUser, paramMap); deadWithUserCrud(loginParam, ytDyzUser, paramMap); } ytDyzUser.setLoginType(LoginType.WX); return ytDyzUser; } /** * 游客模式登录 */ private YtDyzUser visitorLoginHandle(LoginParam loginParam, Map paramMap) { // 唯一性判断 YtDyzUser ytDyzUser = queryUserByDeviceAndDitch(loginParam.getDeviceId(), loginParam.getDitchId()); if(ytDyzUser == null) { log.warn(StrUtil.format("visitor register[ deviceId:{}, ditchId: {}]", loginParam.getDeviceId(), loginParam.getDitchId())); beforeRegistryUser(loginParam, paramMap); ytDyzUser = new YtDyzUser(); registryUser(loginParam, ytDyzUser, paramMap); } else { log.warn(StrUtil.format("visitor login[ deviceId:{}, ditchId: {}]", loginParam.getDeviceId(), loginParam.getDitchId())); //当前渠道已有用户,校验用户是否处于风控中 & 更新用户信息 beforeDeadWithUserCrud(loginParam, ytDyzUser, paramMap); //如果当前登录是本日第一次登录则登录天数+1 //202550916 游客登陆不记录登陆信息 deadWithUserCrud(loginParam, ytDyzUser, paramMap); } // 保存游客广告信息 WxDefaultConfig defaultConfig = (WxDefaultConfig) paramMap.get("defaultConfig"); saveVisitorAdRecord(ytDyzUser, loginParam, defaultConfig); ytDyzUser.setLoginType(LoginType.VISITOR); return ytDyzUser; } // 游客登陆时保存传递记录 protected void saveVisitorAdRecord(YtDyzUser ytDyzUser, LoginParam loginParam, WxDefaultConfig defaultConfig) { } /** * 根据设备及渠道ID查询用户 */ protected abstract YtDyzUser queryUserByDeviceAndDitch(String deviceId, Long ditchId); /** * 第三方登陆调用处理及参数传递 */ protected Map setThirdPartyLoginInfo(LoginParam loginParam, WxDefaultConfig defaultConfig, HttpServletRequest request) { Map map = new HashMap<>(); return map; } /** * 获取登陆默认配置 */ protected abstract WxDefaultConfig getLoginConfig(Integer appType); /** * 根据登陆配置信息 查询系统用户记录 * @param loginParam 登陆参数 * @param thirdPartyLoginInfo 第三方登陆西悉尼 */ protected abstract List queryDyzUserByParam(LoginParam loginParam, Map thirdPartyLoginInfo); // 注册用户处理器回调 protected void beforeRegistryUser(LoginParam loginParam, Map paramMap){ } // 用户注册逻辑 protected abstract YtDyzUser registryUser(LoginParam loginParam,YtDyzUser user, Map paramMap); // 已注册用户处理前回调 protected void beforeDeadWithUserCrud(LoginParam loginParam, YtDyzUser ytDyzUser, Map paramMap){ //当前渠道已有用户,校验用户是否处于风控中 & 更新用户信息 if(ytDyzUser != null && !ytDyzUser.getUserStatus().equals(UserStatusEnum.NORMAL.getCode()) && !ytDyzUser.getUserStatus().equals(UserStatusEnum.VISITOR_LOCK.getCode())){ throw new CommonException(getTipsMsg()); } } private String getTipsMsg(){ String[] split = tips.split(","); return split[RandomUtil.randomInt(split.length)]; } // 已注册用户处理逻辑 protected abstract void deadWithUserCrud(LoginParam loginParam, YtDyzUser old, Map paramMap); private void addLoginRecord(LoginParam param, YtDyzUser old) { YtDyzLoginRecord loginRecord = new YtDyzLoginRecord(); loginRecord.setRecordId(IdUtil.fastSimpleUUID()); loginRecord.setUserId(old.getUserId()); loginRecord.setLoginTime(new Date()); loginRecord.setDeviceBrand(param.getBrand()); loginRecord.setDeviceModel(param.getModel()); loginRecord.setLoginIp(param.getLoginIp()); loginRecord.setOperator(param.getIpOperator()); loginRecord.setIpAddr(param.getIpLocation()); loginRecord.setPhoneJson(param.getPhoneJson()); loginRecord.setLoginType(old.getLoginType().toString()); saveLoginRecord(loginRecord); } /** * 保存登陆记录实现 */ protected abstract void saveLoginRecord(YtDyzLoginRecord loginRecord); /** * 调用风控服务校验默认风控配置 */ protected void ytRiskValidate(YtDyzUser ytDyzUser, Map paramMap) { Result result = remoteCheckLoginRisk(ytDyzUser); if (result == null) { throw new CommonException("feign invoke Fail!"); } if (result.getCode() != 200) { String errorMessage = result.getMessage(); if (ytDyzUser.getLoginType() == LoginType.VISITOR && RepMessage.RISK_VISITOR_LOWER_VALUE.equals(errorMessage)) { WxDefaultConfig defaultConfig = (WxDefaultConfig) paramMap.get("defaultConfig"); throw new CommonException(StrUtil.emptyToDefault(defaultConfig.getLowValueTip(), errorMessage)); } throw new CommonException(errorMessage); } } /** * 配置相关信息 * * @param ytDyzUser * @param paramMap */ protected void setExtInfo(YtDyzUser ytDyzUser, Map paramMap) { ytDyzUser.setServiceName(applicationName); } /** * 远程调用校验用户风控,需设置风控编码[riskCode],并重写该方法 * @param ytDyzUser 当前用户 */ protected abstract Result remoteCheckLoginRisk(YtDyzUser ytDyzUser); /** * 远程调用校验注册用户 * @param user 参数 */ protected abstract Result remoteCheckRegRisk(YtDyzUser user); }