---
url: /zh/paas/platform-token.md
description: |
  说明 PAAS 版平台令牌的用途与申请方式， 介绍如何通过换票接口获取云原生构建 OpenAPI 的临时访问票据， 供第三方服务集成使用。
---
## 概述

平台令牌供第三方服务通过换票接口获取云原生构建 OpenAPI 的临时访问票据。

## 平台令牌申请

前往 admin 管理平台，为第三方服务创建平台令牌，获得 **name** 和 **secret\_key**。

## 服务地址

服务请求地址为 `3rd.cnbprod.alpha.qq.com`。

## 接口

CNB 提供以下换票接口：

### 基于用户名的换票

* 接口地址：`/platform-token/-/user/{username}`
* 接口方法："POST"
* 系统授权：system-token:rw
* 功能描述：换取指定 {username} 用户的个人令牌。
* 参数：
  * expire：可选参数，令牌有效期，支持 1m ~ 24h

### 基于用户 ID 的换票

* 接口地址：`/platform-token/-/userid/{userid}`
* 接口方法："POST"
* 系统授权：system-token:rw
* 功能描述：换取指定 {userid} 用户的个人令牌。
* 参数：
  * expire：可选参数，令牌有效期，支持 1m ~ 24h

### 基于 OpenID 的换票

* 接口地址：`/platform-token/-/openid/{openid}`
* 接口方法："POST"
* 系统授权：system-token:rw
* 功能描述：换取指定 {openid} 用户的个人令牌。
* 参数：
  * user\_type：可选参数，用户类型，对应关系如下：
    * `0`: 微信用户
    * `1`: oauth 授权用户
    * `2`: 测试用户
    * `3`: 助手用户
    * `4`: ioa 授权用户
      默认值为 `1`。
  * expire：可选参数，令牌有效期，支持 1m ~ 24h

### 基于仓库全路径的换票

* 接口地址：`/platform-token/-/repo/{repo-path}`
* 接口方法："POST"
* 系统授权：system-token:rw
* 功能描述：随机选择 {repo-path} 仓库的某位负责人用户，换取该用户的个人令牌。
* 参数：
  * expire：可选参数，令牌有效期，支持 1m ~ 24h

### 基于组织全路径的换票

* 接口地址：`/platform-token/-/organization/{organization-path}`
* 接口方法："POST"
* 系统授权：system-token:rw
* 功能描述：随机选择 {organization-path} 组织的某位负责人用户，换取该用户的个人令牌。
* 参数：
  * expire：可选参数，令牌有效期，支持 1m ~ 24h

### 列出所有根组织

* 接口地址：`/platform-token/-/organization`
* 接口方法："GET"
* 系统授权：system-search:r
* 功能描述：列出所有根组织信息。
* 参数：
  * page：页码，从 1 开始
  * page\_size：每页数量
  * search：根组织名称，只支持全匹配

### 查找资源 ID 对应的对象信息

* 接口地址：`/platform-token/-/resolve/{type:string}`
* 接口方法："POST"
* 系统授权：system-search:r
* 功能描述：根据资源 ID 查询对象信息。
* 参数：
  * type：类型 organization/repo/mission/registry/user
  * body：请求 ID 列表

    ```json
    {
      "id": ["123"]
    }
    ```

### 获取活跃仓库列表

* 接口地址：`/platform-token/-/active-repos`
* 接口方法："GET"
* 系统授权：system-search:r
* 功能描述：查询指定 10 分钟时间段内产生过动态的仓库列表，
  用于第三方服务增量拉取仓库变更。
* 参数（时间参数均按 UTC+8 时区计算）：
  * date：可选参数，日期，格式 yyyyMMdd，默认当天
  * hour：可选参数，小时，取值 0 ~ 23，默认当前小时
  * segment：可选参数，10 分钟段编号，取值 0 ~ 5，默认当前所处的段。
    每小时划分为 6 段，`0` 表示第 0 ~ 9 分钟，`1` 表示第 10 ~ 19 分钟，依此类推
* 返回：活跃仓库列表，该时间段内没有动态时返回空数组

  ```json
  [
    {
      "repo_id": "1293243433212",
      "slug": "organization/repo"
    }
  ]
  ```

:::: warning 注意
活跃仓库数据仅保留 **24 小时**，请在 24 小时内拉取，超出保留期的时间段返回空数组。
建议按 10 分钟的周期轮询，避免遗漏时间段。
::::

### 查找绑定码或认证手机号码对应的对象信息

* 接口地址：`/platform-token/-/bind/user`
* 接口方法："POST"
* 系统授权：system-bind:r
* 功能描述：根据绑定码或认证手机号码查询对象信息
* 参数：
  * body：请求 JSON 内容

    ```json
    {
      "type": "code",
      "user": "someone",
      "code": "123456"
    }
    ```

    * type：码类型，支持 `code`（绑定码）或 `phone`（手机号码）
    * code：码内容，如 `123456` 或 `1581xxx`
    * user：CNB 账户用户名
