Files
junhong_cmp_fiber/openspec/changes/gateway-integration/specs/gateway-client/spec.md
huang 4856a88d41
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 43s
docs: 新增 Gateway 集成和微信公众号支付集成的 OpenSpec 规划文档
2026-01-30 16:09:32 +08:00

7.3 KiB
Raw Blame History

Gateway Client Specification

Gateway API 统一客户端,提供 14 个接口的类型安全封装。

ADDED Requirements

Requirement: Gateway 客户端结构

系统 SHALL 提供 gateway.Client 结构体,封装所有 Gateway API 调用。

客户端字段:

  • baseURL string - Gateway API 基础 URL
  • appID string - 应用 ID
  • appSecret string - 应用密钥
  • httpClient *http.Client - HTTP 客户端(支持连接复用)
  • timeout time.Duration - 请求超时时间

Scenario: 创建 Gateway 客户端

  • WHEN 调用 gateway.NewClient(baseURL, appID, appSecret)
  • THEN 返回已初始化的 Client 实例
  • AND HTTP 客户端配置正确(支持 Keep-Alive

Scenario: 配置超时时间

  • WHEN 调用 client.WithTimeout(30 * time.Second)
  • THEN 客户端的 timeout 字段更新为 30 秒
  • AND 返回客户端自身(支持链式调用)

Requirement: 统一请求方法

系统 SHALL 提供 doRequest 方法统一处理加密、签名、HTTP 请求和响应解析。

Scenario: 成功的 API 调用

  • WHEN 调用 doRequest(ctx, "/flow-card/status", businessData)
  • THEN 业务数据使用 AES-128-ECB 加密
  • AND 请求使用 MD5 签名
  • AND HTTP POST 发送到 {baseURL}/flow-card/status
  • AND 响应中的 data 字段解密并返回

Scenario: 网络错误

  • WHEN HTTP 请求失败网络中断、DNS 解析失败)
  • THEN 返回 CodeGatewayError 错误
  • AND 错误信息包含原始网络错误

Scenario: 请求超时

  • WHEN HTTP 请求超过配置的超时时间
  • THEN 返回 CodeGatewayTimeout 错误
  • AND Context 超时错误被正确识别

Scenario: 响应格式错误

  • WHEN Gateway 响应无法解析为 JSON
  • THEN 返回 CodeGatewayInvalidResp 错误
  • AND 错误信息包含原始响应内容(限制 200 字符)

Scenario: Gateway 业务错误

  • WHEN Gateway 响应中 code != 200
  • THEN 返回 CodeGatewayError 错误
  • AND 错误信息包含 Gateway 的 code 和 msg

Requirement: 流量卡 API 封装

系统 SHALL 提供 7 个流量卡相关的 API 方法。

Scenario: 查询流量卡状态

  • WHEN 调用 client.QueryCardStatus(ctx, &CardStatusReq{CardNo: "898608070422D0010269"})
  • THEN 返回 CardStatusResp 包含 ICCID 和卡状态
  • AND 卡状态为:"准备"、"正常" 或 "停机" 之一

Scenario: 查询流量使用

  • WHEN 调用 client.QueryFlow(ctx, &FlowQueryReq{CardNo: "898608070422D0010269"})
  • THEN 返回 FlowUsageResp 包含已用流量和单位
  • AND 流量单位为 "MB"

Scenario: 查询实名认证状态

  • WHEN 调用 client.QueryRealnameStatus(ctx, &CardStatusReq{CardNo: "898608070422D0010269"})
  • THEN 返回实名认证状态信息

Scenario: 流量卡停机

  • WHEN 调用 client.StopCard(ctx, &CardOperationReq{CardNo: "898608070422D0010269"})
  • THEN Gateway 执行停机操作
  • AND 方法返回 nil成功或错误

Scenario: 流量卡复机

  • WHEN 调用 client.StartCard(ctx, &CardOperationReq{CardNo: "898608070422D0010269"})
  • THEN Gateway 执行复机操作
  • AND 方法返回 nil成功或错误

Scenario: 获取实名认证链接

  • WHEN 调用 client.GetRealnameLink(ctx, &CardStatusReq{CardNo: "898608070422D0010269"})
  • THEN 返回实名认证跳转链接
  • AND 链接格式为有效的 HTTPS URL

Scenario: 广电国网扩展参数

  • WHEN 停机/复机请求中 Extend 字段不为空
  • THEN 请求包含 extend 参数
  • AND Gateway 正确处理广电国网特殊逻辑

