第三方 API Key 集成文档

baozi 第三方接入:你(第三方)通过 ohoooho 统一认证(OAuth2 client_credentials 标准协议 + ES384 JWT)调 baozi 接口,一步完成「下单 + 创建 API Key」,5 分钟接入。

baozi 是 ohoooho 统一认证的 Resource Server:第三方在 ohooho 统一认证后台创建 M2M App,用 OAuth2 client_credentials 拿 access_token,调 baozi 接口时带 Authorization: Bearer <access_token>。baozi 只验签,不签 token。access_token 有效期 2 小时(7200 秒),客户端需自管理刷新。

1. 准备工作(4 步)

1.1 创建 API Resource

步骤 操作
后台 → API Resources+ Create API resource 创 API Resource
API name baozi Third-Party API
API identifier https://baozi.ohoooho.com

1.2 创建 M2M Role

UI 路径 操作
后台 Roles+ Create role → 命名 baozi Third-Party 创 Role

1.3 创建 M2M App + 授权 Role

UI 路径 操作
后台 Applications+ Create applicationMachine-to-machine 创 M2M App
M2M App 配置页 → Roles tab baozi Third-Party Role

1.4 确认 end_user(无需绑定)

OAuth2 client_credentials 只验证 M2M App 本身的身份,不绑定任何 baozi 用户。API Key 归属于请求中 external_user_id 所指定的 end_user。

1.4.1 external_user_id 的语义

external_user_id 是 end_user 在 ohooho 统一认证体系中的稳定唯一标识,对应 ohooho 统一认证 user.id字符串,Mgmt API 返 12 字符 base64-like,非 UUID)。

baozi 用 M2M token 调 GET https://login.ohoooho.com/api/users/{external_user_id} 反查 ohooho 统一认证,拿到完整 profile(含 sub / primaryEmail / primaryPhone / identities),再用 sub 在本地 users 表 upsert 拿到 newapi_uid

user id 类型 baozi 处理方式
ohoooho 统一认证 user.id(字符串) 三方传 external_user_id=<ohoooho 统一认证 user.id>,baozi 用 M2M token 调 GET /api/users/{id} 反查
sub(OIDC subject claim) ❌ ohooho 统一认证内部主键,三方系统不持有,不可作为 external_user_id
email / phone / username ❌ 不参与身份识别,不要传
第三方登录 ID(微信 openid / GitHub id / 企业微信 userid) ❌ 三方系统自有,baozi 通过 identities API 反查,不要传
external_user_info(身份兜底 + 自由文本) ✅ 必传(邮箱格式时)/ ⚪ 可选(追溯字段,详 §1.4.2)
baozi users.id(响应中的 user_id 自增整数) ⚠️ baozi 内部主键,仅供 baozi 内部关联使用

1.4.2 字段说明

  • external_user_id:end_user 在 ohooho 统一认证体系中的稳定唯一标识,对应 user.id字符串,Mgmt API 返 12 字符 base64-like,非 UUID)。
  • external_user_info身份兜底字段(K-312-28)。当 ohooho 统一认证里查不到 external_user_id、邮箱格式时 baozi 会用它调外部认证 Mgmt API search/create user。非邮箱格式时作为展示/追溯任意字符串,max 512 字符(UTF-8),baozi 透传到 baozi_orders.external_user_info 列。示例:"user@example.com" / "team-A 用户" / "13800001111" / "备注"
  • client_id:M2M App 的 OAuth2 客户端标识。OAuth2 client_credentials 是机器对机器认证,不与任何 baozi 用户绑定。

1.4.3 external_user_id 获取流程

  1. end_user 使用任意 OIDC connector(邮箱 / 手机 / 微信 / GitHub)在 https://baozi.ohoooho.com 完成一次登录。
  2. baozi 完成 OIDC 回调,通过 webhook 或 GET /api/v1/end_users?email= 反查接口告知该 end_user 的 user.id字符串,Mgmt API 返 12 字符 base64-like)。
  3. 三方系统记录该 user.id,用于后续下单。
  4. 三方下单时直接传 external_user_id=<ohoooho 统一认证 user.id>,baozi 通过 M2M token 反查 ohooho 统一认证,不依赖 end_user 使用的具体 connector

补充说明

  • 同一个 M2M App 可为不同 external_user_id 创建不同 key(每个订单独立 key)。
  • 同一个 end_user 可从多个 M2M App 各拿到独立 key(都在该用户的 baozi 账号下,登录 baozi 后台可见)。

1.4.4 admin checkout 例外

