概览
Garmin 是一个真实的设备品牌客户端 ——src/health/vendor/device/garmin.cpp,注册为 garmin。它是 Mirobody”只实现可公开确认的部分,其余保留为诚实的桩”这一规则最具启发性的例子,因为 Garmin 的数据 API 需合作方授权且为推送式。
这是一个
vendor::Vendor,实现共享的 authorize / fetch / webhook 契约;接口参见 Vendor 系统。Garmin 的 API 形态带来的约束
| 方面 | 实际情况 | 对客户端的影响 |
|---|---|---|
| 认证 | OAuth 2.0 + PKCE(Garmin 已从 OAuth 1.0a 迁移);流程公开 | authorize_url 是桩 —— PKCE 需要一个有状态的 code_verifier,裸 URL 构建器无处存放它(那属于 EHR 式的有状态连接层) |
| 数据投递 | 推送式:Garmin 把汇总数据 POST 到已注册的 webhook;拉取需合作方授权且仅保留约 7 天 | fetch 是一个桩,它解释这一模型,而非伪造一次同步拉取 |
| Webhook 签名 | 推送无任何有文档的签名 | handle_webhook 是桩 —— 无法从公开文档验证真伪 |
| 断开连接 | 账号断连 hook 是公开有文档的 | revoke 已实现 |
revoke —— 以及三个刻意保留的桩(fetch、authorize_url、handle_webhook),而 list_providers 不适用(单一品牌)。这是预期状态,记录在该文件的头部。
revoke —— 唯一接通的操作
revoke 调用 Garmin 必需的账号断连端点 DELETE /wellness-api/rest/user/registration,以用户的 OAuth 2.0 access token 作为 bearer 认证:
https://apis.garmin.com(可经 MIROBODY_VENDOR_GARMIN_BASE_URL 覆盖)。
fetch —— 一个会自我解释的桩
Garmin 的 fetch 不用通用的”not implemented”,而是抛出一条说明原因的消息,让调用方了解这一模型:
元数据(info())
即便大多数操作都是桩,该 vendor 的 VendorInfo 依然被完整填充,且无需凭据即可查询:
配置
对你自己 vendor 的启示
- 实现可公开确认的部分;其余用带原因的桩留白。 一个点明缺失契约的桩,胜过一个捏造的契约。
- 有状态的 OAuth 流程(PKCE)单靠
authorize_url装不下 —— Mirobody 把这类流程保留在有状态的连接层(正如 SMART-on-FHIR EHR 连接服务所做的那样),而不是放进 URL 构建器的签名里。 VendorInfo无论如何都应完整 —— 它无需网络调用即可支撑选型 / 比较。
src/health/vendor/device/fitbit.cpp)对照,后者实现了 fetch、authorize_url、revoke 以及带签名的 handle_webhook。
下一步
Vendor 系统
Garmin 所实现的契约
Provider 集成
构建你自己的
vendor::VendorOAuth 实现
vendor 客户端中的 OAuth 2.0 / PKCE 模式
Provider 概览
所有已发布的 vendor