50 lines
2.1 KiB
Python
50 lines
2.1 KiB
Python
# requires: fastapi, pydantic
|
|
"""给 Dify / Coze 当“自定义工具”的后端接口:提供 OpenAPI 描述 + API Key 鉴权。
|
|
|
|
在 Dify 中:工具 → 自定义 → 创建自定义工具 → 填入 http://<你的地址>/openapi.json 导入,
|
|
鉴权方式选 API Key(请求头 Authorization: Bearer <key>)。具体界面以 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"])
|