feat: 修复订单查询和物流查询功能

主要修改:

1. 订单数据解析修复 (agent/agents/order.py)
   - 修复 Mall API 返回数据的嵌套结构解析
   - 更新字段映射:orderId→order_id, orderProduct→items, statusText→status_text
   - 支持多种商品图片字段:image, pic, thumb, productImg
   - 添加详细的调试日志

2. 物流查询修复 (mcp_servers/order_mcp/server.py)
   - 修复物流接口返回数据结构解析 (data[].trackingCode→tracking_number)
   - 添加 print() 日志用于调试
   - 支持多种字段名映射

3. Chatwoot 集成优化 (agent/integrations/chatwoot.py)
   - 添加 json 模块导入
   - 完善订单卡片和表单展示功能

4. API 请求头优化 (mcp_servers/shared/mall_client.py)
   - 更新 User-Agent 和 Accept 头
   - 修正 Origin 和 Referer 大小写

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
wangliang
2026-01-20 19:10:21 +08:00
parent 6b6172d8f0
commit e8e89601a5
5 changed files with 1098 additions and 73 deletions

View File

@@ -315,12 +315,10 @@ async def get_mall_order(
"""
import logging
logger = logging.getLogger(__name__)
logger.info(
"get_mall_order called",
order_id=order_id,
has_user_token=bool(user_token),
user_token_prefix=user_token[:20] if user_token else None
f"get_mall_order called: order_id={order_id}, has_user_token={bool(user_token)}, "
f"token_prefix={user_token[:20] if user_token else None}"
)
try:
@@ -347,9 +345,8 @@ async def get_mall_order(
result = await client.get_order_by_id(order_id)
logger.info(
"Mall API request successful",
order_id=order_id,
result_keys=list(result.keys()) if isinstance(result, dict) else None
f"Mall API request successful: order_id={order_id}, "
f"result_keys={list(result.keys()) if isinstance(result, dict) else None}"
)
return {
@@ -359,9 +356,7 @@ async def get_mall_order(
}
except Exception as e:
logger.error(
"Mall API request failed",
order_id=order_id,
error=str(e)
f"Mall API request failed: order_id={order_id}, error={str(e)}"
)
return {
"success": False,
@@ -395,18 +390,11 @@ async def get_logistics(
Returns:
物流信息,包含快递公司、状态、预计送达时间、物流轨迹等
"""
import logging
logger = logging.getLogger(__name__)
logger.info(
"get_logistics called",
order_id=order_id,
has_user_token=bool(user_token)
)
print(f"[get_logistics] Called with order_id={order_id}, has_user_token={bool(user_token)}")
# 必须提供 user_token
if not user_token:
logger.error("No user_token provided for logistics query")
print("[get_logistics] ERROR: No user_token provided")
return {
"success": False,
"error": "用户未登录,请先登录账户以查询物流信息",
@@ -424,32 +412,50 @@ async def get_logistics(
source=settings.mall_source
)
print(f"[get_logistics] Calling Mall API: /mall/api/order/parcel?orderId={order_id}")
result = await client.get(
"/mall/api/order/parcel",
params={"orderId": order_id}
)
logger.info(
"Logistics query successful",
order_id=order_id,
has_tracking=bool(result.get("trackingNumber"))
)
print(f"[get_logistics] SUCCESS: result_keys={list(result.keys()) if isinstance(result, dict) else type(result).__name__}")
print(f"[get_logistics] Sample data: {str(result)[:500]}")
return {
"success": True,
"order_id": order_id,
"tracking_number": result.get("trackingNumber"),
"courier": result.get("courier"),
"status": result.get("status"),
"estimated_delivery": result.get("estimatedDelivery"),
"timeline": result.get("timeline", [])
}
# Mall API 返回结构:{ "total": 1, "data": [{ "trackingCode": "...", "carrier": "...", ... }] }
logistics_list = result.get("data", [])
if logistics_list and len(logistics_list) > 0:
first_logistics = logistics_list[0]
tracking_number = first_logistics.get("trackingCode", "")
carrier = first_logistics.get("carrier", "未知")
print(f"[get_logistics] Extracted: tracking_number={tracking_number}, carrier={carrier}")
return {
"success": True,
"order_id": order_id,
"tracking_number": tracking_number,
"courier": carrier,
"tracking_url": first_logistics.get("trackingUrl", ""),
"status": first_logistics.get("status", ""),
"timeline": [] # 如果 API 返回轨迹信息,可以在这里添加
}
else:
print(f"[get_logistics] WARNING: No logistics data found in response")
return {
"success": True,
"order_id": order_id,
"tracking_number": "",
"courier": "暂无物流信息",
"status": "",
"timeline": []
}
except Exception as e:
logger.error(
"Logistics query failed",
order_id=order_id,
error=str(e)
)
import traceback
print(f"[get_logistics] ERROR: {type(e).__name__}: {str(e)}")
print(f"[get_logistics] TRACEBACK:\n{traceback.format_exc()}")
return {
"success": False,
"error": str(e),

View File

@@ -55,14 +55,16 @@ class MallClient:
headers={
"Authorization": f"Bearer {self.api_token}",
"Content-Type": "application/json",
"Accept": "application/json",
"Accept": "application/json, text/plain, */*",
"Device-Type": "pc",
"tenant-Id": self.tenant_id,
"currency-code": self.currency_code,
"language-id": self.language_id,
"source": self.source,
"origin": "https://www.qa1.gaia888.com",
"referer": "https://www.qa1.gaia888.com/",
"Origin": "https://www.qa1.gaia888.com",
"Referer": "https://www.qa1.gaia888.com/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
"DNT": "1",
},
timeout=30.0
)