package com.ruoyi.system.ControllerUtil; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.system.domain.Users; import com.ruoyi.system.service.IUsersService; import java.util.HashMap; import java.util.Map; import static com.ruoyi.common.core.domain.AjaxResult.error; import static com.ruoyi.common.core.domain.AjaxResult.success; /** * 小程序登录工具类 * * 提供微信小程序登录相关的工具方法 * 主要功能: * 1. 参数验证和提取 * 2. 微信openid获取 * 3. 用户手机号获取 * 4. 用户创建和更新 * 5. 登录响应构建 * * @author Mr. Zhang Pan * @date 2025-01-03 * @version 1.0 */ public class AppletLoginUtil { /** * 执行微信登录完整流程 * * @param params 登录参数 * @param usersService 用户服务 * @return 登录结果 */ public static AjaxResult executeWechatLogin(Map params, IUsersService usersService) { try { // 1. 参数验证 String jsCode = validateAndExtractParam(params, "usercode", "微信登录code不能为空"); String phoneCode = validateAndExtractParam(params, "code", "手机号授权code不能为空"); // 2. 获取微信openid String openid = getWechatOpenid(jsCode); if (openid == null) { return error("获取微信openid失败,请重试"); } // 3. 检查用户是否已存在 Users existingUser = usersService.selectUsersByOpenid(openid); if (existingUser != null) { existingUser.setRemember_token(existingUser.getRememberToken()); return buildSuccessResponse(existingUser, false); } // 4. 新用户处理:获取手机号并创建用户 String phoneNumber = getPhoneNumber(phoneCode); if (phoneNumber == null) { return error("获取手机号失败,请重新授权"); } // 5. 创建或更新用户 Users user = createOrUpdateUser(openid, phoneNumber, usersService); user.setRemember_token(user.getRememberToken()); return buildSuccessResponse(user, true); } catch (IllegalArgumentException e) { return error(e.getMessage()); } catch (Exception e) { System.err.println("微信登录异常:" + e.getMessage()); e.printStackTrace(); return error("微信登录失败,请稍后重试"); } } /** * 验证并提取请求参数 * * @param params 参数Map * @param key 参数键 * @param errorMessage 错误信息 * @return 参数值 * @throws IllegalArgumentException 参数无效时抛出 */ public static String validateAndExtractParam(Map params, String key, String errorMessage) { Object value = params.get(key); if (value == null || value.toString().trim().isEmpty()) { throw new IllegalArgumentException(errorMessage); } return value.toString().trim(); } /** * 获取微信openid * * @param jsCode 微信小程序登录code * @return openid或null */ public static String getWechatOpenid(String jsCode) { try { Map openidResult = WechatApiUtil.getWechatUserOpenidInfo(jsCode); if (!(Boolean) openidResult.get("success")) { System.err.println("获取openid失败:" + openidResult.get("errorMsg")); return null; } String openid = (String) openidResult.get("openid"); if (openid == null || openid.trim().isEmpty()) { System.err.println("微信API返回的openid为空"); return null; } System.out.println("成功获取微信openid:" + openid.substring(0, 8) + "..."); return openid; } catch (Exception e) { System.err.println("获取微信openid异常:" + e.getMessage()); return null; } } /** * 获取用户手机号 * * @param phoneCode 手机号授权code * @return 手机号或null */ public static String getPhoneNumber(String phoneCode) { try { Map phoneResult = WechatApiUtil.getPhoneNumberByCode(phoneCode); if (!(Boolean) phoneResult.get("success")) { System.err.println("获取手机号失败:" + phoneResult.get("errorMsg")); return null; } Map phoneInfo = (Map) phoneResult.get("phone_info"); if (phoneInfo == null) { System.err.println("微信API返回的手机号信息为空"); return null; } String phoneNumber = (String) phoneInfo.get("phoneNumber"); if (phoneNumber == null || phoneNumber.trim().isEmpty()) { System.err.println("微信API返回的手机号为空"); return null; } System.out.println("成功获取用户手机号:" + phoneNumber.substring(0, 3) + "****" + phoneNumber.substring(7)); return phoneNumber; } catch (Exception e) { System.err.println("获取用户手机号异常:" + e.getMessage()); return null; } } /** * 创建或更新用户 * * @param openid 微信openid * @param phoneNumber 手机号 * @param usersService 用户服务 * @return 用户对象 * @throws Exception 操作失败时抛出 */ public static Users createOrUpdateUser(String openid, String phoneNumber, IUsersService usersService) throws Exception { // 1. 生成用户token String token = WechatApiUtil.generateUserToken(openid); if (token == null || token.trim().isEmpty()) { throw new Exception("生成用户token失败"); } // 2. 检查手机号是否已存在 Users existingUserByPhone = usersService.selectUsersByPhone(phoneNumber); if (existingUserByPhone != null) { // 3. 更新已有用户的openid和token return updateExistingUser(existingUserByPhone, openid, token, usersService); } else { // 4. 创建新用户 return createNewUser(openid, phoneNumber, token, usersService); } } /** * 更新已有用户信息 * * @param user 已有用户 * @param openid 微信openid * @param token 新token * @param usersService 用户服务 * @return 更新后的用户 * @throws Exception 更新失败时抛出 */ public static Users updateExistingUser(Users user, String openid, String token, IUsersService usersService) throws Exception { try { user.setOpenid(openid); user.setRememberToken(token); int updateResult = usersService.updateUsers(user); if (updateResult <= 0) { throw new Exception("更新用户信息失败"); } System.out.println("成功更新用户信息,用户ID:" + user.getId()); return user; } catch (Exception e) { System.err.println("更新用户信息异常:" + e.getMessage()); throw new Exception("更新用户信息失败:" + e.getMessage()); } } /** * 创建新用户 * * @param openid 微信openid * @param phoneNumber 手机号 * @param token 用户token * @param usersService 用户服务 * @return 新创建的用户 * @throws Exception 创建失败时抛出 */ public static Users createNewUser(String openid, String phoneNumber, String token, IUsersService usersService) throws Exception { try { Users newUser = new Users(); newUser.setPhone(phoneNumber); newUser.setRememberToken(token); newUser.setName("微信用户"); newUser.setOpenid(openid); newUser.setAvatar("/default/user_avatar.jpeg"); newUser.setType("1"); newUser.setStatus(1); newUser.setIsWork(0); int insertResult = usersService.insertUsers(newUser); if (insertResult <= 0) { throw new Exception("创建用户记录失败"); } System.out.println("成功创建新用户,手机号:" + phoneNumber.substring(0, 3) + "****" + phoneNumber.substring(7)); return newUser; } catch (Exception e) { System.err.println("创建新用户异常:" + e.getMessage()); throw new Exception("创建用户失败:" + e.getMessage()); } } /** * 构建成功响应 * * @param user 用户对象 * @param isNewUser 是否为新用户 * @return 响应结果 */ public static AjaxResult buildSuccessResponse(Users user, boolean isNewUser) { try { // 设置返回字段 user.setRemember_token(user.getRememberToken()); // 构建响应数据 Map responseData = new HashMap<>(); responseData.put("user", user); responseData.put("isNewUser", isNewUser); responseData.put("loginTime", System.currentTimeMillis()); responseData.put("message", isNewUser ? "注册成功" : "登录成功"); System.out.println((isNewUser ? "用户注册成功" : "用户登录成功") + ",用户ID:" + user.getId()); return success(responseData); } catch (Exception e) { System.err.println("构建响应数据异常:" + e.getMessage()); return error("登录成功但返回数据异常"); } } /** * 验证用户token并获取用户信息 * * @param token 用户token * @param usersService 用户服务 * @return 验证结果 */ public static Map validateUserToken(String token, IUsersService usersService) { Map result = new HashMap<>(); try { if (token == null || token.trim().isEmpty()) { result.put("valid", false); result.put("message", "token不能为空"); return result; } // 验证token格式 if (!WechatApiUtil.isValidTokenFormat(token.trim())) { result.put("valid", false); result.put("message", "token格式无效"); return result; } // 查询用户信息 Users user = usersService.selectUsersByRememberToken(token.trim()); if (user == null) { result.put("valid", false); result.put("message", "token无效或用户不存在"); return result; } // 检查用户状态 if (user.getStatus() == null || user.getStatus() != 1) { result.put("valid", false); result.put("message", "用户账号已被禁用"); return result; } // 设置返回字段并过滤敏感信息 user.setRemember_token(user.getRememberToken()); result.put("valid", true); result.put("user", user); result.put("message", "token验证成功"); } catch (Exception e) { result.put("valid", false); result.put("message", "token验证异常:" + e.getMessage()); System.err.println("验证用户token异常:" + e.getMessage()); } return result; } /** * 获取并验证请求头中的token * * @param authHeader Authorization请求头 * @param tokenHeader token请求头 * @return 提取的token或null */ public static String extractToken(String authHeader, String tokenHeader) { String token = tokenHeader; // 如果token头为空,尝试从Authorization头获取 if (token == null || token.trim().isEmpty()) { if (authHeader != null && authHeader.startsWith("Bearer ")) { token = authHeader.substring(7); } } return (token != null && !token.trim().isEmpty()) ? token.trim() : null; } /** * 构建登录失败响应 * * @param message 失败信息 * @return 失败响应 */ public static AjaxResult buildFailureResponse(String message) { return error("登录失败:" + message); } /** * 构建参数错误响应 * * @param paramName 参数名 * @return 错误响应 */ public static AjaxResult buildParamErrorResponse(String paramName) { return error("参数错误:" + paramName + " 不能为空或格式不正确"); } }