* 返回：用户信息

  ```json
  {
    "id": "1293243433212",
    "username": "someone"
  }
  ```

### 绑定用户

* 接口地址：`/platform-token/-/bind/user/{openid:string}`
* 接口方法："POST"
* 系统授权：system-bind:rw
* 功能描述：绑定用户
* 参数：
  * openid：第三方平台用户唯一 ID
  * body：请求 JSON 内容

    ```json
    {
      "type": "code",
      "code": "123456",
      "user": "someone",
      "metadata": {
        "name": "hello"
      }
    }
    ```

    * type：码类型，支持 `code`（绑定码）或 `phone`（手机号码）
    * code：码内容，如 `123456` 或 `1581xxx`
    * user：CNB 账户用户名
    * metadata：自定义元数据
* 返回：用户信息

  ```json
  {
    "id": "1293243433212",
    "username": "someone"
  }
  ```

### 批量解除用户绑定

* 接口地址：`/platform-token/-/unbind/user/{username:string or userid:string}`
* 接口方法："POST"
* 系统授权：system-bind:rw
* 功能描述：解除该用户在此平台上的所有绑定记录

### 解除用户绑定

* 接口地址：`/platform-token/-/unbind/user/{username:string or userid:string}/{openid:string}`
* 接口方法："POST"
* 系统授权：system-bind:rw
* 功能描述：解除该用户在此平台上的某一条绑定记录

### 锁定用户

* 接口地址：`/platform-token/-/lock/user/{username:string}`
* 接口方法："POST"
* 系统授权：system-lock:rw
* 功能描述：锁定指定 {username} 的用户
* 参数：
  * body：请求 JSON 内容

    ```json
    {
      "lock_duration": "10"
    }
    ```

    * lock\_duration：锁定天数

### 解锁用户

* 接口地址：`/platform-token/-/unlock/user/{username:string}`
* 接口方法："POST"
* 系统授权：system-lock:rw
* 功能描述：解锁指定 {username} 的用户

### 创建新用户

* 接口地址：`/platform-token/-/user/create/{openid:string}`
* 接口方法："POST"
* 系统授权：system-user:rw
* 功能描述：新建指定 {openid} 的 cnb 用户
* 参数：
  * body：请求 JSON 内容

    ```json
    {
      "name": "someone",
      "nick": "someone",
      "email": "someone@cnb.com"
    }
    ```

    * name：用户名
    * nick：用户昵称
    * email：用户邮箱

### 更新用户信息

* 接口地址：`/platform-token/-/user/update/{openid:string}`
* 接口方法："POST"
* 系统授权：system-user:rw
* 功能描述：更新指定 {openid} 的 cnb 用户的信息
* 参数：
  * body：请求 JSON 内容

    ```json
    {
      "name": "someone",
      "nick": "someone",
      "email": "someone@cnb.com"
    }
    ```

    * name：用户名
    * nick：用户昵称
    * email：用户邮箱

### 基于邮箱查询用户信息

* 接口地址：`/platform-token/-/user`
* 接口方法："POST"
* 系统授权：system-userinfo:r
* 功能描述：基于邮箱查询用户信息
* 参数：
  * body：请求 Email 邮箱列表

    ```json
    {
      "emails": ["test1@tencent.com", "test2@tencent.com"]
    }
    ```

## 资源绑定接口

### 绑定资源

* 接口地址：`/platform-token/-/bind/resource`
* 接口方法："POST"
* 系统授权：system-bind:rw
* 功能描述：将第三方平台的实例与 CNB 资源绑定
* 参数：
  * body：请求 JSON 内容

    ```json
    {
      "openid": "third-party-instance-id",
      "slug": "organization/repo",
      "code": "123456",
      "metadata": {
        "key": "value"
      }
    }
    ```

    * openid：第三方平台实例唯一 ID
    * slug：CNB 资源路径（如：组织/仓库）
    * code：绑定码
    * metadata：可选，绑定的扩展信息

### 获取资源绑定信息

* 接口地址：`/platform-token/-/bind/resource`
* 接口方法："GET"
* 系统授权：system-bind:r
* 功能描述：获取资源的绑定信息
* 参数：
  * slug：可选参数，过滤绑定的资源路径
  * openid：可选参数，过滤绑定的实例 OpenID
* 返回：资源绑定信息

  ```json
  {
    "data": [
      {
        "slug": "organization/repo",
        "openid": "third-party-instance-id",
        "metadata": "{\"key\":\"value\"}",
        "created_at": "2026-03-10T10:00:00Z",
        "updated_at": "2026-03-10T10:00:00Z"
      }
    ],
    "repository": {
      "id": "123456",
      "name": "repo",
      "path": "organization/repo"
    }
  }
  ```

### 解绑资源

* 接口地址：`/platform-token/-/bind/resource`
* 接口方法："DELETE"
* 系统授权：system-bind:rw
* 功能描述：解除第三方平台实例与 CNB 资源的绑定关系
* 参数：
  * slug：可选参数，过滤绑定的资源路径
  * openid：可选参数，过滤绑定的实例 OpenID
  * 注意：如果只提供 openid，则解除该实例的所有绑定；如果同时提供 slug 和 openid，则只解除特定资源的绑定

