From 54a840dea26e0fc6fd3d8bc57575278e96d6a0a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Thu, 4 Sep 2025 10:22:08 +0800 Subject: [PATCH] =?UTF-8?q?fix(system):=20=E4=BC=98=E5=8C=96=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E7=99=BB=E5=BD=95=E6=8E=A5=E5=8F=A3=E7=9A=84=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E5=A4=84=E7=90=86=E5=92=8C=E5=BC=82=E5=B8=B8=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 改进了微信手机号和 access_token 获取接口的响应清理逻辑 - 增加了对响应格式的验证和错误处理 -优化了缓存 access_token 的存储和解析 - 提升了代码的健壮性和错误提示的详细性 --- .../system/controller/WxLoginController.java | 112 ++++++++++++++---- 1 file changed, 91 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java index 35a7a42..32c3a3a 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java @@ -292,12 +292,34 @@ public class WxLoginController extends BaseController { throw new BusinessException("微信接口响应为空"); } - // 清理响应中的控制字符 - String cleanResponse = post.trim().replaceAll("[\u0000-\u001f]", ""); - System.out.println("微信获取手机号响应: " + cleanResponse); + // 更全面地清理响应中的特殊字符 + String cleanResponse = post.trim() + .replaceAll("[\u0000-\u001f\u007f-\u009f]", "") // 清理控制字符 + .replaceAll("\\p{Cntrl}", "") // 清理所有控制字符 + .replaceAll("[\\x00-\\x1f\\x7f]", ""); // 清理ASCII控制字符 - JSONObject json = JSON.parseObject(cleanResponse); - if (json.get("errcode").equals(0)) { + System.out.println("微信获取手机号原始响应: " + post); + System.out.println("微信获取手机号清理后响应: " + cleanResponse); + + // 验证清理后的响应是否为有效JSON + if (!cleanResponse.startsWith("{") || !cleanResponse.endsWith("}")) { + System.err.println("响应不是有效的JSON格式: " + cleanResponse); + throw new BusinessException("微信接口响应格式异常"); + } + + JSONObject json; + try { + json = JSON.parseObject(cleanResponse); + } catch (Exception parseException) { + System.err.println("JSON解析失败: " + parseException.getMessage()); + System.err.println("原始响应: " + post); + System.err.println("清理后响应: " + cleanResponse); + throw new BusinessException("微信接口响应解析失败"); + } + + // 检查微信接口是否返回错误 + Object errcode = json.get("errcode"); + if (errcode != null && errcode.equals(0)) { JSONObject phoneInfo = JSON.parseObject(json.getString("phone_info")); // 微信用户的手机号码 final String phoneNumber = phoneInfo.getString("phoneNumber"); @@ -310,13 +332,16 @@ public class WxLoginController extends BaseController { return phoneNumber; } else { String errorMsg = json.getString("errmsg"); - System.err.println("微信获取手机号失败: errcode=" + json.get("errcode") + ", errmsg=" + errorMsg); + System.err.println("微信获取手机号失败: errcode=" + errcode + ", errmsg=" + errorMsg); throw new BusinessException("获取手机号失败:" + errorMsg); } + } catch (BusinessException be) { + // 重新抛出业务异常 + throw be; } catch (Exception e) { System.err.println("获取微信手机号异常: " + e.getMessage()); e.printStackTrace(); - throw new BusinessException("获取手机号失败,请重试"); + throw new BusinessException("获取手机号失败,请重试: " + e.getMessage()); } } @@ -346,17 +371,30 @@ public class WxLoginController extends BaseController { // 从缓存获取access_token String value = redisTemplate.opsForValue().get(key); if (value != null) { - // 解析access_token - JSONObject response = JSON.parseObject(value); -// return response.getString("access_token"); + try { + // 解析access_token + JSONObject response = JSON.parseObject(value); + String accessToken = response.getString("access_token"); + if (StrUtil.isNotBlank(accessToken)) { + System.out.println("从缓存获取access_token: " + accessToken); + return accessToken; + } + } catch (Exception e) { + System.err.println("解析缓存的access_token失败: " + e.getMessage()); + // 缓存数据异常,删除缓存,重新获取 + redisTemplate.delete(key); + } } // 微信获取凭证接口 String apiUrl = "https://api.weixin.qq.com/cgi-bin/token"; // 组装url参数 String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(setting.getString("appId")).concat("&secret=").concat(setting.getString("appSecret")); + + System.out.println("请求微信access_token接口: " + url); + // 执行get请求 String result = HttpUtil.get(url); - System.out.println("result = " + result); + System.out.println("微信access_token原始响应: " + result); try { // 验证响应内容 @@ -364,24 +402,56 @@ public class WxLoginController extends BaseController { throw new BusinessException("微信接口响应为空"); } - // 清理响应中的控制字符 - String cleanResult = result.trim().replaceAll("[\u0000-\u001f]", ""); + // 更全面地清理响应中的特殊字符 + String cleanResult = result.trim() + .replaceAll("[\u0000-\u001f\u007f-\u009f]", "") // 清理控制字符 + .replaceAll("\\p{Cntrl}", "") // 清理所有控制字符 + .replaceAll("[\\x00-\\x1f\\x7f]", ""); // 清理ASCII控制字符 + + System.out.println("微信access_token清理后响应: " + cleanResult); + + // 验证清理后的响应是否为有效JSON + if (!cleanResult.startsWith("{") || !cleanResult.endsWith("}")) { + System.err.println("响应不是有效的JSON格式: " + cleanResult); + throw new BusinessException("微信接口响应格式异常"); + } // 解析access_token - JSONObject response = JSON.parseObject(cleanResult); - if (response.getString("access_token") != null) { - // 存入缓存 - redisTemplate.opsForValue().set(key, cleanResult, 7000L, TimeUnit.SECONDS); - return response.getString("access_token"); - } else { + JSONObject response; + try { + response = JSON.parseObject(cleanResult); + } catch (Exception parseException) { + System.err.println("JSON解析失败: " + parseException.getMessage()); + System.err.println("原始响应: " + result); + System.err.println("清理后响应: " + cleanResult); + throw new BusinessException("微信接口响应解析失败"); + } + + // 检查是否有错误码 + Object errcode = response.get("errcode"); + if (errcode != null && !errcode.equals(0)) { String errorMsg = response.getString("errmsg"); - System.err.println("获取access_token失败: " + errorMsg); + System.err.println("获取access_token失败: errcode=" + errcode + ", errmsg=" + errorMsg); throw new BusinessException("获取access_token失败:" + errorMsg); } + + String accessToken = response.getString("access_token"); + if (StrUtil.isNotBlank(accessToken)) { + // 存入缓存,设置过期时间为7000秒(约2小时,微信access_token有效期为2小时) + redisTemplate.opsForValue().set(key, cleanResult, 7000L, TimeUnit.SECONDS); + System.out.println("获取新的access_token成功: " + accessToken); + return accessToken; + } else { + System.err.println("响应中没有access_token字段: " + cleanResult); + throw new BusinessException("获取access_token失败:响应格式异常"); + } + } catch (BusinessException be) { + // 重新抛出业务异常 + throw be; } catch (Exception e) { System.err.println("解析access_token异常: " + e.getMessage()); e.printStackTrace(); - throw new BusinessException("小程序配置不正确或网络异常"); + throw new BusinessException("小程序配置不正确或网络异常: " + e.getMessage()); } }