| | |
| | | |
| | | import com.rongyichuang.auth.dto.LoginRequest; |
| | | import com.rongyichuang.auth.dto.LoginResponse; |
| | | import com.rongyichuang.auth.dto.PhoneDecryptResponse; |
| | | import com.rongyichuang.auth.dto.WxLoginRequest; |
| | | import com.rongyichuang.auth.dto.WxLoginResponse; |
| | | import com.rongyichuang.auth.entity.WxLoginRecord; |
| | | import com.rongyichuang.auth.util.JwtUtil; |
| | | import com.rongyichuang.service.WechatApiService; |
| | | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.databind.JsonMappingException; |
| | | import com.rongyichuang.employee.entity.Employee; |
| | | import com.rongyichuang.employee.repository.EmployeeRepository; |
| | | import com.rongyichuang.judge.entity.Judge; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Optional; |
| | | import javax.crypto.Cipher; |
| | | import javax.crypto.spec.IvParameterSpec; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.util.Base64; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | |
| | | /** |
| | | * 认证服务类 |
| | |
| | | |
| | | @Autowired |
| | | private JwtUtil jwtUtil; |
| | | |
| | | @Autowired |
| | | private WxLoginRecordService wxLoginRecordService; |
| | | |
| | | @Autowired |
| | | private WechatApiService wechatApiService; |
| | | |
| | | /** |
| | | * 用户登录 |
| | |
| | | throw new BadCredentialsException("没有权限"); |
| | | } |
| | | |
| | | // 6. 生成JWT token |
| | | // 7. 生成JWT token |
| | | String token = jwtUtil.generateToken(user.getId(), user.getPhone()); |
| | | |
| | | // 7. 确定主要角色类型(优先级:employee > judge > player) |
| | | // 8. 确定主要角色类型(优先级:employee > judge > player) |
| | | String userType; |
| | | if (employeeOpt.isPresent()) { |
| | | userType = "employee"; |
| | |
| | | userType = "player"; |
| | | } |
| | | |
| | | // 8. 构建用户信息 |
| | | // 9. 构建用户信息 |
| | | LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo( |
| | | user.getId(), |
| | | user.getName(), |
| | |
| | | userType |
| | | ); |
| | | |
| | | // 9. 设置所有关联的角色信息 |
| | | // 10. 设置所有关联的角色信息 |
| | | if (employeeOpt.isPresent()) { |
| | | Employee employee = employeeOpt.get(); |
| | | userInfo.setEmployee(new LoginResponse.EmployeeInfo( |
| | |
| | | player.getId(), |
| | | player.getName(), |
| | | player.getPhone(), |
| | | player.getDescription(), |
| | | player.getAuditState() |
| | | player.getDescription() |
| | | )); |
| | | if (employeeOpt.isEmpty() && judgeOpt.isEmpty()) { |
| | | logger.info("学员登录成功,ID: {}, 姓名: {}", player.getId(), player.getName()); |
| | |
| | | |
| | | return new LoginResponse(token, userInfo); |
| | | } |
| | | |
| | | /** |
| | | * 微信登录 |
| | | */ |
| | | public WxLoginResponse wxLogin(WxLoginRequest wxLoginRequest) throws JsonProcessingException, JsonMappingException { |
| | | logger.info("=== 开始微信登录流程 ==="); |
| | | logger.info("登录时间: {}", java.time.LocalDateTime.now()); |
| | | logger.info("请求参数详情:"); |
| | | logger.info("- code: {}", wxLoginRequest.getCode()); |
| | | logger.info("- code长度: {}", wxLoginRequest.getCode() != null ? wxLoginRequest.getCode().length() : 0); |
| | | logger.info("- wxOpenid: {}", wxLoginRequest.getWxOpenid()); |
| | | logger.info("- wxUnionid: {}", wxLoginRequest.getWxUnionid()); |
| | | logger.info("- phone: {}", wxLoginRequest.getPhone()); |
| | | logger.info("- loginIp: {}", wxLoginRequest.getLoginIp()); |
| | | logger.info("- deviceInfo: {}", wxLoginRequest.getDeviceInfo()); |
| | | logger.info("- phoneAuthorized: {}", wxLoginRequest.getPhoneAuthorized()); |
| | | |
| | | // 1. 通过code调用微信API获取openid和unionid |
| | | WechatApiService.WechatUserInfo wechatUserInfo = null; |
| | | if (wxLoginRequest.getCode() != null && !wxLoginRequest.getCode().trim().isEmpty()) { |
| | | logger.info("步骤1: 调用微信API获取用户信息"); |
| | | logger.info("使用code: {}", wxLoginRequest.getCode()); |
| | | |
| | | try { |
| | | wechatUserInfo = wechatApiService.getWechatUserInfo(wxLoginRequest.getCode()); |
| | | |
| | | // 将从微信API获取的信息设置到请求对象中 |
| | | wxLoginRequest.setWxOpenid(wechatUserInfo.getOpenid()); |
| | | wxLoginRequest.setWxUnionid(wechatUserInfo.getUnionid()); |
| | | wxLoginRequest.setSessionKey(wechatUserInfo.getSessionKey()); |
| | | |
| | | logger.info("✅ 从微信API获取用户信息成功"); |
| | | logger.info("- openid: {}", wechatUserInfo.getOpenid()); |
| | | logger.info("- unionid: {}", wechatUserInfo.getUnionid()); |
| | | logger.info("- sessionKey长度: {}", wechatUserInfo.getSessionKey() != null ? wechatUserInfo.getSessionKey().length() : 0); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("❌ 调用微信API失败"); |
| | | logger.error("异常信息: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | throw e; |
| | | } |
| | | } else { |
| | | logger.warn("⚠️ 微信登录code为空,将使用请求中的openid和unionid"); |
| | | logger.info("请求中的openid: {}", wxLoginRequest.getWxOpenid()); |
| | | logger.info("请求中的unionid: {}", wxLoginRequest.getWxUnionid()); |
| | | } |
| | | |
| | | User user = null; |
| | | boolean isNewUser = false; |
| | | |
| | | logger.info("步骤2: 查找或创建用户"); |
| | | |
| | | // 2. 首先尝试通过openid查找用户 |
| | | if (wxLoginRequest.getWxOpenid() != null && !wxLoginRequest.getWxOpenid().trim().isEmpty()) { |
| | | logger.info("尝试通过openid查找用户: {}", wxLoginRequest.getWxOpenid()); |
| | | |
| | | try { |
| | | Optional<User> userOpt = userRepository.findByWxOpenid(wxLoginRequest.getWxOpenid()); |
| | | if (userOpt.isPresent()) { |
| | | user = userOpt.get(); |
| | | logger.info("✅ 通过openid找到用户"); |
| | | logger.info("- 用户ID: {}", user.getId()); |
| | | logger.info("- 用户姓名: {}", user.getName()); |
| | | logger.info("- 用户手机号: {}", user.getPhone()); |
| | | logger.info("- 用户unionid: {}", user.getWxUnionid()); |
| | | } else { |
| | | logger.info("❌ 通过openid未找到用户"); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 通过openid查找用户时发生异常: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | } else { |
| | | logger.warn("⚠️ openid为空,跳过openid查找"); |
| | | } |
| | | |
| | | // 3. 如果通过openid没找到,尝试通过unionid查找 |
| | | if (user == null && wxLoginRequest.getWxUnionid() != null && !wxLoginRequest.getWxUnionid().trim().isEmpty()) { |
| | | logger.info("尝试通过unionid查找用户: {}", wxLoginRequest.getWxUnionid()); |
| | | |
| | | try { |
| | | Optional<User> userOpt = userRepository.findByWxUnionid(wxLoginRequest.getWxUnionid()); |
| | | if (userOpt.isPresent()) { |
| | | user = userOpt.get(); |
| | | logger.info("✅ 通过unionid找到用户"); |
| | | logger.info("- 用户ID: {}", user.getId()); |
| | | logger.info("- 用户姓名: {}", user.getName()); |
| | | logger.info("- 用户手机号: {}", user.getPhone()); |
| | | logger.info("- 用户openid: {}", user.getWxOpenid()); |
| | | |
| | | // 更新用户的openid(如果之前没有) |
| | | if (user.getWxOpenid() == null || user.getWxOpenid().trim().isEmpty()) { |
| | | logger.info("用户openid为空,需要更新"); |
| | | user.setWxOpenid(wxLoginRequest.getWxOpenid()); |
| | | try { |
| | | userRepository.save(user); |
| | | logger.info("✅ 成功更新用户openid,用户ID: {}", user.getId()); |
| | | } catch (Exception e) { |
| | | logger.error("❌ 更新用户openid失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | } else { |
| | | logger.info("用户openid已存在,无需更新"); |
| | | } |
| | | } else { |
| | | logger.info("❌ 通过unionid未找到用户"); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 通过unionid查找用户时发生异常: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | } else { |
| | | logger.warn("⚠️ unionid为空或用户已找到,跳过unionid查找"); |
| | | } |
| | | |
| | | // 4. 如果都没找到,创建新用户 |
| | | if (user == null) { |
| | | logger.info("未找到现有用户,开始创建新用户"); |
| | | logger.info("新用户信息:"); |
| | | logger.info("- openid: {}", wxLoginRequest.getWxOpenid()); |
| | | logger.info("- unionid: {}", wxLoginRequest.getWxUnionid()); |
| | | logger.info("- phone: {}", wxLoginRequest.getPhone()); |
| | | |
| | | try { |
| | | user = new User(); |
| | | user.setWxOpenid(wxLoginRequest.getWxOpenid()); |
| | | user.setWxUnionid(wxLoginRequest.getWxUnionid()); |
| | | user.setName("微信用户"); // 默认名称,后续可以更新 |
| | | user.setPhone(wxLoginRequest.getPhone()); // 如果有授权手机号 |
| | | |
| | | user = userRepository.save(user); |
| | | isNewUser = true; |
| | | |
| | | logger.info("✅ 成功创建新的微信用户"); |
| | | logger.info("- 新用户ID: {}", user.getId()); |
| | | logger.info("- 新用户姓名: {}", user.getName()); |
| | | logger.info("- 新用户手机号: {}", user.getPhone()); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("❌ 创建新用户失败"); |
| | | logger.error("异常信息: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | throw new RuntimeException("创建新用户失败: " + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | // 5. 记录登录信息到新表 |
| | | logger.info("步骤3: 记录登录信息"); |
| | | WxLoginRecord loginRecord = null; |
| | | try { |
| | | loginRecord = wxLoginRecordService.createLoginRecord( |
| | | wxLoginRequest.getWxOpenid(), |
| | | wxLoginRequest.getWxUnionid(), |
| | | user.getId(), |
| | | wxLoginRequest.getLoginIp(), |
| | | wxLoginRequest.getDeviceInfo(), |
| | | wxLoginRequest.getSessionKey(), |
| | | wxLoginRequest.getPhoneAuthorized() |
| | | ); |
| | | logger.info("✅ 成功创建登录记录,记录ID: {}", loginRecord.getId()); |
| | | } catch (Exception e) { |
| | | logger.error("❌ 创建登录记录失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | throw new RuntimeException("创建登录记录失败: " + e.getMessage(), e); |
| | | } |
| | | |
| | | // 6. 查找关联的员工、评委和学员信息 |
| | | logger.info("步骤4: 查找用户关联的角色信息"); |
| | | logger.info("查找用户ID: {}", user.getId()); |
| | | |
| | | Optional<Employee> employeeOpt = Optional.empty(); |
| | | Optional<Judge> judgeOpt = Optional.empty(); |
| | | Optional<Player> playerOpt = Optional.empty(); |
| | | |
| | | try { |
| | | employeeOpt = employeeRepository.findByUserId(user.getId()); |
| | | logger.info("员工角色查找结果: {}", employeeOpt.isPresent() ? "找到" : "未找到"); |
| | | if (employeeOpt.isPresent()) { |
| | | Employee employee = employeeOpt.get(); |
| | | logger.info("- 员工ID: {}", employee.getId()); |
| | | logger.info("- 员工姓名: {}", employee.getName()); |
| | | logger.info("- 员工角色ID: {}", employee.getRoleId()); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 查找员工角色时发生异常: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | |
| | | try { |
| | | judgeOpt = judgeRepository.findByUserId(user.getId()); |
| | | logger.info("评委角色查找结果: {}", judgeOpt.isPresent() ? "找到" : "未找到"); |
| | | if (judgeOpt.isPresent()) { |
| | | Judge judge = judgeOpt.get(); |
| | | logger.info("- 评委ID: {}", judge.getId()); |
| | | logger.info("- 评委姓名: {}", judge.getName()); |
| | | logger.info("- 评委职称: {}", judge.getTitle()); |
| | | logger.info("- 评委公司: {}", judge.getCompany()); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 查找评委角色时发生异常: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | |
| | | try { |
| | | playerOpt = playerRepository.findByUserId(user.getId()); |
| | | logger.info("学员角色查找结果: {}", playerOpt.isPresent() ? "找到" : "未找到"); |
| | | if (playerOpt.isPresent()) { |
| | | Player player = playerOpt.get(); |
| | | logger.info("- 学员ID: {}", player.getId()); |
| | | logger.info("- 学员姓名: {}", player.getName()); |
| | | logger.info("- 学员手机号: {}", player.getPhone()); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 查找学员角色时发生异常: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | |
| | | // 6. 生成JWT token |
| | | logger.info("步骤5: 生成JWT token"); |
| | | String tokenIdentifier = user.getPhone() != null ? user.getPhone() : user.getWxOpenid(); |
| | | logger.info("Token标识符: {}", tokenIdentifier); |
| | | |
| | | String token = null; |
| | | try { |
| | | token = jwtUtil.generateToken(user.getId(), tokenIdentifier); |
| | | logger.info("✅ 成功生成JWT token,长度: {}", token != null ? token.length() : 0); |
| | | } catch (Exception e) { |
| | | logger.error("❌ 生成JWT token失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | throw new RuntimeException("生成JWT token失败: " + e.getMessage(), e); |
| | | } |
| | | |
| | | // 7. 确定主要角色类型(优先级:employee > judge > player) |
| | | logger.info("步骤6: 确定用户主要角色类型"); |
| | | String userType; |
| | | if (employeeOpt.isPresent()) { |
| | | userType = "employee"; |
| | | logger.info("用户主要角色: 员工"); |
| | | } else if (judgeOpt.isPresent()) { |
| | | userType = "judge"; |
| | | logger.info("用户主要角色: 评委"); |
| | | } else if (playerOpt.isPresent()) { |
| | | userType = "player"; |
| | | logger.info("用户主要角色: 学员"); |
| | | } else { |
| | | userType = "user"; // 普通微信用户 |
| | | logger.info("用户主要角色: 普通微信用户"); |
| | | } |
| | | |
| | | // 8. 构建用户信息 |
| | | logger.info("步骤7: 构建用户信息响应"); |
| | | LoginResponse.UserInfo userInfo = null; |
| | | try { |
| | | userInfo = new LoginResponse.UserInfo( |
| | | user.getId(), |
| | | user.getName(), |
| | | user.getPhone(), |
| | | userType |
| | | ); |
| | | logger.info("✅ 成功构建基础用户信息"); |
| | | logger.info("- 用户ID: {}", user.getId()); |
| | | logger.info("- 用户姓名: {}", user.getName()); |
| | | logger.info("- 用户手机号: {}", user.getPhone()); |
| | | logger.info("- 用户类型: {}", userType); |
| | | } catch (Exception e) { |
| | | logger.error("❌ 构建基础用户信息失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | throw new RuntimeException("构建基础用户信息失败: " + e.getMessage(), e); |
| | | } |
| | | |
| | | // 9. 设置所有关联的角色信息 |
| | | logger.info("步骤8: 设置角色详细信息"); |
| | | |
| | | if (employeeOpt.isPresent()) { |
| | | try { |
| | | Employee employee = employeeOpt.get(); |
| | | userInfo.setEmployee(new LoginResponse.EmployeeInfo( |
| | | employee.getId(), |
| | | employee.getName(), |
| | | employee.getRoleId(), |
| | | employee.getDescription() |
| | | )); |
| | | logger.info("✅ 设置员工信息成功"); |
| | | logger.info("- 员工ID: {}", employee.getId()); |
| | | logger.info("- 员工姓名: {}", employee.getName()); |
| | | logger.info("- 员工角色ID: {}", employee.getRoleId()); |
| | | logger.info("员工微信登录成功,ID: {}, 姓名: {}", employee.getId(), employee.getName()); |
| | | } catch (Exception e) { |
| | | logger.error("❌ 设置员工信息失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | } |
| | | |
| | | if (judgeOpt.isPresent()) { |
| | | try { |
| | | Judge judge = judgeOpt.get(); |
| | | userInfo.setJudge(new LoginResponse.JudgeInfo( |
| | | judge.getId(), |
| | | judge.getName(), |
| | | judge.getTitle(), |
| | | judge.getCompany(), |
| | | judge.getDescription() |
| | | )); |
| | | logger.info("✅ 设置评委信息成功"); |
| | | logger.info("- 评委ID: {}", judge.getId()); |
| | | logger.info("- 评委姓名: {}", judge.getName()); |
| | | logger.info("- 评委职称: {}", judge.getTitle()); |
| | | logger.info("- 评委公司: {}", judge.getCompany()); |
| | | |
| | | if (employeeOpt.isEmpty()) { |
| | | logger.info("评委微信登录成功,ID: {}, 姓名: {}", judge.getId(), judge.getName()); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 设置评委信息失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | } |
| | | |
| | | if (playerOpt.isPresent()) { |
| | | try { |
| | | Player player = playerOpt.get(); |
| | | userInfo.setPlayer(new LoginResponse.PlayerInfo( |
| | | player.getId(), |
| | | player.getName(), |
| | | player.getPhone(), |
| | | player.getDescription() |
| | | )); |
| | | logger.info("✅ 设置学员信息成功"); |
| | | logger.info("- 学员ID: {}", player.getId()); |
| | | logger.info("- 学员姓名: {}", player.getName()); |
| | | logger.info("- 学员手机号: {}", player.getPhone()); |
| | | |
| | | if (employeeOpt.isEmpty() && judgeOpt.isEmpty()) { |
| | | logger.info("学员微信登录成功,ID: {}, 姓名: {}", player.getId(), player.getName()); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("❌ 设置学员信息失败: {}", e.getMessage()); |
| | | logger.error("异常堆栈:", e); |
| | | } |
| | | } |
| | | |
| | | logger.info("=== 微信登录流程完成 ==="); |
| | | logger.info("登录结果:"); |
| | | logger.info("- 是否新用户: {}", isNewUser); |
| | | logger.info("- 登录记录ID: {}", loginRecord != null ? loginRecord.getId() : "null"); |
| | | logger.info("- Token长度: {}", token != null ? token.length() : 0); |
| | | logger.info("- 用户类型: {}", userType); |
| | | logger.info("完成时间: {}", java.time.LocalDateTime.now()); |
| | | |
| | | return new WxLoginResponse(token, userInfo, isNewUser, loginRecord.getId(), wxLoginRequest.getSessionKey()); |
| | | } |
| | | |
| | | /** |
| | | * 解密微信手机号 |
| | | */ |
| | | public PhoneDecryptResponse decryptPhoneNumber(String encryptedData, String iv, String sessionKey) { |
| | | logger.info("=== 开始解密微信手机号 ==="); |
| | | logger.info("解密时间: {}", java.time.LocalDateTime.now()); |
| | | logger.info("encryptedData长度: {}", encryptedData != null ? encryptedData.length() : 0); |
| | | logger.info("iv长度: {}", iv != null ? iv.length() : 0); |
| | | logger.info("sessionKey长度: {}", sessionKey != null ? sessionKey.length() : 0); |
| | | |
| | | try { |
| | | // 1. Base64解码 |
| | | byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData); |
| | | byte[] ivBytes = Base64.getDecoder().decode(iv); |
| | | byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey); |
| | | |
| | | logger.info("Base64解码成功"); |
| | | logger.info("encryptedBytes长度: {}", encryptedBytes.length); |
| | | logger.info("ivBytes长度: {}", ivBytes.length); |
| | | logger.info("sessionKeyBytes长度: {}", sessionKeyBytes.length); |
| | | |
| | | // 2. AES解密 |
| | | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); |
| | | SecretKeySpec secretKeySpec = new SecretKeySpec(sessionKeyBytes, "AES"); |
| | | IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); |
| | | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); |
| | | |
| | | byte[] decryptedBytes = cipher.doFinal(encryptedBytes); |
| | | String decryptedData = new String(decryptedBytes, "UTF-8"); |
| | | |
| | | logger.info("AES解密成功"); |
| | | logger.info("解密后数据长度: {}", decryptedData.length()); |
| | | logger.info("解密后数据: {}", decryptedData); |
| | | |
| | | // 3. 解析JSON |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | WechatPhoneInfo phoneInfo = objectMapper.readValue(decryptedData, WechatPhoneInfo.class); |
| | | |
| | | logger.info("JSON解析成功"); |
| | | logger.info("手机号: {}", phoneInfo.getPhoneNumber()); |
| | | logger.info("纯手机号: {}", phoneInfo.getPurePhoneNumber()); |
| | | logger.info("国家代码: {}", phoneInfo.getCountryCode()); |
| | | |
| | | PhoneDecryptResponse response = new PhoneDecryptResponse( |
| | | phoneInfo.getPhoneNumber(), |
| | | phoneInfo.getPurePhoneNumber(), |
| | | phoneInfo.getCountryCode() |
| | | ); |
| | | |
| | | logger.info("✅ 微信手机号解密成功"); |
| | | return response; |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("❌ 微信手机号解密失败", e); |
| | | String friendlyMessage = getDecryptFriendlyErrorMessage(e); |
| | | throw new RuntimeException(friendlyMessage, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 使用新版API通过code直接获取手机号 |
| | | */ |
| | | public PhoneDecryptResponse getPhoneNumberByCode(String code) { |
| | | logger.info("=== 开始使用新版API获取手机号 ==="); |
| | | logger.info("获取时间: {}", java.time.LocalDateTime.now()); |
| | | logger.info("输入code: {}", code); |
| | | |
| | | try { |
| | | // 调用微信API服务获取手机号 |
| | | WechatApiService.WechatPhoneInfo phoneInfo = wechatApiService.getPhoneNumberByCode(code); |
| | | |
| | | logger.info("✅ 新版API获取手机号成功"); |
| | | logger.info("手机号: {}", phoneInfo.getPhoneNumber()); |
| | | logger.info("纯手机号: {}", phoneInfo.getPurePhoneNumber()); |
| | | logger.info("国家代码: {}", phoneInfo.getCountryCode()); |
| | | |
| | | PhoneDecryptResponse response = new PhoneDecryptResponse( |
| | | phoneInfo.getPhoneNumber(), |
| | | phoneInfo.getPurePhoneNumber(), |
| | | phoneInfo.getCountryCode() |
| | | ); |
| | | |
| | | return response; |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("❌ 新版API获取手机号失败", e); |
| | | // 直接传递WechatApiService的友好错误信息 |
| | | throw new RuntimeException(e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 微信手机号信息 |
| | | */ |
| | | @JsonIgnoreProperties(ignoreUnknown = true) |
| | | public static class WechatPhoneInfo { |
| | | private String phoneNumber; |
| | | private String purePhoneNumber; |
| | | private String countryCode; |
| | | |
| | | public String getPhoneNumber() { |
| | | return phoneNumber; |
| | | } |
| | | |
| | | public void setPhoneNumber(String phoneNumber) { |
| | | this.phoneNumber = phoneNumber; |
| | | } |
| | | |
| | | public String getPurePhoneNumber() { |
| | | return purePhoneNumber; |
| | | } |
| | | |
| | | public void setPurePhoneNumber(String purePhoneNumber) { |
| | | this.purePhoneNumber = purePhoneNumber; |
| | | } |
| | | |
| | | public String getCountryCode() { |
| | | return countryCode; |
| | | } |
| | | |
| | | public void setCountryCode(String countryCode) { |
| | | this.countryCode = countryCode; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据解密异常提供友好的错误信息 |
| | | */ |
| | | private String getDecryptFriendlyErrorMessage(Exception e) { |
| | | String errorMessage = e.getMessage(); |
| | | |
| | | if (e instanceof IllegalArgumentException) { |
| | | if (errorMessage.contains("Illegal base64 character")) { |
| | | return "授权数据格式错误,请重新获取手机号授权"; |
| | | } |
| | | } |
| | | |
| | | if (e instanceof javax.crypto.BadPaddingException) { |
| | | return "授权数据已过期或无效,请重新获取手机号授权"; |
| | | } |
| | | |
| | | if (e instanceof javax.crypto.IllegalBlockSizeException) { |
| | | return "授权数据长度错误,请重新获取手机号授权"; |
| | | } |
| | | |
| | | if (e instanceof java.security.InvalidKeyException) { |
| | | return "会话密钥无效,请重新登录后再试"; |
| | | } |
| | | |
| | | if (e instanceof com.fasterxml.jackson.core.JsonParseException) { |
| | | return "授权数据解析失败,请重新获取手机号授权"; |
| | | } |
| | | |
| | | if (errorMessage.contains("sessionKey")) { |
| | | return "会话已过期,请重新登录后再试"; |
| | | } |
| | | |
| | | if (errorMessage.contains("encryptedData")) { |
| | | return "授权数据无效,请重新获取手机号授权"; |
| | | } |
| | | |
| | | return "手机号解密失败,请重新获取手机号授权"; |
| | | } |
| | | } |