baozi 内部运营对账 / 补单时,可能传整数 baozi users.id 作为 external_user_id(admin checkout 流程)。该路径仅供 baozi 内部使用:服务端先按 sub 查询;若 external_user_id 为纯数字且按 sub 查不到,则 WHERE id = ? 查询 baozi users.id,并打 [partner/orders] admin checkout warn 日志。

对于使用本地 users.id 整数或 sub 字符串的旧集成,服务端按 ohooho 统一认证 user.id 字符串匹配失败后,会按上述 admin checkout 逻辑兜底查询。

2. 接入流程(3 步)

2.1 拿 access_token(OAuth2 client_credentials)

curl -X POST https://login.ohoooho.com/oidc/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=api"

返回:

{
  "access_token": "eyJhbGciOiJFUzM4NCIs...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "api"
}

access_token 默认 2 小时过期,建议在调用前 5 分钟刷新。

2.2 查 baozi 可购买套餐(推荐先调)

curl https://baozi.ohoooho.com/api/v1/packages \
  -H "Authorization: Bearer ***"

响应 200(精简版示例):

{
  "success": true,
  "api_version": "v1",
  "data": [
    {
      "id": "bz-taster",
      "name": "体验套餐",
      "scene": "taster",
      "tiers": [
        { "id": "lite", "name": "Lite", "price_yuan": 0, "quota": 1000, "period": "月" }
      ]
    }
  ],
  "total": 1
}

2.3 一步下单 + 创 API Key(核心)

curl -X POST https://baozi.ohoooho.com/api/v1/partner/orders \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "package_id": "bz-taster",
    "period": "月",
    "external_order_id": "my-order-2026-09-18-001",
    "external_user_id": "abc12345-1234-5678-9abc-def012345678",
    "external_user_info": "user@example.com",
    "settlement_mode": "baozi_paid"
  }'

每个字段详细参数使用和限制说明(K-312-12 完整化):

