# requires: fastapi, pydantic """给 Dify / Coze 当“自定义工具”的后端接口:提供 OpenAPI 描述 + API Key 鉴权。 在 Dify 中:工具 → 自定义 → 创建自定义工具 → 填入 http://<你的地址>/openapi.json 导入, 鉴权方式选 API Key(请求头 Authorization: Bearer )。具体界面以 Dify 官方文档为准。 本地运行:uvicorn app:app --port 8100(直接 python app.py 只做导入检查) """ from __future__ import annotations import os import secrets from fastapi import Depends, FastAPI, HTTPException from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from pydantic import BaseModel, Field API_KEY = os.environ.get("TOOL_API_KEY", "dev-only-key") # 生产环境从密钥管理读取 app = FastAPI( title="订单查询工具", version="1.0.0", description="供低代码平台调用的订单查询接口。只读,按调用方的店铺隔离数据。", servers=[{"url": "http://127.0.0.1:8100"}], # Dify 导入时需要 servers 字段,部署后改成实际地址 ) bearer = HTTPBearer() ORDERS = {"A1001": {"shop": "s1", "status": "已发货", "eta": "明天"}, "A1002": {"shop": "s2", "status": "待支付", "eta": None}} def auth(cred: HTTPAuthorizationCredentials = Depends(bearer)) -> str: if not secrets.compare_digest(cred.credentials, API_KEY): raise HTTPException(401, "无效的 API Key") return "s1" # 示例:一个 Key 对应一个店铺;真实项目查表 class OrderStatus(BaseModel): order_id: str status: str = Field(description="订单状态") eta: str | None = Field(default=None, description="预计送达时间") @app.get("/orders/{order_id}", operation_id="getOrderStatus", response_model=OrderStatus, summary="查询订单状态", description="根据订单号查询订单状态和预计送达时间。订单号形如 A1001。") def get_order_status(order_id: str, shop: str = Depends(auth)) -> OrderStatus: o = ORDERS.get(order_id) if not o or o["shop"] != shop: raise HTTPException(404, "订单不存在") return OrderStatus(order_id=order_id, status=o["status"], eta=o["eta"])