Requirement: 设备 API 封装

系统 SHALL 提供 7 个设备相关的 API 方法。

Scenario: 查询设备信息

  • WHEN 调用 client.GetDeviceInfo(ctx, &DeviceInfoReq{CardNo: "898608070422D0010269"})
  • THEN 返回 DeviceInfoResp 包含设备详细信息
  • AND 信息包括IMEI、在线状态、信号强度、WiFi 配置、速率等

Scenario: 通过设备 ID 查询

  • WHEN 调用 client.GetDeviceInfo(ctx, &DeviceInfoReq{DeviceID: "868123456789012"})
  • THEN 通过设备 IMEI 查询设备信息
  • AND 返回结果与通过卡号查询一致

Scenario: 查询设备卡槽信息

  • WHEN 调用 client.GetSlotInfo(ctx, &DeviceInfoReq{CardNo: "898608070422D0010269"})
  • THEN 返回设备中已安装的物联网卡信息

Scenario: 设置设备限速

  • WHEN 调用 client.SetSpeedLimit(ctx, &SpeedLimitReq{DeviceID: "868123456789012", UploadSpeed: 1024, DownloadSpeed: 2048})
  • THEN 设备上下行速率设置为指定值KB/s

Scenario: 设置设备 WiFi

  • WHEN 调用 client.SetWiFi(ctx, &WiFiReq{DeviceID: "868123456789012", SSID: "MyWiFi", Password: "12345678", Enabled: true})
  • THEN 设备 WiFi 配置更新
  • AND WiFi 名称、密码和启用状态正确设置

Scenario: 设备切换卡

  • WHEN 调用 client.SwitchCard(ctx, &SwitchCardReq{DeviceID: "868123456789012", TargetICCID: "898608070422D0010270"})
  • THEN 多卡设备切换到目标 ICCID

Scenario: 设备恢复出厂设置

  • WHEN 调用 client.ResetDevice(ctx, &DeviceOperationReq{DeviceID: "868123456789012"})
  • THEN 设备恢复为出厂状态

Scenario: 设备重启

  • WHEN 调用 client.RebootDevice(ctx, &DeviceOperationReq{DeviceID: "868123456789012"})
  • THEN 设备执行重启操作

Requirement: 类型安全的 DTO

系统 SHALL 为所有请求和响应定义类型安全的结构体。

Scenario: 请求 DTO 包含验证标签

  • WHEN 定义 CardStatusReq 结构体
  • THEN CardNo 字段包含 validate:"required" 标签
  • AND 可以使用 Validator 库进行验证

Scenario: 响应 DTO 正确解析

  • WHEN Gateway 返回 JSON 响应
  • THEN CardStatusResp 结构体正确解析 iccidcardStatusextend 字段
  • AND 字段类型与 Gateway 文档一致

Requirement: 并发安全

系统 SHALL 确保 Client 结构体可以安全地并发调用。

Scenario: 多个 Goroutine 并发调用

  • WHEN 10 个 Goroutine 同时调用 client.QueryCardStatus
  • THEN 所有请求都正确执行
  • AND 不发生 race condition

Scenario: HTTP 连接复用

  • WHEN 多次调用相同的 Gateway API
  • THEN HTTP 客户端复用 TCP 连接
  • AND 减少连接建立开销

Requirement: 错误处理一致性

系统 SHALL 使用项目统一的错误码系统。

Scenario: Gateway 错误返回统一错误码

  • WHEN Gateway API 调用失败
  • THEN 返回 errors.AppError 类型
  • AND 错误码为 CodeGatewayErrorCodeGatewayTimeout 等之一

Scenario: 错误包含上下文信息

  • WHEN 加密失败
  • THEN 错误信息为 "数据加密失败"
  • AND 包含底层错误的详细信息

Requirement: Context 支持

系统 SHALL 支持通过 Context 控制请求超时和取消。

Scenario: 使用 Context 控制超时

  • WHEN 调用 client.QueryCardStatus(ctx, req) 且 ctx 设置了 30 秒超时
  • THEN 请求在 30 秒后自动超时
  • AND 返回 CodeGatewayTimeout 错误

Scenario: 取消请求

  • WHEN 调用 client.QueryCardStatus(ctx, req) 且 ctx 被取消
  • THEN 请求立即停止
  • AND 返回 context canceled 错误