diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index b4c1901..f4ca703 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -119,6 +119,10 @@ public interface ErrorCodeConstants { // ========== 社交用户 1-002-018-000 ========== ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}"); ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户"); + ErrorCode SOCIAL_USER_CODE_EXPIRED = new ErrorCode(1_002_018_002, "微信授权码已过期,请重新授权"); + ErrorCode SOCIAL_USER_CODE_INVALID = new ErrorCode(1_002_018_003, "微信授权码无效或已被使用"); + ErrorCode SOCIAL_USER_NETWORK_ERROR = new ErrorCode(1_002_018_005, "微信服务器连接失败,请稍后重试"); + ErrorCode SOCIAL_USER_OPENID_MISMATCH = new ErrorCode(1_002_018_006, "用户身份验证失败,请重新登录"); ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1_002_018_200, "获得手机号失败"); ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR = new ErrorCode(1_002_018_201, "获得小程序码失败"); @@ -128,8 +132,6 @@ public interface ErrorCodeConstants { ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_211, "社交客户端已存在配置"); ErrorCode SOCIAL_CLIENT_CODE_EXISTS = new ErrorCode(1_002_018_212, "社交客户端CODE不存在"); - - // ========== OAuth2 客户端 1-002-020-000 ========= ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在"); ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 客户端编号已存在"); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index 1b23d4f..9848e57 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java @@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -56,6 +57,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_AUTH_FAILURE; @Tag(name = "管理后台 - 认证") @RestController @@ -102,21 +104,40 @@ public class AuthController { @PostMapping("/app_login") @Operation(summary = "社交快捷登录,使用 code 授权码") public CommonResult AppLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) { - final AdminUserDO user = authService.miniAppLogin(reqVO); - - if (!user.getIsBand()) { - //添加绑定 - SocialUserBindReqDTO userBindReqDTO = new SocialUserBindReqDTO(); - userBindReqDTO.setUserId(user.getId()); - userBindReqDTO.setUserType(UserTypeEnum.MEMBER.getValue()); - userBindReqDTO.setCode(reqVO.getCode()); - userBindReqDTO.setSocialType(reqVO.getType()); - userBindReqDTO.setState(reqVO.getState()); - socialUserService.bindSocialUser(userBindReqDTO); - //给用户添加默认角色 可以编辑用户信息, 可以上传图片 - } + log.info("[AppLogin][小程序登录开始,code({}) type({}) userType({})]", + reqVO.getCode(), reqVO.getType(), reqVO.getUserType()); + + try { + final AdminUserDO user = authService.miniAppLogin(reqVO); + + if (!user.getIsBand()) { + log.info("[AppLogin][新用户绑定社交账号,userId({})]", user.getId()); + //添加绑定 + SocialUserBindReqDTO userBindReqDTO = new SocialUserBindReqDTO(); + userBindReqDTO.setUserId(user.getId()); + userBindReqDTO.setUserType(UserTypeEnum.MEMBER.getValue()); + userBindReqDTO.setCode(reqVO.getCode()); + userBindReqDTO.setSocialType(reqVO.getType()); + userBindReqDTO.setState(reqVO.getState()); + socialUserService.bindSocialUser(userBindReqDTO); + //给用户添加默认角色 可以编辑用户信息, 可以上传图片 + } + + AuthLoginRespVO respVO = authService.createTokenAfterLoginSuccess2( + user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL); - return success(authService.createTokenAfterLoginSuccess2(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL)); + log.info("[AppLogin][小程序登录成功,userId({}) username({}) token({})]", + user.getId(), user.getUsername(), respVO.getAccessToken()); + + return success(respVO); + + } catch (ServiceException e) { + log.error("[AppLogin][小程序登录失败,code({}) error({})]", reqVO.getCode(), e.getMessage()); + return error(e.getCode(), e.getMessage()); + } catch (Exception e) { + log.error("[AppLogin][小程序登录异常,code({})]", reqVO.getCode(), e); + return error(SOCIAL_USER_AUTH_FAILURE.getCode(), "登录失败,请重试"); + } } @PermitAll diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index a05c75a..630540b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; @@ -317,57 +318,95 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override @Transactional public AdminUserDO miniAppLogin(AuthSocialLoginReqVO reqVO) { + log.info("[miniAppLogin][开始小程序登录,code({}) type({}) userType({})]", + reqVO.getCode(), reqVO.getType(), reqVO.getUserType()); + + try { + AuthUser authUser = socialClientService.getAuthUser( + SocialTypeEnum.WECHAT_MINI_APP.getType(), + UserTypeEnum.ADMIN.getValue(),// 假设用户类型为会员 + reqVO.getCode(), + reqVO.getState() + ); + + log.info("[miniAppLogin][获取到用户信息,openId({}) nickname({})]", + authUser.getUuid(), authUser.getNickname()); + + final SocialUserDO socialUserDO = socialUserService.selectBySocialTypeAndOpenId( + SocialTypeEnum.WECHAT_MINI_APP.getType(), authUser.getUuid()); + + AdminUserDO user = null; + + if (socialUserDO == null ) { + log.info("[miniAppLogin][新用户注册,openId({})]", authUser.getUuid()); + +// String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo" + +// "?access_token=" + authUser.getToken() + +// "&openid=" + authUser.getUuid() + +// "&lang=zh_CN"; +// String userInfoResponse = HttpUtil.get(userInfoUrl); +// JSONObject userInfoJson = JSONUtil.parseObj(userInfoResponse); +// String nickname = userInfoJson.getStr("nickname"); + + // 未找到社交用户,插入记录 + SocialUserDO socialUser = new SocialUserDO(); + socialUser.setType(reqVO.getType()); + socialUser.setOpenid(authUser.getUuid()); + socialUser.setCode(reqVO.getCode()); + socialUser.setAvatar(authUser.getAvatar()); + socialUser.setRawTokenInfo(authUser.getToken().getRefreshToken() != null? authUser.getToken().getRefreshToken(): "default" ); + socialUser.setNickname(authUser.getNickname()); + socialUser.setState(reqVO.getState()); + socialUser.setRawUserInfo(authUser.getRawUserInfo() != null? authUser.getRawUserInfo().toString(): "default"); + final int insert = socialUserMapper.insert(socialUser); + + if (insert < 0) { + log.error("[miniAppLogin][插入社交用户失败,openId({})]", authUser.getUuid()); + throw exception(INSERT_ERROR); + } + user = userService.autoRegisterUser(authUser, reqVO.getUserType()); + + //给用户付一个普通用户角色可以上传图片 + UserRoleDO userRoleDO = new UserRoleDO(); + userRoleDO.setUserId(user.getId()); + userRoleDO.setRoleId(2l); + userRoleMapper.insert(userRoleDO); + + user.setIsBand(false); + log.info("[miniAppLogin][新用户注册成功,userId({}) username({})]", user.getId(), user.getUsername()); + + } else { + log.info("[miniAppLogin][已有用户登录,socialUserId({})]", socialUserDO.getId()); + + SocialUserBindDO bind = socialUserBindMapper.selectByUserTypeAndSocialUserId( + UserTypeEnum.MEMBER.getValue(), socialUserDO.getId()); + + if (bind == null) { + log.error("[miniAppLogin][未找到用户绑定信息,socialUserId({})]", socialUserDO.getId()); + throw exception(SOCIAL_USER_NOT_FOUND); + } - AuthUser authUser = socialClientService.getAuthUser( - SocialTypeEnum.WECHAT_MINI_APP.getType(), - UserTypeEnum.ADMIN.getValue(),// 假设用户类型为会员 - reqVO.getCode(), - reqVO.getState() - ); - - final SocialUserDO socialUserDO = socialUserService.selectBySocialTypeAndOpenId(SocialTypeEnum.WECHAT_MINI_APP.getType(), authUser.getUuid()); - - AdminUserDO user = null; - - if (socialUserDO == null ) { - // 未找到社交用户,插入记录 - SocialUserDO socialUser = new SocialUserDO(); - socialUser.setType(reqVO.getType()); - socialUser.setOpenid(authUser.getUuid()); - socialUser.setCode(reqVO.getCode()); - socialUser.setAvatar(authUser.getAvatar()); - socialUser.setRawTokenInfo(authUser.getToken().getRefreshToken() != null? authUser.getToken().getRefreshToken(): "default" ); - socialUser.setNickname(authUser.getNickname()); - socialUser.setState(reqVO.getState()); - socialUser.setRawUserInfo(authUser.getRawUserInfo() != null? authUser.getRawUserInfo().toString(): "default"); - final int insert = socialUserMapper.insert(socialUser); - - if (insert < 0) { - throw exception(INSERT_ERROR); - } - user = userService.autoRegisterUser(authUser, reqVO.getUserType()); - - //给用户付一个普通用户角色可以上传图片 - UserRoleDO userRoleDO = new UserRoleDO(); - userRoleDO.setUserId(user.getId()); - userRoleDO.setRoleId(2l); - userRoleMapper.insert(userRoleDO); +// // 获得用户 + user = userService.getUser(bind.getUserId()); - user.setIsBand(false); + if (user == null) { + log.error("[miniAppLogin][用户不存在,userId({})]", bind.getUserId()); + throw exception(USER_NOT_EXISTS); + } - } else { + user.setIsBand(true); + log.info("[miniAppLogin][用户登录成功,userId({}) username({})]", user.getId(), user.getUsername()); + } - SocialUserBindDO bind = socialUserBindMapper.selectByUserTypeAndSocialUserId(UserTypeEnum.MEMBER.getValue(), socialUserDO.getId()); -// // 获得用户 - user = userService.getUser(bind.getUserId()); + return user; - if (user == null) { - throw exception(USER_NOT_EXISTS); - } - user.setIsBand(true); + } catch (ServiceException e) { + log.error("[miniAppLogin][小程序登录失败,code({}) error({})]", reqVO.getCode(), e.getMessage()); + throw e; + } catch (Exception e) { + log.error("[miniAppLogin][小程序登录异常,code({})]", reqVO.getCode(), e); + throw exception(SOCIAL_USER_AUTH_FAILURE, e.getMessage()); } - - return user; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 1da2c0b..2ea5698 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -14,6 +14,7 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.cache.CacheUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; @@ -158,14 +159,43 @@ public class SocialClientServiceImpl implements SocialClientService { // 构建请求 AuthRequest authRequest = buildAuthRequest(socialType, userType); AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build(); - // 执行请求 - AuthResponse authResponse = authRequest.login(authCallback); - log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", socialType, + + try { + // 执行请求 + log.info("[getAuthUser][开始请求社交平台,type({}) userType({}) code({})]", socialType, userType, code); + AuthResponse authResponse = authRequest.login(authCallback); + log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", socialType, toJsonString(authCallback), toJsonString(authResponse)); - if (!authResponse.ok()) { - throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg()); + + if (!authResponse.ok()) { + // 分析错误原因 + String errorMsg = authResponse.getMsg(); + log.error("[getAuthUser][社交授权失败,type({}) code({}) errorMsg({})]", socialType, code, errorMsg); + + // 根据错误信息判断具体错误类型 + if (errorMsg != null) { + if (errorMsg.contains("invalid code") || errorMsg.contains("40163") || errorMsg.contains("code been used")) { + throw exception(SOCIAL_USER_CODE_INVALID); + } else if (errorMsg.contains("code expired") || errorMsg.contains("40029")) { + throw exception(SOCIAL_USER_CODE_EXPIRED); + } else if (errorMsg.contains("network") || errorMsg.contains("timeout")) { + throw exception(SOCIAL_USER_NETWORK_ERROR); + } + } + + // 默认错误 + throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg()); + } + return (AuthUser) authResponse.getData(); + + } catch (Exception e) { + // 捕获其他异常 + if (e instanceof ServiceException) { + throw e; // 如果是我们的业务异常,直接抛出 + } + log.error("[getAuthUser][请求社交平台异常,type({}) code({}) error({})]", socialType, code, e.getMessage(), e); + throw exception(SOCIAL_USER_NETWORK_ERROR); } - return (AuthUser) authResponse.getData(); } /**