package com.ytpm.handle; import cn.hutool.core.collection.CollUtil; 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.Result; import com.ytpm.util.IPUtil; 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.Objects; import java.util.Map; /** *

登陆模板

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

需重写方法:
* 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 */ public abstract class AbstractLoginService { @Value("${risk.config.banned.tips}") private String tips; 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.getUserId()); // 调用风控服务校验默认风控配置 ytRiskValidate(ytDyzUser); return ytDyzUser; } /** * 登陆参数校验 */ 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); } return ytDyzUser; } /** * 游客模式登录 */ private YtDyzUser visitorLoginHandle(LoginParam loginParam, Map paramMap) { // 唯一性判断 // 1.查询设备ID不存在记录 则根据设备id+渠道id注册用户 // 2.查询设备ID存在记录 则根据渠道ID控制唯一性,同步出路风控记录 YtDyzUser ytDyzUser = null; List ytDyzUsers = queryDyzUserByParam(loginParam, paramMap); if(CollUtil.isEmpty(ytDyzUsers)) { //注册后回调 beforeRegistryUser(loginParam, paramMap); ytDyzUser = new YtDyzUser(); registryUser(loginParam, ytDyzUser, paramMap); } else { // 查询当前设备当前渠道是否存在该用户 ytDyzUser = queryUserByDeviceAndDitch(loginParam.getDeviceId(), loginParam.getDitchId()); if(ytDyzUser == null) { ytDyzUser = new YtDyzUser(); registryUser(loginParam, ytDyzUser, paramMap); } //当前渠道已有用户,校验用户是否处于风控中 & 更新用户信息 beforeDeadWithUserCrud(loginParam, ytDyzUser, paramMap); //如果当前登录是本日第一次登录则登录天数+1 deadWithUserCrud(loginParam, ytDyzUser, paramMap); } // 保存广告信息 WxDefaultConfig defaultConfig = (WxDefaultConfig) paramMap.get("defaultConfig"); saveVisitorAdRecord(ytDyzUser, loginParam, defaultConfig); 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())){ 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, String userId) { YtDyzLoginRecord loginRecord = new YtDyzLoginRecord(); loginRecord.setRecordId(IdUtil.fastSimpleUUID()); loginRecord.setUserId(userId); 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()); saveLoginRecord(loginRecord); } /** * 保存登陆记录实现 */ protected abstract void saveLoginRecord(YtDyzLoginRecord loginRecord); /** * 调用风控服务校验默认风控配置 */ protected void ytRiskValidate(YtDyzUser ytDyzUser) { Result result = remoteCheckLoginRisk(ytDyzUser); if (result == null || result.getCode() != 200) { throw new CommonException(result == null ? "feign invoke Fail!" : result.getMessage()); } } /** * 配置相关信息 * * @param ytDyzUser * @param paramMap */ protected void setExtInfo(YtDyzUser ytDyzUser, Map paramMap) { } /** * 远程调用校验用户风控,需设置风控编码[riskCode],并重写该方法 * @param ytDyzUser 当前用户 */ protected abstract Result remoteCheckLoginRisk(YtDyzUser ytDyzUser); /** * 远程调用校验注册用户 * @param user 参数 */ protected abstract Result remoteCheckRegRisk(YtDyzUser user); }