diff --git a/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java b/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java index 5385230..4fd5e1c 100644 --- a/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java +++ b/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java @@ -126,11 +126,16 @@ public class QrLoginServiceImpl implements QrLoginService { * @return 小程序码图片Base64字符串 */ private String generateMiniprogramQrCode(String token, Integer tenantId) { + // 构建 access_token 的 Redis key(与 WxService 保持一致) + String accessTokenKey = "WX_ACCESS_TOKEN:" + (tenantId != null ? tenantId : 10048); + try { // 获取小程序access_token String accessToken = wxService.getAccessToken(tenantId); if (StrUtil.isBlank(accessToken)) { - log.warn("获取小程序access_token失败,跳过生成小程序码"); + log.warn("获取小程序access_token失败,跳过生成小程序码,将清理缓存"); + // 获取失败时清理缓存,下次会重新获取 + clearAccessTokenCache(accessTokenKey, tenantId); return null; } @@ -166,7 +171,18 @@ public class QrLoginServiceImpl implements QrLoginService { // 检查是否返回JSON错误(微信API错误时会返回JSON) if (imageBytes.length < 100 && new String(imageBytes).startsWith("{")) { JSONObject errorResult = JSON.parseObject(new String(imageBytes)); - log.error("生成小程序码API返回错误: {}", errorResult); + Integer errCode = errorResult.getInteger("errcode"); + String errMsg = errorResult.getString("errmsg"); + + // 判断是否是 token 相关错误,需要清理缓存 + boolean shouldClearCache = isTokenRelatedError(errCode, errMsg); + + if (shouldClearCache) { + log.error("生成小程序码API返回token相关错误[{}:{}],将清理缓存", errCode, errMsg); + clearAccessTokenCache(accessTokenKey, tenantId); + } else { + log.error("生成小程序码API返回错误[{}:{}],不清理缓存", errCode, errMsg); + } return null; } @@ -176,10 +192,55 @@ public class QrLoginServiceImpl implements QrLoginService { return "data:image/png;base64," + base64Image; } catch (Exception e) { log.error("生成小程序码异常: {}", e.getMessage(), e); + // 异常时也清理缓存,以防是 token 问题 + clearAccessTokenCache(accessTokenKey, tenantId); return null; } } + /** + * 判断是否是 token 相关的错误码,需要清理缓存 + * 常见微信 API 错误码: + * - 40001: 获取access_token时AppSecret错误 + * - 40013: appid无效 + * - 40125: appsecret无效 + * - 42001: access_token超时 + * - 42002: refresh_token超时 + * - 42003: code超时 + * - 44002: post body太长 + * - 44003: 图片太大 + * - 41002: appid不正确 + * - 41008: 缺少access_token参数 + */ + private boolean isTokenRelatedError(Integer errCode, String errMsg) { + if (errCode == null) { + return false; + } + // token 相关错误码 + return errCode == 40001 // AppSecret错误 + || errCode == 40013 // appid无效 + || errCode == 40125 // appsecret无效 + || errCode == 42001 // access_token超时 + || errCode == 42002 // refresh_token超时 + || errCode == 42003 // code超时 + || errCode == 41002 // appid不正确 + || errCode == 41008 // 缺少access_token参数 + || errCode == 40014 // 不合法的access_token + || errCode == 40097; // invalid page + } + + /** + * 清理 access_token 缓存 + */ + private void clearAccessTokenCache(String accessTokenKey, Integer tenantId) { + try { + redisUtil.delete(accessTokenKey); + log.info("清理微信access_token缓存[{}], tenantId={}", accessTokenKey, tenantId); + } catch (Exception e) { + log.error("清理access_token缓存失败: {}", e.getMessage()); + } + } + @Override public QrLoginStatusResponse checkQrLoginStatus(String token) { if (StrUtil.isBlank(token)) {