feat: 添加物流查询功能和完善 token 传递

- 添加 get_logistics 工具查询 Mall API /mall/api/order/parcel
- 修复 Cookie token 传递到 MCP 的问题
- 增强 LLM 客户端超时处理和日志
- 移除 MALL_API_TOKEN,使用用户登录 token
- 更新测试页面使用 setUser 设置用户属性
- 增强 webhook 调试日志
This commit is contained in:
wangliang
2026-01-16 18:36:17 +08:00
parent cd787d608b
commit c4e97cf312
9 changed files with 334 additions and 111 deletions

View File

@@ -313,37 +313,150 @@ async def get_mall_order(
订单详情,包含订单号、状态、商品信息、金额、物流信息等
Order details including order ID, status, items, amount, logistics info, etc.
"""
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
)
try:
# 如果提供 user_token使用用户自己的 token
if user_token:
client = MallClient(
api_url=settings.mall_api_url,
api_token=user_token,
tenant_id=settings.mall_tenant_id,
currency_code=settings.mall_currency_code,
language_id=settings.mall_language_id,
source=settings.mall_source
)
else:
# 否则使用默认的 mall 实例
client = mall
# 必须提供 user_token
if not user_token:
logger.error("No user_token provided, user must be logged in")
return {
"success": False,
"error": "用户未登录,请先登录账户以查询订单信息",
"order_id": order_id,
"require_login": True
}
logger.info("Using user token for Mall API request")
client = MallClient(
api_url=settings.mall_api_url,
api_token=user_token,
tenant_id=settings.mall_tenant_id,
currency_code=settings.mall_currency_code,
language_id=settings.mall_language_id,
source=settings.mall_source
)
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
)
return {
"success": True,
"order": result,
"order_id": order_id
}
except Exception as e:
logger.error(
"Mall API request failed",
order_id=order_id,
error=str(e)
)
return {
"success": False,
"error": str(e),
"order_id": order_id
}
finally:
# 如果创建了临时客户端,关闭它
if user_token:
# 关闭客户端
if 'client' in dir() and client:
await client.close()
@register_tool("get_logistics")
@mcp.tool()
async def get_logistics(
order_id: str,
user_token: str = None,
user_id: str = None,
account_id: str = None
) -> dict:
"""Query logistics tracking information from Mall API
从 Mall API 查询订单物流信息
Args:
order_id: 订单号 (e.g., "201941967")
user_token: 用户 JWT token必需用于身份验证
user_id: 用户 ID自动注入此工具不使用
account_id: 账户 ID自动注入此工具不使用
Returns:
物流信息,包含快递公司、状态、预计送达时间、物流轨迹等
"""
import logging
logger = logging.getLogger(__name__)
logger.info(
"get_logistics called",
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")
return {
"success": False,
"error": "用户未登录,请先登录账户以查询物流信息",
"order_id": order_id,
"require_login": True
}
try:
client = MallClient(
api_url=settings.mall_api_url,
api_token=user_token,
tenant_id=settings.mall_tenant_id,
currency_code=settings.mall_currency_code,
language_id=settings.mall_language_id,
source=settings.mall_source
)
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"))
)
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", [])
}
except Exception as e:
logger.error(
"Logistics query failed",
order_id=order_id,
error=str(e)
)
return {
"success": False,
"error": str(e),
"order_id": order_id
}
finally:
if 'client' in dir() and client:
await client.close()

View File

@@ -61,6 +61,8 @@ class MallClient:
"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/",
},
timeout=30.0
)