From 917c772b592eededfe20b165f66ae2deda82818f Mon Sep 17 00:00:00 2001 From: "[yxf]" <[1524240689@qq.com]> Date: Tue, 19 May 2026 17:17:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=A5=E5=BF=97=E6=89=93?= =?UTF-8?q?=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../im/controller/TikTokAuthController.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/TikTokAuthController.java b/im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/TikTokAuthController.java index a9c9a97..98dbb9f 100644 --- a/im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/TikTokAuthController.java +++ b/im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/TikTokAuthController.java @@ -31,32 +31,50 @@ public class TikTokAuthController { String state = generateState(); stateStore.put(state, System.currentTimeMillis()); String authUrl = authService.buildAuthUrl(state); - // 生产环境建议 302 跳转: - // return "redirect:" + authUrl; + log.info("生成授权链接: {}", authUrl); return "请访问以下链接完成授权:\n" + authUrl; } @SaIgnore @GetMapping("/callback") - public String callback( - @RequestParam(value = "code", required = false) String code, - @RequestParam(value = "state", required = false) String state, - @RequestParam(value = "error", required = false) String error) { + public String callback(@RequestParam Map params) { + + // ★ 第一步:打印全部参数,不再盲目判断 + log.info("===== TikTok 回调全部参数: {} =====", params); + + String code = params.get("code"); + String state = params.get("state"); + String error = params.get("error"); + String shopRegion = params.get("shop_region"); // 1. 用户拒绝 - if ("auth_denied".equals(error) || code == null || "null".equals(code)) { + if ("auth_denied".equals(error)) { + log.warn("用户拒绝授权, error={}", error); return "用户拒绝了授权"; } - // 2. state 校验 - if (state == null || !stateStore.containsKey(state)) { - return "state 校验失败,可能存在 CSRF 攻击"; + // 2. code 为空或字符串 "null" + if (code == null || "null".equals(code)) { + log.warn("code 无效: code=[{}]", code); + return "授权失败:未收到有效的授权码"; + } + + // 3. state 校验(TikTok Shop 回调不一定带 state,放宽处理) + if (state != null) { + if (!stateStore.containsKey(state)) { + log.warn("state 校验失败: state={}", state); + return "state 校验失败"; + } + stateStore.remove(state); + log.info("state 校验通过: {}", state); + } else { + log.info("TikTok 未返回 state,跳过 state 校验"); } - stateStore.remove(state); - // 3. 用 code 换 token - log.info("收到授权回调, code={}, state={}", code, state); + // 4. 用 code 换 token + log.info("开始用 code 换取 token, code={}, shop_region={}", code, shopRegion); TikTokTokenResponse tokenResp = authService.getAccessToken(code); + log.info("Token 接口响应: code={}, message={}", tokenResp.getCode(), tokenResp.getMessage()); if (tokenResp.getCode() != 0) { return "获取 Token 失败:" + tokenResp.getMessage(); @@ -64,8 +82,8 @@ public class TikTokAuthController { TikTokTokenResponse.TokenData data = tokenResp.getData(); - // 4. ⚠️ 生产环境应将 data 存入数据库/Redis,而非直接返回 return "授权成功!\n" + + "shop_region: " + shopRegion + "\n" + "卖家名称: " + data.getSellerName() + "\n" + "地区: " + data.getSellerBaseRegion() + "\n" + "open_id: " + data.getOpenId() + "\n"