From 1116bddbc24cc052d3981e6c26c82ff727f8adac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8D=92?= Date: Wed, 5 Nov 2025 15:42:44 +0800 Subject: [PATCH] 1 --- .../controller/jarvis/JDOrderController.java | 96 +++++++++++++++++++ .../jarvis/TencentDocController.java | 30 +++++- .../service/impl/TencentDocServiceImpl.java | 8 +- 3 files changed, 131 insertions(+), 3 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/JDOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/JDOrderController.java index 4368229..8ec7963 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/JDOrderController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/JDOrderController.java @@ -671,4 +671,100 @@ public class JDOrderController extends BaseController { return AjaxResult.error("文本URL替换失败: " + e.getMessage()); } } + + /** + * 手动获取物流信息(用于调试) + * 如果订单的分销标识是F或PDD,调用外部接口获取物流信息并记录 + * 入参:{ orderId: 订单ID } + * 返回:接口返回的数据和记录状态 + */ + @PostMapping("/fetchLogisticsManually") + public AjaxResult fetchLogisticsManually(@RequestBody Map body) { + try { + Long orderId = null; + if (body.get("orderId") != null) { + if (body.get("orderId") instanceof Number) { + orderId = ((Number) body.get("orderId")).longValue(); + } else { + orderId = Long.parseLong(body.get("orderId").toString()); + } + } + + if (orderId == null) { + return AjaxResult.error("订单ID不能为空"); + } + + // 查询订单信息 + JDOrder order = jdOrderService.selectJDOrderById(orderId); + if (order == null) { + return AjaxResult.error("订单不存在"); + } + + // 检查分销标识 + String distributionMark = order.getDistributionMark(); + if (distributionMark == null || (!distributionMark.equals("F") && !distributionMark.equals("PDD"))) { + return AjaxResult.error("该订单的分销标识不是F或PDD,无需处理。当前分销标识: " + distributionMark); + } + + // 检查物流链接 + String logisticsLink = order.getLogisticsLink(); + if (logisticsLink == null || logisticsLink.trim().isEmpty()) { + return AjaxResult.error("该订单暂无物流链接"); + } + + logger.info("手动获取物流信息 - 订单ID: {}, 订单号: {}, 分销标识: {}, 物流链接: {}", + orderId, order.getOrderId(), distributionMark, logisticsLink); + + // 调用外部接口 + String externalUrl = "http://192.168.8.88:5001/fetch_logistics?tracking_url=" + + java.net.URLEncoder.encode(logisticsLink, "UTF-8"); + + logger.info("调用外部接口 - URL: {}", externalUrl); + + String result = ""; + try { + result = HttpUtils.sendGet(externalUrl); + logger.info("外部接口返回 - 订单ID: {}, 订单号: {}, 返回数据: {}", + orderId, order.getOrderId(), result); + } catch (Exception e) { + logger.error("调用外部接口失败 - 订单ID: {}, 订单号: {}, 错误: {}", + orderId, order.getOrderId(), e.getMessage(), e); + return AjaxResult.error("调用外部接口失败: " + e.getMessage()); + } + + // 记录返回数据到日志文件(方便debug) + logger.info("========== 物流信息获取记录 =========="); + logger.info("订单ID: {}", orderId); + logger.info("订单号: {}", order.getOrderId()); + logger.info("分销标识: {}", distributionMark); + logger.info("物流链接: {}", logisticsLink); + logger.info("请求URL: {}", externalUrl); + logger.info("返回数据: {}", result); + logger.info("====================================="); + + // 解析返回结果 + JSONObject responseData = new JSONObject(); + responseData.put("orderId", orderId); + responseData.put("orderNo", order.getOrderId()); + responseData.put("distributionMark", distributionMark); + responseData.put("logisticsLink", logisticsLink); + responseData.put("requestUrl", externalUrl); + + try { + // 尝试解析为JSON + Object parsed = JSON.parse(result); + responseData.put("responseData", parsed); + responseData.put("responseRaw", result); + } catch (Exception e) { + // 如果不是JSON,直接保存原始字符串 + responseData.put("responseRaw", result); + logger.warn("返回数据不是有效的JSON格式: {}", result); + } + + return AjaxResult.success(responseData); + } catch (Exception e) { + logger.error("手动获取物流信息异常", e); + return AjaxResult.error("获取物流信息失败: " + e.getMessage()); + } + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java index 729286f..ac42530 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java @@ -56,11 +56,39 @@ public class TencentDocController extends BaseController { /** * OAuth回调 - 通过授权码获取访问令牌 + * 根据腾讯文档官方文档:https://docs.qq.com/open/document/app/oauth2/authorize.html + * 用户授权成功后,腾讯文档会重定向到此回调地址,并携带code和state参数 */ @GetMapping("/oauth/callback") - public AjaxResult oauthCallback(@RequestParam("code") String code) { + public AjaxResult oauthCallback(@RequestParam("code") String code, + @RequestParam(value = "state", required = false) String state, + @RequestParam(value = "error", required = false) String error, + @RequestParam(value = "error_description", required = false) String errorDescription) { try { + // 处理授权错误 + if (error != null) { + log.error("腾讯文档授权失败 - error: {}, error_description: {}", error, errorDescription); + return AjaxResult.error("授权失败: " + (errorDescription != null ? errorDescription : error)); + } + + // 验证授权码 + if (code == null || code.trim().isEmpty()) { + return AjaxResult.error("授权码不能为空"); + } + + log.info("收到腾讯文档授权回调 - code: {}, state: {}", code, state); + + // 使用授权码换取access_token JSONObject tokenInfo = tencentDocService.getAccessTokenByCode(code); + + // 验证返回的token信息 + if (tokenInfo == null || !tokenInfo.containsKey("access_token")) { + log.error("获取访问令牌失败 - 响应数据: {}", tokenInfo); + return AjaxResult.error("获取访问令牌失败,响应数据格式不正确"); + } + + log.info("成功获取访问令牌 - access_token: {}", tokenInfo.getString("access_token")); + return AjaxResult.success("授权成功", tokenInfo); } catch (Exception e) { log.error("OAuth回调处理失败", e); diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocServiceImpl.java index 4983517..b8dfbbe 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocServiceImpl.java @@ -33,7 +33,7 @@ public class TencentDocServiceImpl implements ITencentDocService { String redirectUri = tencentDocConfig.getRedirectUri(); String oauthUrl = tencentDocConfig.getOauthUrl(); - // 构建授权URL + // 构建授权URL(根据腾讯文档官方文档:https://docs.qq.com/open/document/app/oauth2/authorize.html) StringBuilder authUrl = new StringBuilder(); authUrl.append(oauthUrl); authUrl.append("?client_id=").append(appId); @@ -44,7 +44,11 @@ public class TencentDocServiceImpl implements ITencentDocService { authUrl.append("&redirect_uri=").append(redirectUri); } authUrl.append("&response_type=code"); - authUrl.append("&scope=file.read_write"); + authUrl.append("&scope=all"); // 根据官方文档,scope固定为all + + // 添加state参数(用于防CSRF攻击,可选但建议带上) + String state = java.util.UUID.randomUUID().toString(); + authUrl.append("&state=").append(state); return authUrl.toString(); }