API 客户端集成.md 14 KB

API 客户端集成

本文档引用的文件

  • src/client/cosmoe.ts
  • src/command/index.ts
  • src/index.ts
  • src/command/handlers/login.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/history.ts
  • src/scheduler/index.ts
  • wrangler.jsonc
  • package.json
  • 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 命名空间用于凭证与状态存储

    graph TB
    subgraph "客户端层"
    C1["CosmoeClient<br/>封装 API 调用"]
    end
    subgraph "命令层"
    CMD["命令路由与会话"]
    H1["登录处理器"]
    H2["预约处理器"]
    H3["历史处理器"]
    end
    subgraph "调度层"
    SCH["定时任务处理器"]
    end
    subgraph "配置层"
    W["Wrangler 配置<br/>KV 命名空间"]
    end
    CMD --> C1
    H1 --> C1
    H2 --> C1
    H3 --> C1
    SCH --> C1
    C1 --> W
    

图表来源

  • src/client/cosmoe.ts
  • src/command/index.ts
  • src/scheduler/index.ts
  • wrangler.jsonc

章节来源

  • src/index.ts
  • src/command/index.ts
  • src/scheduler/index.ts
  • wrangler.jsonc

核心组件

  • CosmoeClient:统一的 API 客户端,负责认证、事件查询、用户资料、预约、支付订单更新、取消与转约等操作
  • 命令路由与处理器:将 Telegram 命令映射到具体业务逻辑,并通过 CosmoeClient 执行
  • 定时任务:周期性拉取新活动并推送通知
  • KV 存储:凭证与状态持久化(COSMOE_CREDENTIALS、COSMOE_STORAGE)

章节来源

  • src/client/cosmoe.ts
  • src/command/index.ts
  • src/scheduler/index.ts
  • wrangler.jsonc

架构总览

下图展示了从 Telegram 命令到 API 调用再到 KV 存储的整体流程。

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
  • src/command/handlers/login.ts
  • src/command/handlers/bookEvent.ts
  • src/client/cosmoe.ts
  • wrangler.jsonc

详细组件分析

CosmoeClient 组件分析

CosmoeClient 是整个系统的 API 封装核心,提供以下能力:

  • 认证:获取 token 并缓存用户标识与 token
  • 查询:活动列表、活动详情、用户资料、预约历史
  • 业务:预约、修改密码、优惠券查询、支付订单更新、备注更新、取消、改签、转约
  • 安全:所有需要鉴权的方法均在调用前校验认证状态

    classDiagram
    class CosmoeClient {
    -baseUrl : string
    -userId : number
    -token : string
    +getToken(username, password) Promise~ApiResponse<TokenResponse>~
    +setCredentials(userId, token) void
    +getCredentials() {userId, token} | null
    +isAuthenticated() boolean
    +getEvents() Promise~ApiResponse<Event[]>~
    +getEventDetail(eventId) Promise~ApiResponse<EventDetail>~
    +getProfile() Promise~ApiResponse<ProfileData>~
    +getMyBookings() Promise~ApiResponse<Booking[]>~
    +bookEvent(req) Promise~ApiResponse<any>~
    +changePassword(old, new) Promise~ApiResponse<any>~
    +getUserProfile() Promise~ApiResponse<UserProfile>~
    +getAvailableCoupons(eventId) Promise~ApiResponse<Coupon[]>~
    +updatePaymentOrder(bookingId, orderId) Promise~ApiResponse<any>~
    +updateBookingNote(bookingId, note) Promise~ApiResponse<any>~
    +cancelBooking(bookingId) Promise~ApiResponse<any>~
    +selfReschedule(bookingId, newSlot) Promise~ApiResponse<any>~
    +selfTransfer(bookingId, recipient) Promise~ApiResponse<any>~
    +register(key, username, email, password, identity) Promise~ApiResponse<{user_id, username}>~
    }
    

图表来源

  • src/client/cosmoe.ts

章节来源

  • src/client/cosmoe.ts

登录流程与认证集成

登录流程通过交互式会话完成,成功后将凭证写入 KV 命名空间,后续命令处理器读取并注入到 CosmoeClient。

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
  • src/client/cosmoe.ts
  • wrangler.jsonc

章节来源

  • src/command/handlers/login.ts

预约流程与优惠券选择

预约流程包含活动详情获取、时间槽选择、优惠券查询与选择、最终提交预约。

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
  • src/command/handlers/bookEvent.ts
  • src/client/cosmoe.ts
  • src/client/cosmoe.ts
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/bookEvent.ts

预约历史与取消

历史查询与取消流程展示了认证检查、数据排序与条件生成。

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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/history.ts

定时任务与新活动通知

定时任务每分钟执行一次,比较最新事件 ID 并向所有已注册用户推送新活动通知。

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
  • src/client/cosmoe.ts
  • wrangler.jsonc

章节来源

  • src/scheduler/index.ts

依赖关系分析

  • 运行时依赖:grammy、@grammyjs/conversations、@grammyjs/storage-cloudflare
  • Worker 配置:KV 命名空间绑定、定时触发器、环境变量
  • 测试:Vitest + Cloudflare Workers 测试工具链

    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
  • wrangler.jsonc

章节来源

  • package.json
  • wrangler.jsonc

性能考量

  • 请求合并与去抖:对于频繁查询的场景(如历史列表),可在客户端层增加本地缓存与去抖策略
  • 异步并发:命令处理器中避免不必要的串行等待,合理使用 Promise 并行
  • KV 读写:KV 写入为最终一致,建议在关键路径上做幂等与重试
  • 超时与重试:当前实现未显式设置超时与重试,建议在 fetch 层增加超时控制与指数退避重试
  • 数据量限制:历史消息长度超过平台限制时需截断或分页

故障排除指南

  • 认证失败
    • 检查 KV 中是否正确存储了凭证
    • 确认 CosmoeClient 是否已 setCredentials
    • 查看服务端返回的错误码与消息
  • 服务端响应异常
    • 捕获网络错误与 JSON 解析异常
    • 在处理器中对 code 字段进行严格判断
  • KV 读写异常
    • 检查命名空间绑定与权限
    • 对 JSON 解析失败进行容错处理
  • 定时任务失败
    • 查看日志输出,确认事件列表与用户列表读取是否成功
    • 注意消息发送失败时的回退策略

章节来源

  • src/command/handlers/login.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/history.ts
  • src/scheduler/index.ts

结论

本项目以 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

扩展指南:新增 API 端点

步骤概览:

  1. 在 CosmoeClient 中新增方法,定义请求参数与返回类型
  2. 在命令处理器中调用新方法并处理返回结果
  3. 如需持久化状态,使用 KV 命名空间进行读写
  4. 编写单元测试与集成测试,覆盖正常与异常分支

    flowchart TD
    A["定义新 API 方法"] --> B["实现请求构建与响应解析"]
    B --> C["在处理器中调用新方法"]
    C --> D["处理返回结果与错误"]
    D --> E["必要时写入 KV"]
    E --> F["编写测试用例"]
    

[此图为概念性流程图,无需图表来源]

超时与重试机制建议

  • 超时控制:在 fetch 层设置合理的超时时间(例如 10 秒)
  • 指数退避重试:对 5xx 或网络瞬时错误进行最多 3 次重试,间隔 1、2、4 秒
  • 幂等性:对可能重复提交的操作(如支付订单更新)确保幂等
  • 降级策略:在网络不可用时返回友好提示并记录日志

[本节为通用指导,无需章节来源]