字段 类型 必填 长度限制 格式校验 示例值 含义
package_id string 1-64 chars baozi 套餐 ID(来自 GET /api/v1/packages "bz-taster" baozi 套餐标识
period string enum month / year / / "月" 计费周期
external_order_id string 1-128 chars 唯一,三方自生成(推荐 UUID v4 或带日期前缀) "my-order-2026-09-18-001" 三方订单号 = 幂等键(baozi 去重用)
external_user_id string 1-128 chars ohoooho 统一认证 user.id 字符串(Mgmt API 返 12 字符 base64-like) "qbtk3tka66u8" end_user 在 ohooho 统一认证体系中的稳定唯一标识;baozi 用 M2M token 调 GET /api/users/{id} 反查
external_user_info string ⚪ 可选 / ✅ 必传(兜底创号时) 0-512 chars 邮箱格式(兜底)或自由文本(追溯) "user@example.com" / "13800001111" / "wxid_abc" / "备注" 身份兜底字段(邮箱格式时调外部认证 Mgmt search/create);非邮箱格式作为展示/追溯任意字符串,baozi 透传到订单表
settlement_mode string enum baozi_paid(你付 baozi) / external_paid(已收款,仅记账) "baozi_paid" 结算模式
settlement_amount_yuan number ⚠️ external_paid 时必填 0 < x ≤ 1000000 正数(元,2 位小数) 199.00 已结算金额(external_paid 模式必填,baozi_paid 模式按套餐价)
token_name string ⚪ 可选 1-64 chars 自由文本(new-api 限 50 chars,建议 ≤50) &quot;my-team-key&quot; API Key 名称(默认 co-${pkg.id}-${ts}
metadata object ⚪ 可选 JSON < 4KB baozi 透传(不解析) {&quot;campaign&quot;:&quot;promo-2026&quot;} 三方自定义元数据,透传到订单 metadata 字段

HTTP Header

Header 必填 长度限制 格式 含义
Authorization: Bearer &lt;token&gt; - ohooho 统一认证 JWT(ES384) M2M access_token
Content-Type - application/json -
X-Idempotency-Key ⚪ 可选 1-128 chars 推荐 UUID v4 幂等键(与 external_order_id 二选一或同时带)

字段名变更说明

  • external_user_id:固定为 ohoooho 统一认证 user.id 字符串。baozi 用 M2M token 反查 ohooho 统一认证,不依赖 baozi users 表 sub 列
  • external_user_info:身份兜底字段 + 展示/追溯任意字符串,max 512 字符长度限制(K-312-28)。邮箱格式时 baozi 调外部认证 Mgmt API search/create user;非邮箱格式直接透传到 baozi_orders.external_user_info 列。

响应 201(订单 + API Key 一次给齐):

{
  "success": true,
  "api_version": "v1",
  "order_id": "co-1789379842859-k4hy49",
  "transaction_id": "txn-co-1789379842859-k4hy49",
  "amount_yuan": 0,
  "status": "fulfilled",
  "user_token_id": 19,
  "full_key": "9hIJ**********JGEA",
  "masked_key": "9hIJ***...JGEA",
  "quota_added": 1000,
  "expires_at": 1791971842000,
  "_one_time": true,
  "_hint": "full_key 仅 partner/orders 一次性返, 后续不返. 请立即保存."
}

⚠️ full_key 仅创时一次性返回,请立即安全保存!后续 list / detail 都不再返。

2.4 用 API Key 调 baozi 模型

curl -X POST https://llm.ohoooho.com/v1/chat/completions \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

3. 对账(1 步)

第三方跟 baozi 对账时,调下面端点查自己创建的全部订单:

curl https://baozi.ohoooho.com/api/v1/partner/orders \
  -H "Authorization: Bearer ***"

响应 200(实测 2026-09-14):

{
  "success": true,
  "api_version": "v1",
  "total": 1,
  "limit": 20,
  "offset": 0,
  "count": 1,
  "orders": [
    {
      "order_id": "co-1789379842859-k4hy49",
      "user_id": 1,
      "package_id": "bz-taster",
      "scene": "taster",
      "tier": "lite",
      "period": "月",
      "amount_yuan": 0,
      "status": "fulfilled",
      "payment_provider": "mock",
      "external_order_id": "my-order-2026-09-14-001",
      "external_user_id": "abc12345-1234-5678-9abc-def012345678",
      "external_user_info": "team-A 用户",
      "settlement_mode": "baozi_paid",
      "quota_added": 1000,
      "created_at": 1789379842431,
      "paid_at": 1789379842431,
      "fulfilled_at": 1789379842431
    }
  ],
  "_hint": "支持查询参数: limit (1-100, 默认 20), offset (默认 0), status, external_user_id (ohoooho 统一认证 user.id 字符串), external_user_info (模糊匹配), start_date, end_date (ms timestamp)"
}

对账要点

字段 对账逻辑
orders[].amount_yuan 实际应付 baozi 多少钱
orders[].quota_added baozi 实际给多少配额
orders[].status fulfilled = 已履约;refunded = 已退款
orders[].external_order_id 你的幂等键

支持 query 参数

参数 类型 默认 说明
limit int 20 1-100
offset int 0 分页偏移
status string - 过滤: fulfilled / refunded / cancelled
external_user_id string - 过滤: ohooho 统一认证 user.id 字符串(baozi 用 M2M token 反查)
external_user_info string - 过滤: 模糊匹配订单表 external_user_info 列(任意字符串子串)
start_date int (ms) - 起始时间戳
end_date int (ms) - 结束时间戳

防越权:强制 WHERE client_id = req.m2m.client_id,看不到其他 partner 的订单。

4. 错误码(精简版)

code 含义 触发场景
unauthorized 缺 Authorization 头 Authorization 头缺失
invalid_token access_token 无效 token 错或过期
invalid_request 参数缺失或格式错 必填字段缺失
package_not_found 套餐不存在 / 已下架 package_id 错
end_user_not_found end_user 不存在 baozi 用 external_user_id 调 ohooho 统一认证 API 查不到该用户(让用户先用任意 OIDC connector 在 baozi 登录一次)
end_user_not_linked end_user 未关联 new-api 用户登录过 baozi 但还没完成 new-api 映射(baozi 会自动建,可能需要等几秒重试)
self_create_failed 后端创 token 失败 new-api 不可用,重试

5. 完整版

需要其他接口(POST /api/v1/orders 分步下单 / GET /api/v1/orders/:id 单查 / POST /api/v1/orders/:id/refund 退款 / GET /api/v1/tokens 列 keys / GET /api/v1/tokens/:id 单查 / DELETE /api/v1/tokens/:id 撤销)请看 完整版第三方文档。无 basicauth 凭据要求,公开可读。

6. 联系 baozi

  • 邮箱:support@ohoooho.com(仅当 ohooho 统一认证 / baozi 服务故障或合规需求时联系;流程问题请先翻文档)
  • client_secret 泄露 / 撤销:去你自己的 ohooho 统一认证控制台后台处理(baozi 不参与 secret 生命周期)

文档问题反馈:飞书群 @ 闲云 · 第三方 API Key 集成文档