feat: 初始化Webhook中继系统项目
- 添加FastAPI应用基础结构,包括主入口、路由和模型定义
- 实现Webhook接收端点(/webhook/{namespace})和健康检查(/health)
- 添加管理后台路由和模板,支持端点、目标、渠道和模板管理
- 包含SQLite数据库模型定义和初始化逻辑
- 添加日志记录和统计服务
- 包含Dockerfile和配置示例文件
- 添加项目文档,包括设计、流程图和验收标准
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# 验收记录
|
||||
|
||||
## 用例1:示例JSON
|
||||
- 步骤:POST /webhook/opps-webhook,负载为示例
|
||||
- 期望:
|
||||
- 路由至 target_3
|
||||
- 生成文本包含商户名、支付方式、金额、状态与日期,例如:`【某商户】支付宝 收款 5.50 元,状态:成功,日期:20251220`
|
||||
- 飞书与企业微信推送成功
|
||||
|
||||
## 用例2:remark未匹配
|
||||
- 步骤:remark为未知值
|
||||
- 期望:使用 default_targets 或仅通知
|
||||
|
||||
## 用例3:退款事件
|
||||
- 步骤:事件为 `refund.standard`
|
||||
- 期望:从 `actual_ref_amt` 或 `ref_amt/settlement_amt` 渲染文本
|
||||
|
||||
## 用例4:目标不可达
|
||||
- 步骤:模拟目标URL不可达
|
||||
- 期望:记录失败并按策略重试
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# 任务名称
|
||||
|
||||
Webhook中继与通知系统(Docker化)
|
||||
|
||||
## 背景与目标
|
||||
- 统一接收外部Webhook,按规则路由到目标端点,并生成通知消息推送至飞书/企业微信。
|
||||
- 基于配置可扩展,支持新增目标、remark映射与事件模板。
|
||||
|
||||
## 业务范围
|
||||
- 接收JSON负载,至少包含 `remark`、`event_define_no`、`trans_amt`、`trans_order_info.cash_resp_desc`、可选 `actual_ref_amt`。
|
||||
- 路由策略:按 `remark` 映射至一个或多个目标Webhook;若无匹配使用 `default_targets`。
|
||||
- 通知策略:按 `event_define_no` 模板生成文本,支持多渠道并发推送。
|
||||
|
||||
## 技术范围
|
||||
- Python 3.12、FastAPI、httpx
|
||||
- Docker 容器化;SQLite 持久化,模型定义见 `app/db.py`
|
||||
- 管理后台 `/admin` 维护端点、规则、动作、模板与通知渠道
|
||||
- 结构化日志;失败重试(在转发逻辑中可扩展);请求与分发记录持久化
|
||||
|
||||
## 输入与输出
|
||||
- 输入:`POST /webhook/{namespace}` JSON
|
||||
- 输出:200 返回路由与通知结果结构
|
||||
|
||||
## 验收标准
|
||||
- 能正确解析示例 JSON 并生成消息,包含商户名、支付方式、金额、状态与日期,例如:`【某商户】支付宝 收款 5.50 元,状态:成功,日期:20251220`
|
||||
- `remark=imcgcd03` 时转发至配置第3个目标;`remark=imcgcd02` 时至第2个目标
|
||||
- 同时推送至飞书与企业微信(若配置存在多个机器人则全部发送)
|
||||
- 失败记录与重试可配置(次数与退避)
|
||||
|
||||
## 部署与运行方式(概要)
|
||||
- 运行模式:
|
||||
- 作为独立 FastAPI 服务运行,暴露 `POST /webhook/{namespace}` 与 `/admin` 管理界面
|
||||
- 通过 Docker 镜像部署到服务器
|
||||
- 最低运行环境:
|
||||
- Python 3.12 或兼容的 Docker 运行时
|
||||
- 对外开放的 HTTP 端口(默认 8080)
|
||||
- 配置与数据:
|
||||
- 数据库:默认 `sqlite:///./config/data.db`,可通过环境变量 `DB_PATH` 调整
|
||||
- 规则、模板、渠道均通过 Web 管理后台写入数据库,无需修改代码或 YAML
|
||||
|
||||
## 边界与不做事项
|
||||
- 不实现目标端点的认证协议,默认匿名POST;可通过配置扩展签名
|
||||
- 不提供长期持久幂等存储,默认进程内短期去重
|
||||
|
||||
## 风险与约束
|
||||
- 目标Webhook不可达导致延迟;通过重试与超时保护
|
||||
- 通知渠道限流;并发可控与错误日志
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 共识与决策
|
||||
|
||||
## 技术选型
|
||||
- 语言与框架:Python + FastAPI
|
||||
- 网络库:httpx
|
||||
- 配置:YAML(PyYAML),环境变量 `WEBHOOK_CONFIG_PATH`
|
||||
- 重试:简单指数退避
|
||||
- 容器:python:3.12-slim,入口 `uvicorn app.main:app --host 0.0.0.0 --port 8080`
|
||||
|
||||
## 接口规范
|
||||
- `POST /webhook/{namespace}` 接收上游负载;`GET /health` 健康检查
|
||||
|
||||
## 配置规范
|
||||
- `targets`:目标Webhook注册表
|
||||
- `routing.remark_map`:remark到target名称列表映射
|
||||
- `notifications.event_map`:事件模板与渠道列表
|
||||
- `channels`:各渠道机器人Webhook列表
|
||||
|
||||
## 路由与通知规则
|
||||
- 路由按 `remark` 精确匹配,多目标并发转发
|
||||
- 通知按 `event_define_no` 模板渲染,支持多渠道并发推送
|
||||
|
||||
## 验收口径
|
||||
- 示例JSON生成消息与路由正确;返回结构包含每个目标与渠道的状态
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 架构设计
|
||||
|
||||
## 总体架构
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Incoming Webhook] --> B[FastAPI /webhook/{namespace}]
|
||||
B --> C[Router]
|
||||
C --> D[Targets Forwarder]
|
||||
B --> E[Event Template]
|
||||
E --> F[Channels Sender]
|
||||
D --> G[External Webhook Targets]
|
||||
F --> H[Feishu]
|
||||
F --> I[WeCom]
|
||||
```
|
||||
|
||||
## 模块分层
|
||||
- 接入层:`app/main.py`(FastAPI 入口与 Webhook 接收)
|
||||
- 管理后台:`app/admin.py`(端点、规则、模板与渠道的增删改查)
|
||||
- 领域模型与持久化:`app/db.py`, `app/models.py`
|
||||
- 规则引擎:`app/services/engine.py`(树形规则 + 动作编排)
|
||||
- 通知发送:`app/services/notify.py`
|
||||
- 统计与日志:`app/services/stats.py`, `app/logging.py`
|
||||
|
||||
## 关键接口
|
||||
- `engine.process(endpoint_id, payload) -> (routed: List, notified: List)`
|
||||
- `_exec_forward(target, payload) -> Result`(内部使用)
|
||||
- `_exec_notify(channel, msg) -> Result`(内部使用)
|
||||
- 管理接口:`/admin/*` 用于维护端点、规则树、动作、模板与渠道
|
||||
|
||||
## 数据契约
|
||||
- 输入:示例 JSON 结构,关键字段存在于顶层与 `trans_order_info`
|
||||
- 输出:`{"namespace": str, "routed": [...], "notified": [...]}`,其中:
|
||||
- `routed`:每个转发目标的执行摘要(目标名、是否成功、失败原因)
|
||||
- `notified`:每个通知渠道的执行摘要(渠道名、是否成功、失败原因)
|
||||
|
||||
## 异常策略
|
||||
- 超时与网络错误重试;失败记录结构化日志
|
||||
- 非致命错误不影响其他目标或渠道发送
|
||||
|
||||
## 部署与运行(概要)
|
||||
- 本地直接运行:
|
||||
- 创建并激活虚拟环境(可选)
|
||||
- 执行 `pip install -r requirements.txt`
|
||||
- 启动服务:`uvicorn app.main:app --host 0.0.0.0 --port 8080`
|
||||
- Docker 部署:
|
||||
- 构建镜像:`docker build -t webhook-relay .`
|
||||
- 运行容器示例:
|
||||
- `docker run -d --name webhook-relay -p 8080:8080 webhook-relay`
|
||||
- 默认使用 SQLite 数据库,路径由环境变量 `DB_PATH` 控制,默认值为 `sqlite:///./config/data.db`
|
||||
- 如需持久化,可将宿主机目录挂载到容器内 `/app/config` 目录
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
# Webhook 中继系统流程图
|
||||
|
||||
## 1. 系统宏观架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph External["外部世界"]
|
||||
Sender["发送方 (支付宝/微信/业务系统)"]
|
||||
User["管理员"]
|
||||
TargetSys["目标系统 (ERP/BI)"]
|
||||
NotifyApp["IM工具 (飞书/企微)"]
|
||||
end
|
||||
|
||||
subgraph WebhookRelay["Webhook中继服务 (Docker)"]
|
||||
direction TB
|
||||
|
||||
subgraph Interface["接入层"]
|
||||
API["FastAPI (端口:8080)"]
|
||||
AdminUI["Web管理后台"]
|
||||
end
|
||||
|
||||
subgraph Core["核心逻辑层"]
|
||||
Parser["数据解析 (Pydantic)"]
|
||||
Router["路由引擎 (Routing)"]
|
||||
Notifier["通知引擎 (Notification)"]
|
||||
Logger["日志审计 (Logging)"]
|
||||
end
|
||||
|
||||
subgraph Data["数据存储层"]
|
||||
DB[(SQLite 数据库)]
|
||||
Config["Config Loader (DB优先 + YAML回退)"]
|
||||
end
|
||||
end
|
||||
|
||||
Sender -->|POST JSON| API
|
||||
User -->|浏览器访问| AdminUI
|
||||
AdminUI -->|CRUD配置| DB
|
||||
|
||||
API --> Parser
|
||||
Parser --> Router
|
||||
Parser --> Notifier
|
||||
|
||||
Router <-->|查询规则| Config
|
||||
Notifier <-->|查询模板| Config
|
||||
Config <-->|读取| DB
|
||||
|
||||
Router -->|转发请求| TargetSys
|
||||
Notifier -->|推送消息| NotifyApp
|
||||
|
||||
API -->|异步写入| Logger
|
||||
Logger -->|持久化| DB
|
||||
```
|
||||
|
||||
## 2. 详细数据处理流程
|
||||
|
||||
此图展示了一个 Webhook 请求从进入系统到完成分发与记录的完整生命周期。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Ext as 外部系统
|
||||
participant API as FastAPI入口
|
||||
participant DB as SQLite数据库
|
||||
participant Router as 路由服务
|
||||
participant Target as 目标系统
|
||||
participant Notifier as 通知服务
|
||||
participant Channel as IM渠道(飞书/企微)
|
||||
participant Log as 日志服务
|
||||
|
||||
Note over Ext, API: 1. 请求接入
|
||||
Ext->>API: POST /webhook/{namespace} (Payload)
|
||||
|
||||
activate API
|
||||
API->>DB: 校验 Namespace 是否有效/启用
|
||||
alt Namespace 无效/禁用
|
||||
API-->>Ext: 403 Forbidden
|
||||
else Namespace 有效
|
||||
API->>API: 解析 Payload (remark, event_no, trans_amt...)
|
||||
|
||||
par 2. 并行处理 - 转发 (Relay)
|
||||
API->>Router: 使用规则引擎匹配路由规则
|
||||
Router->>DB: 查询 ProcessingRule/RuleAction/Target
|
||||
Router-->>API: 返回目标列表 [Target A, Target B]
|
||||
|
||||
loop 对每个目标
|
||||
API->>Target: POST /target_url (异步 + 重试机制)
|
||||
Target-->>API: 响应 (200 OK / 500 Error)
|
||||
end
|
||||
|
||||
and 3. 并行处理 - 通知 (Notify)
|
||||
API->>Notifier: notify(event_no, payload)
|
||||
Notifier->>DB: 查询 ProcessingRule/RuleAction/MessageTemplate/NotificationChannel
|
||||
Notifier->>Notifier: 渲染模板 ("【{biz_name}】{pay_method_name} 收款 {trans_amt} 元,状态:{cash_resp_desc},日期:{trans_date}")
|
||||
Notifier-->>API: 返回消息文本 & 渠道列表
|
||||
|
||||
loop 对每个渠道
|
||||
API->>Channel: POST Webhook (发送消息)
|
||||
Channel-->>API: 响应结果
|
||||
end
|
||||
end
|
||||
|
||||
Note over API, Log: 4. 收尾工作
|
||||
API->>Log: BackgroundTask: 保存 RequestLog & DeliveryLog
|
||||
Log->>DB: INSERT request_logs, delivery_logs
|
||||
|
||||
API-->>Ext: 200 OK (包含 routed/notified 摘要)
|
||||
end
|
||||
deactivate API
|
||||
```
|
||||
|
||||
## 3. 数据库实体关系图 (ERD)
|
||||
|
||||
展示了用于支撑上述流程的数据库模型结构。
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
WebhookEndpoint {
|
||||
int id PK
|
||||
string namespace "URL路径标识"
|
||||
string description
|
||||
bool is_active
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
ProcessingRule {
|
||||
int id PK
|
||||
int endpoint_id FK
|
||||
int parent_rule_id FK "父规则ID,可为空"
|
||||
int priority "优先级,高优先级先匹配"
|
||||
string match_field "如 remark / event_define_no"
|
||||
string operator "eq/neq/contains/regex"
|
||||
string match_value "匹配值"
|
||||
}
|
||||
|
||||
RuleAction {
|
||||
int id PK
|
||||
int rule_id FK
|
||||
string action_type "forward/notify"
|
||||
int target_id FK "转发目标,可空"
|
||||
int channel_id FK "通知渠道,可空"
|
||||
int template_id FK "消息模板,可空"
|
||||
json template_vars "模板变量,键值对"
|
||||
}
|
||||
|
||||
Target {
|
||||
int id PK
|
||||
string name
|
||||
string url
|
||||
int timeout_ms
|
||||
}
|
||||
|
||||
NotificationChannel {
|
||||
int id PK
|
||||
string name
|
||||
string channel_type "feishu/wecom"
|
||||
string webhook_url
|
||||
}
|
||||
|
||||
MessageTemplate {
|
||||
int id PK
|
||||
string name "模板名称"
|
||||
text template_content "模板内容"
|
||||
}
|
||||
|
||||
RequestLog {
|
||||
int id PK
|
||||
string namespace
|
||||
string remark "来源标识"
|
||||
string event_no "事件类型"
|
||||
json raw_body "原始数据"
|
||||
datetime received_at
|
||||
string status "success/error"
|
||||
}
|
||||
|
||||
DeliveryLog {
|
||||
int id PK
|
||||
int request_id FK
|
||||
string target_name
|
||||
string type "relay/notify"
|
||||
string status "success/failed"
|
||||
text response_summary
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
WebhookEndpoint ||--|{ ProcessingRule : "拥有多条规则"
|
||||
ProcessingRule ||--|{ ProcessingRule : "树形子规则"
|
||||
ProcessingRule ||--|{ RuleAction : "每条规则包含多个动作"
|
||||
RuleAction }o--|| Target : "转发到目标"
|
||||
RuleAction }o--|| NotificationChannel : "推送到渠道"
|
||||
RuleAction }o--|| MessageTemplate : "使用消息模板"
|
||||
RequestLog ||--|{ DeliveryLog : "包含多条分发记录"
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
# 原子任务清单
|
||||
|
||||
## T1 配置加载
|
||||
- 输入:`config/config.yml`
|
||||
- 输出:内存配置对象与查询API
|
||||
- 验收:能返回目标、remark与事件模板
|
||||
|
||||
## T2 模型解析
|
||||
- 输入:请求JSON
|
||||
- 输出:`IncomingPayload` 对象
|
||||
- 验收:示例JSON解析字段正确
|
||||
|
||||
## T3 路由与转发
|
||||
- 输入:`remark` 与目标列表
|
||||
- 输出:并发POST结果数组
|
||||
- 验收:`imcgcd03` 路由到 `target_3`
|
||||
|
||||
## T4 通知消息
|
||||
- 输入:`event_define_no` 与负载
|
||||
- 输出:消息文本与渠道推送结果
|
||||
- 验收:`pay.ali_scaned` 生成正确文本并推送
|
||||
|
||||
## T5 接口与容器
|
||||
- 输入:应用代码
|
||||
- 输出:FastAPI端点与Dockerfile
|
||||
- 验收:健康检查与示例数据POST通过
|
||||
|
||||
Reference in New Issue
Block a user