# API 客户端集成
**本文档引用的文件**
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts)
- [src/command/index.ts](file://src/command/index.ts)
- [src/index.ts](file://src/index.ts)
- [src/command/handlers/login.ts](file://src/command/handlers/login.ts)
- [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts)
- [src/command/handlers/history.ts](file://src/command/handlers/history.ts)
- [src/scheduler/index.ts](file://src/scheduler/index.ts)
- [wrangler.jsonc](file://wrangler.jsonc)
- [package.json](file://package.json)
- [test/index.spec.ts](file://test/index.spec.ts)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本指南面向需要在 Cosmoe Bot 中集成与扩展 API 客户端的开发者,系统讲解如何封装新的 API 端点调用(请求构建、响应处理、错误管理)、认证机制(token 管理、权限验证、安全考虑)、设计模式(可维护性与可测试性)、异步操作与超时控制、重试机制、数据模型定义与验证,以及实际扩展示例(新增服务端功能或第三方 API 集成)。
## 项目结构
该项目基于 Cloudflare Workers 与 GrammY 框架,采用分层组织:
- 客户端层:封装对 Cosmoe 服务端 API 的调用,统一请求参数、响应格式与错误处理
- 命令层:通过 Telegram Bot 命令与交互式会话触发业务流程
- 调度层:定时任务轮询新活动并向已注册用户推送通知
- 配置层:Wrangler 配置 KV 命名空间用于凭证与状态存储
```mermaid
graph TB
subgraph "客户端层"
C1["CosmoeClient
封装 API 调用"]
end
subgraph "命令层"
CMD["命令路由与会话"]
H1["登录处理器"]
H2["预约处理器"]
H3["历史处理器"]
end
subgraph "调度层"
SCH["定时任务处理器"]
end
subgraph "配置层"
W["Wrangler 配置
KV 命名空间"]
end
CMD --> C1
H1 --> C1
H2 --> C1
H3 --> C1
SCH --> C1
C1 --> W
```
图表来源
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503)
- [src/command/index.ts](file://src/command/index.ts#L20-L110)
- [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88)
- [wrangler.jsonc](file://wrangler.jsonc#L21-L30)
章节来源
- [src/index.ts](file://src/index.ts#L1-L47)
- [src/command/index.ts](file://src/command/index.ts#L1-L110)
- [src/scheduler/index.ts](file://src/scheduler/index.ts#L1-L88)
- [wrangler.jsonc](file://wrangler.jsonc#L1-L31)
## 核心组件
- CosmoeClient:统一的 API 客户端,负责认证、事件查询、用户资料、预约、支付订单更新、取消与转约等操作
- 命令路由与处理器:将 Telegram 命令映射到具体业务逻辑,并通过 CosmoeClient 执行
- 定时任务:周期性拉取新活动并推送通知
- KV 存储:凭证与状态持久化(COSMOE_CREDENTIALS、COSMOE_STORAGE)
章节来源
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503)
- [src/command/index.ts](file://src/command/index.ts#L20-L110)
- [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88)
- [wrangler.jsonc](file://wrangler.jsonc#L21-L30)
## 架构总览
下图展示了从 Telegram 命令到 API 调用再到 KV 存储的整体流程。
```mermaid
sequenceDiagram
participant U as "用户"
participant B as "Bot 命令路由"
participant H as "命令处理器"
participant C as "CosmoeClient"
participant S as "Cosmoe 服务端"
participant K as "KV 存储"
U->>B : 发送命令/回调
B->>H : 分发到对应处理器
H->>K : 读取用户凭证
alt 凭证存在
H->>C : 初始化并设置凭证
H->>C : 调用 API 方法
C->>S : 发起 HTTP 请求
S-->>C : 返回 JSON 响应
C-->>H : 解析并返回结果
H-->>U : 发送回复
else 凭证不存在
H-->>U : 提示先登录
end
```
图表来源
- [src/command/index.ts](file://src/command/index.ts#L59-L109)
- [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L43-L69)
- [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L37-L117)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503)
- [wrangler.jsonc](file://wrangler.jsonc#L21-L30)
## 详细组件分析
### CosmoeClient 组件分析
CosmoeClient 是整个系统的 API 封装核心,提供以下能力:
- 认证:获取 token 并缓存用户标识与 token
- 查询:活动列表、活动详情、用户资料、预约历史
- 业务:预约、修改密码、优惠券查询、支付订单更新、备注更新、取消、改签、转约
- 安全:所有需要鉴权的方法均在调用前校验认证状态
```mermaid
classDiagram
class CosmoeClient {
-baseUrl : string
-userId : number
-token : string
+getToken(username, password) Promise~ApiResponse~
+setCredentials(userId, token) void
+getCredentials() {userId, token} | null
+isAuthenticated() boolean
+getEvents() Promise~ApiResponse~
+getEventDetail(eventId) Promise~ApiResponse~
+getProfile() Promise~ApiResponse~
+getMyBookings() Promise~ApiResponse~
+bookEvent(req) Promise~ApiResponse~
+changePassword(old, new) Promise~ApiResponse~
+getUserProfile() Promise~ApiResponse~
+getAvailableCoupons(eventId) Promise~ApiResponse~
+updatePaymentOrder(bookingId, orderId) Promise~ApiResponse~
+updateBookingNote(bookingId, note) Promise~ApiResponse~
+cancelBooking(bookingId) Promise~ApiResponse~
+selfReschedule(bookingId, newSlot) Promise~ApiResponse~
+selfTransfer(bookingId, recipient) Promise~ApiResponse~
+register(key, username, email, password, identity) Promise~ApiResponse<{user_id, username}>~
}
```
图表来源
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503)
章节来源
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503)
### 登录流程与认证集成
登录流程通过交互式会话完成,成功后将凭证写入 KV 命名空间,后续命令处理器读取并注入到 CosmoeClient。
```mermaid
sequenceDiagram
participant U as "用户"
participant C as "对话处理器"
participant CL as "CosmoeClient"
participant S as "Cosmoe 服务端"
participant K as "KV 命名空间"
U->>C : 输入用户名/密码
C->>CL : 创建实例并调用 getToken
CL->>S : POST /CreatToken.php
S-->>CL : 返回 {code, data : {user_id, token}}
CL-->>C : 返回结果
alt 成功
C->>K : put(telegramUserId, {user_id, token, timestamp})
C-->>U : 登录成功
else 失败
C-->>U : 登录失败
end
```
图表来源
- [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L74)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L124-L140)
- [wrangler.jsonc](file://wrangler.jsonc#L21-L30)
章节来源
- [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L1-L75)
### 预约流程与优惠券选择
预约流程包含活动详情获取、时间槽选择、优惠券查询与选择、最终提交预约。
```mermaid
sequenceDiagram
participant U as "用户"
participant B as "命令路由"
participant H as "预约处理器"
participant C as "CosmoeClient"
participant S as "Cosmoe 服务端"
participant K as "KV 命名空间"
U->>B : /book_{eventId}_{slotIndex}
B->>H : 触发 handleBookEvent
H->>K : 读取凭证
H->>C : setCredentials(...)
H->>C : getEventDetail(eventId)
C->>S : GET /api.php?action=get_event_detail
S-->>C : 返回 EventDetail
C-->>H : 返回详情
alt 多个优惠券
H-->>U : 展示优惠券选择键盘
U->>B : 回调选择优惠券
B->>H : 触发 handleCouponSelection
else 单个或无优惠券
H->>C : bookEvent({event_id, time_slot, coupon_code?})
C->>S : POST /api.php
S-->>C : 返回结果
C-->>H : 返回结果
H-->>U : 成功/失败提示
end
```
图表来源
- [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L118)
- [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L159-L226)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L191-L199)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L247-L270)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L329-L343)
章节来源
- [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L1-L226)
### 预约历史与取消
历史查询与取消流程展示了认证检查、数据排序与条件生成。
```mermaid
flowchart TD
Start(["进入历史命令"]) --> ReadKV["读取 KV 中用户凭证"]
ReadKV --> HasCreds{"凭证是否存在?"}
HasCreds --> |否| PromptLogin["提示先登录"] --> End
HasCreds --> |是| InitClient["初始化 CosmoeClient 并 setCredentials"]
InitClient --> GetBookings["getMyBookings()"]
GetBookings --> ResultOK{"code == 200 且有数据?"}
ResultOK --> |否| ShowError["显示获取失败"] --> End
ResultOK --> |是| Sort["按日期降序排序并取最新若干条"]
Sort --> BuildMsg["构建 Markdown 格式消息"]
BuildMsg --> CancelLink{"满足取消条件?"}
CancelLink --> |是| AddCancel["添加取消链接"]
CancelLink --> |否| SkipCancel["跳过取消链接"]
AddCancel --> Send["发送消息"]
SkipCancel --> Send
Send --> End(["结束"])
```
图表来源
- [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L4-L107)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L226-L239)
章节来源
- [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L1-L107)
### 定时任务与新活动通知
定时任务每分钟执行一次,比较最新事件 ID 并向所有已注册用户推送新活动通知。
```mermaid
sequenceDiagram
participant T as "定时器"
participant SCH as "调度处理器"
participant C as "CosmoeClient"
participant S as "Cosmoe 服务端"
participant K as "KV 命名空间"
participant U as "Telegram 用户"
T->>SCH : 触发 scheduled
SCH->>C : getEvents()
C->>S : GET /api.php?action=get_events
S-->>C : 返回事件列表
C-->>SCH : 返回事件列表
SCH->>K : list() 获取所有已注册用户
loop 对每个新事件
SCH->>U : 发送通知消息
end
SCH->>K : 更新 latestEventId
```
图表来源
- [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88)
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L177-L184)
- [wrangler.jsonc](file://wrangler.jsonc#L13-L17)
章节来源
- [src/scheduler/index.ts](file://src/scheduler/index.ts#L1-L88)
## 依赖关系分析
- 运行时依赖:grammy、@grammyjs/conversations、@grammyjs/storage-cloudflare
- Worker 配置:KV 命名空间绑定、定时触发器、环境变量
- 测试:Vitest + Cloudflare Workers 测试工具链
```mermaid
graph LR
P["package.json 依赖"] --> G["grammy"]
P --> GC["grammy conversations"]
P --> GS["grammy storage-cloudflare"]
W["wrangler.jsonc"] --> KV1["COSMOE_CREDENTIALS"]
W --> KV2["COSMOE_STORAGE"]
W --> TRIG["定时触发器"]
```
图表来源
- [package.json](file://package.json#L18-L22)
- [wrangler.jsonc](file://wrangler.jsonc#L13-L30)
章节来源
- [package.json](file://package.json#L1-L24)
- [wrangler.jsonc](file://wrangler.jsonc#L1-L31)
## 性能考量
- 请求合并与去抖:对于频繁查询的场景(如历史列表),可在客户端层增加本地缓存与去抖策略
- 异步并发:命令处理器中避免不必要的串行等待,合理使用 Promise 并行
- KV 读写:KV 写入为最终一致,建议在关键路径上做幂等与重试
- 超时与重试:当前实现未显式设置超时与重试,建议在 fetch 层增加超时控制与指数退避重试
- 数据量限制:历史消息长度超过平台限制时需截断或分页
## 故障排除指南
- 认证失败
- 检查 KV 中是否正确存储了凭证
- 确认 CosmoeClient 是否已 setCredentials
- 查看服务端返回的错误码与消息
- 服务端响应异常
- 捕获网络错误与 JSON 解析异常
- 在处理器中对 code 字段进行严格判断
- KV 读写异常
- 检查命名空间绑定与权限
- 对 JSON 解析失败进行容错处理
- 定时任务失败
- 查看日志输出,确认事件列表与用户列表读取是否成功
- 注意消息发送失败时的回退策略
章节来源
- [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L70-L74)
- [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L114-L118)
- [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L103-L107)
- [src/scheduler/index.ts](file://src/scheduler/index.ts#L81-L84)
## 结论
本项目以 CosmoeClient 为核心,结合 GrammY 命令系统与 Cloudflare KV 实现了完整的聊天机器人 API 集成方案。通过清晰的职责分离与模块化设计,既保证了可维护性,也为后续扩展新的服务端功能或第三方 API 提供了良好基础。
## 附录
### 设计模式与最佳实践
- 单一职责:每个 API 方法只负责一个业务动作
- 统一错误处理:所有 API 方法返回统一的 ApiResponse 结构
- 权限前置:所有需要鉴权的方法在调用前检查认证状态
- 可测试性:将 KV 读写抽象为接口,便于单元测试替换
- 可扩展性:新增 API 时遵循现有模式,保持一致的请求/响应结构
### 数据模型与验证
- 统一响应结构:包含 code、msg、data 字段
- 关键实体:Event、EventDetail、UserInfo、UserProfile、Booking、Coupon 等
- 参数校验:在客户端层对输入参数进行基本校验(如密码长度、时间槽索引范围)
- 类型约束:使用 TypeScript 接口确保数据结构一致性
章节来源
- [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L9-L112)
### 扩展指南:新增 API 端点
步骤概览:
1. 在 CosmoeClient 中新增方法,定义请求参数与返回类型
2. 在命令处理器中调用新方法并处理返回结果
3. 如需持久化状态,使用 KV 命名空间进行读写
4. 编写单元测试与集成测试,覆盖正常与异常分支
```mermaid
flowchart TD
A["定义新 API 方法"] --> B["实现请求构建与响应解析"]
B --> C["在处理器中调用新方法"]
C --> D["处理返回结果与错误"]
D --> E["必要时写入 KV"]
E --> F["编写测试用例"]
```
[此图为概念性流程图,无需图表来源]
### 超时与重试机制建议
- 超时控制:在 fetch 层设置合理的超时时间(例如 10 秒)
- 指数退避重试:对 5xx 或网络瞬时错误进行最多 3 次重试,间隔 1、2、4 秒
- 幂等性:对可能重复提交的操作(如支付订单更新)确保幂等
- 降级策略:在网络不可用时返回友好提示并记录日志
[本节为通用指导,无需章节来源]