## 部署令牌接口

平台令牌绑定资源后，可为绑定的实例创建和管理部署令牌。
部署令牌用于访问绑定的 CNB 资源（如代码仓库），
每个实例通过唯一的密钥标识（key）管理其部署令牌。

### 创建部署令牌

* 接口地址：`/platform-token/-/deploy-keys/{openid}/{key}`
* 接口方法："POST"
* 系统授权：继承平台令牌的权限范围
* 功能描述：为已绑定的第三方平台实例创建部署令牌
* 路径参数：
  * openid：第三方平台实例唯一 ID（必须已完成资源绑定）
  * key：密钥标识，用于标识和管理该实例的部署令牌（同一 openid + key 组合唯一）
* 参数：
  * body：请求 JSON 内容

    ```json
    {
      "slug": "organization/repo",
      "description": "用于 CI/CD 的部署令牌",
      "scope": "registry-package:r",
      "metadata": {
        "environment": "production"
      }
    }
    ```

    * slug：CNB 资源路径，必须是已绑定的资源
    * description：可选，令牌描述信息
    * scope：可选，令牌的权限范围
    * metadata：可选，令牌的扩展信息
* 返回：创建成功的令牌

  ```json
  {
    "token": "dk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
  ```

  **注意：令牌只在创建时返回一次，请妥善保存**

### 删除部署令牌

* 接口地址：`/platform-token/-/deploy-keys/{openid}/{key}`
* 接口方法："DELETE"
* 系统授权：继承平台令牌的权限范围
* 功能描述：删除指定的部署令牌
* 路径参数：
  * openid：第三方平台实例唯一 ID
  * key：密钥标识
* 返回：HTTP 204 No Content

根据实际需求选择合适的接口。

## Header 信息

* `Authorization`：string 类型，HTTP 标准身份认证头部字段，使用标准 JWT 计算签名，格式为 `Bearer ${token}`。

  Go JWT 签名示例如下：

  ```go
  import (
   "fmt"
   "time"

   "github.com/golang-jwt/jwt/v5"
  )

  // Claims 认证请求所需的参数
  type Claims struct {
    JWTPayload // 用户自定义 JWT payload 结构
    jwt.RegisteredClaims
  }

  // Generate 签名编码
  func Generate(payload JWTPayload, name, secretKey string) (string, error) {
    claims := Claims{
      payload,
      jwt.RegisteredClaims{
        Issuer:   name, // 平台令牌 name
        IssuedAt: jwt.NewNumericDate(time.Now().UTC()), // 当前 UTC 时间
      },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString([]byte(secretKey))
  }
  ```

  Python JWT 签名示例如下：

  ```python
  from datetime import datetime, timezone
  import jwt

  class JWTPayload:
    """JWT payload 自定义结构"""
    pass

  def generate(payload: JWTPayload, name: str, secret_key: str) -> str:
  claims = {
      # 标准声明
      "iss": name,  # Issuer - 平台令牌 name
      "iat": datetime.now(timezone.utc),  # IssuedAt - 当前 UTC 时间

      # 可以在这里添加自定义 payload 字段
      # 如果 payload 有属性，可以通过 vars(payload) 或 payload.__dict__ 获取
  }

  token = jwt.encode(claims, secret_key, algorithm="HS256")
  return token
  ```

  Node.js JWT 签名示例如下：

  ```javascript
  // 依赖：npm install jsonwebtoken
  const jwt = require('jsonwebtoken')

  /**
   * 生成 JWT 签名
   * @param {object} payload 自定义 JWT payload 字段
   * @param {string} name 平台令牌 name
   * @param {string} secretKey 平台令牌 secret_key
   * @returns {string} 签名后的 JWT
   */
  function generate(payload, name, secretKey) {
    const claims = {
      ...payload,
      iss: name, // Issuer - 平台令牌 name
      iat: Math.floor(Date.now() / 1000), // IssuedAt - 当前 UNIX 时间戳（秒）
    }
    return jwt.sign(claims, secretKey, { algorithm: 'HS256' })
  }
  ```

  JWT 详细介绍请参考官方文档。

  将 **JWT Claims** 的 **issueAt** 字段赋值为当前 UNIX 时间戳。
  如果该时间与服务器时间相差超过 2 分钟，调用接口会返回签名过期错误。

## 接口返回

换票接口请求成功后，返回 **24 小时**有效的临时票据，可用于调用 OpenAPI 接口。

OpenAPI 接口详情请参照 [云原生构建 OpenAPI 接口文档](https://api.cnbprod.alpha.qq.com)。

## 请求示例

curl 请求示例：

```bash
curl -X POST 3rd.cnbprod.alpha.qq.com/platform-token/-/user/someone \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoiIiwic2NvcGUiO"
```

返回结果示例：

```json
{ "token": "bHaDbC6esm88116aZOGDbpH26fL" }
```
