> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clinkbill.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 云端 Agent 平台接入

> 为平台用户连接 Clink Wallet Service，使用加密支付凭证完成 Browser Pay 购买。

云端 Agent 平台为每位用户连接 Clink，代表该用户调用钱包和支付工具，并通过平台的浏览器能力完成商户结账。Browser Pay 凭证使用平台公钥加密时，按[凭证解密范例](/cn/guides/agent/browser_pay/decryption)解密。

## 准备平台连接

| 配置项 | 接入要求 |
| :- | :- |
| OAuth Client | 按 [MCP 连接与 OAuth](/cn/guides/agent/mcp_integration)选择 CIMD、预注册或 DCR。同一应用或部署复用 Client。 |
| 环境 | MCP Resource 和 OAuth 端点使用同一环境。先在 UAT 联调。 |
| Redirect URI | 登记完成用户连接的 HTTPS 回调地址。 |
| Scope | 启用下面的钱包、支付权限，以及所用工具要求的其他权限。 |
| Browser Pay 公钥 | 线下联系 Clink，为对应环境配置平台 RSA 公钥。提供内容为 X.509 SubjectPublicKeyInfo 的 PEM 公钥（`BEGIN PUBLIC KEY`）。 |

Browser Pay 流程需要以下 Scope：

```text theme={null}
wallet:read payment:execute instruction:read instruction:write events:read events:consume offline_access
```

`events:read` 与 `events:consume` 用于恢复用户操作后的流程，`offline_access` 用于取得 Refresh Token。平台需要修改用户默认卡时，还需加入 `wallet:setup`。OAuth Client 登记的 Scope 必须覆盖用户授权请求中的全部 Scope。各工具要求见[接口参考](/cn/api-reference/mcp/browser_pay)。

<Note>
  OAuth Client 注册与 Browser Pay 公钥登记是两个步骤。加密公钥通过线下联系 Clink 配置，不是 DCR 请求参数。钱包查询不需要解密支付凭证。
</Note>

## 为每位用户建立连接

按[共用 OAuth 文档](/cn/guides/agent/mcp_integration)实现 Authorization Code + PKCE（`S256`）。将授权回调关联到发起连接的用户，该用户的 MCP 请求使用其自己的 Access Token。各用户的 Token 分别维护和刷新。

OAuth 连接授予调用 Clink 工具的权限；购买授权决定 Agent 可以使用哪张支付卡、在什么额度内购买。用户完成连接不代表已授权一次购买。需要 Passkey 验证时，平台展示用户操作链接并等待完成；授权机制见 [Wallet Service：Passkey 与购买授权](/cn/guides/agent/wallet_service#passkey-与购买授权)。

[Clink Skill](https://www.clinkbill.com/SKILL.md)用于安装 Host 连接。业务操作读取已连接 MCP 服务端的 `clink://skill/rules`；无法读取资源时，调用 `get_skill_manifest` 并传入 `include_rules: true`。升级接入时遵循服务端当前规则。

## 跑通第一个钱包调用

OAuth 返回具备 `wallet:read` 权限的用户 Access Token 后，先用这个只读示例验证连接。它会发现工具并读取钱包，不会发起支付。示例使用[官方 MCP TypeScript SDK v2](https://ts.sdk.modelcontextprotocol.io/v2/clients/connect)。

<Accordion title="Node.js 范例：连接并读取钱包">
  使用 Node.js 20.19 或更新版本，在示例目录安装 Client：

  ```bash theme={null}
  npm install @modelcontextprotocol/client@2
  ```

  通过运行环境注入 `CLINK_USER_ACCESS_TOKEN`，它必须属于已连接用户及当前环境。`CLINK_MCP_URL` 可选，默认使用 UAT。将下面的代码保存为 `check-wallet.mjs`：

  ```javascript theme={null}
  import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";

  const token = process.env.CLINK_USER_ACCESS_TOKEN;
  if (!token) throw new Error("Set CLINK_USER_ACCESS_TOKEN for the connected user.");

  const client = new Client({ name: "clink-wallet-check", version: "1.0.0" });
  const transport = new StreamableHTTPClientTransport(
    new URL(process.env.CLINK_MCP_URL ?? "https://uat-api.clinkbill.com/mcp"),
    { authProvider: { token: async () => token } }
  );

  try {
    await client.connect(transport);
    const { tools } = await client.listTools();
    if (!tools.some(tool => tool.name === "get_account_state")) {
      throw new Error("get_account_state is unavailable; check the MCP environment.");
    }

    const result = await client.callTool({ name: "get_account_state", arguments: {} });
    if (result.isError) throw new Error("Wallet read failed; check the token and scopes.");
    const account = result.structuredContent;
    if (!account || !Array.isArray(account.paymentMethods)) {
      throw new Error("Unexpected wallet response.");
    }
    console.log({ connected: true, walletReadable: true, cardCount: account.paymentMethods.length });
  } finally {
    try {
      await transport.terminateSession();
    } finally {
      await client.close();
    }
  }
  ```

  ```bash theme={null}
  node check-wallet.mjs
  ```
</Accordion>

预期输出为 `connected: true`、`walletReadable: true` 以及当前 `cardCount`。数量为 `0` 表示钱包读取成功但还没有卡，不是连接失败。平台持续运行时，应接入每位用户的 Token 刷新流程；这里的固定 Token 仅用于连接验证。

## 完成一次 Browser Pay 购买

用户完成 OAuth 连接并提出购买需求后，按下面的流程完成结账。图中展示已配置平台公钥、返回加密凭证的情况。

<Tabs>
  <Tab title="支付主流程">
    已有有效购买授权覆盖本次付款时，`get_credential` 可直接返回凭证。

    ```mermaid theme={null}
    %%{init: {"theme":"base","themeVariables":{"fontFamily":"inherit","actorBkg":"#F7F7F7","actorBorder":"#E7E7E7","actorTextColor":"#161616","actorLineColor":"#E7E7E7","signalColor":"#71717A","signalTextColor":"#3F3F46","noteBkgColor":"#F8E1CC","noteBorderColor":"#F8E1CC","noteTextColor":"#161616"},"sequence":{"width":116,"height":44,"actorMargin":64,"diagramMarginX":12,"diagramMarginY":12,"messageMargin":28,"noteMargin":14,"boxMargin":12,"wrap":false,"mirrorActors":false,"actorFontSize":14,"messageFontSize":14,"noteFontSize":14}}}%%
    sequenceDiagram
      participant M as 商户网站
      participant P as Agent 平台
      participant C as Clink MCP
      P->>M: 读取最终结账金额
      M-->>P: 金额与币种
      P->>C: get_credential
      C-->>P: 加密凭证与支付标识
      Note over P: 解密并提取卡信息
      P->>M: 填卡并提交支付
      M-->>P: 实际支付结果
      P->>C: confirm_result
    ```
  </Tab>

  <Tab title="需要用户操作时">
    当 `get_credential` 返回 `REDIRECT_USER` 链接时，先完成这一流程，再回到主流程使用凭证。

    ```mermaid theme={null}
    %%{init: {"theme":"base","themeVariables":{"fontFamily":"inherit","actorBkg":"#F7F7F7","actorBorder":"#E7E7E7","actorTextColor":"#161616","actorLineColor":"#E7E7E7","signalColor":"#71717A","signalTextColor":"#3F3F46","noteBkgColor":"#F8E1CC","noteBorderColor":"#F8E1CC","noteTextColor":"#161616"},"sequence":{"width":116,"height":44,"actorMargin":64,"diagramMarginX":12,"diagramMarginY":12,"messageMargin":28,"noteMargin":14,"boxMargin":12,"wrap":false,"mirrorActors":false,"actorFontSize":14,"messageFontSize":14,"noteFontSize":14}}}%%
    sequenceDiagram
      participant U as 用户
      participant P as Agent 平台
      participant C as Clink MCP
      C-->>P: REDIRECT_USER
      P-->>U: 展示用户操作链接
      U->>C: 完成绑卡或购买授权
      P->>C: get_operation
      C-->>P: 设置操作完成
      P->>C: get_credential
      C-->>P: 凭证与支付标识
    ```

    `get_operation` 查询返回的设置 Operation。设置完成后，使用相同结账信息再次调用 `get_credential`，不传入设置 Operation ID。其他 `SETUP_REQUIRED` 情况见 [Browser Pay](/cn/guides/agent/browser_pay)。
  </Tab>
</Tabs>

平台需要衔接三个环节：

* **用户操作：** 保留结账信息与设置 Operation，展示返回的链接，读取更新后的状态再恢复流程。
* **支付凭证：** 直接使用 `credential.card`，或按[解密范例](/cn/guides/agent/browser_pay/decryption)处理 `key` 与 `payload`。提交前保留签发凭证的 Operation 及支付标识。
* **商户结果：** 操作结账浏览器，上报实际观察到的结果。金额、选卡和重试的完整规则统一见 [Browser Pay](/cn/guides/agent/browser_pay)。

<Accordion title="购买与恢复的编排示意">
  以下伪代码展示调用如何衔接。`callTool` 代表已检查 `isError` 和结构化结果的 MCP 调用。保存上下文、展示链接、解密与商户浏览器操作由平台实现，不是额外的 Clink API。

  ```text theme={null}
  checkout = { merchantUrl, merchantName, amount, currency, paymentInstrumentId? }

  if resuming a saved setup operation:
    setup = callTool("get_operation", { operationId: setupOperationId, maxWaitSeconds: 15 })
    if setup.status != "SUCCEEDED":
      follow setup.next_action, or stop if the operation failed or expired
      return

  issued = callTool("get_credential", checkout)
  if issued.credential is absent:
    save checkout and issued.operation_id for recovery
    present issued.next_action to the user; do not open USER_DEVICE_ONLY links
    return

  reportIds = {
    operationId: issued.operation_id,
    orderId: issued.resources.payment_order_id,
    paymentExecutionDetailId: issued.resources.payment_execution_detail_id
  }
  save reportIds before filling the merchant form
  card = issued.credential.card, or decrypt issued.credential.key + payload
  if decryption fails or the final total changes:
    callTool("confirm_result", { ...reportIds, outcome: "NOT_SUBMITTED" })
    stop before submission

  fill the card fields, submit once, and inspect the merchant result
  outcome = "SUCCEEDED" | "FAILED" | "UNKNOWN", based on what was observed
  save the report arguments for retry
  callTool("confirm_result", { ...reportIds, outcome })
  if reporting fails: retry the saved report; do not submit payment again
  if outcome is "UNKNOWN": reconcile the existing payment before report_deadline
  ```

  结账信息来自商户最终结账页：`amount` 使用最小货币单位；仅在用户指定卡时传入 `paymentInstrumentId`。设置响应未提供用户链接时，按 [Browser Pay](/cn/guides/agent/browser_pay)处理返回的操作。设置完成后保留相同结账信息和选定卡，不向 `get_credential` 传入设置 Operation ID。

  支付标识从 `resources` 或凭证负载的对应字段读取；无法读取时，先从签发凭证的 Operation 恢复标识再继续。商户确认实付金额时，同时上报 `paidAmount` 与 `currency`。完整结构和上报参数见[响应范例](/cn/api-reference/mcp/browser_pay)。
</Accordion>

Clink 提供钱包、购买授权、支付凭证和结果上报工具。需要区分以下三个完成点：

| 完成步骤 | 能证明什么 |
| :- | :- |
| 凭证已发放 | Clink 已为本次结账提供凭证，不代表商户已收款。 |
| 商户已确认付款 | 商户页面明确显示付款成功；保留实际观察到的商户订单号。 |
| 结果已记录 | Clink 接受了平台的上报，不代表商户独立确认。 |

## 保留支付上下文

| 数据 | 用途 |
| :- | :- |
| `operation_id` | 标识 Clink Operation，用于恢复流程以及 `confirm_result.operationId`。 |
| 原结账信息 | 在最终结果上报前继续同一次结账；用户指定卡时保留对应 `paymentInstrumentId`。 |
| `orderId` 与 `paymentExecutionDetailId` | 上报结果时标识凭证所属订单。从解密负载或对应的 `resources` 字段取得。 |
| `next_action` 与当前 revision | 判断应跳转用户、等待，还是执行指定的下一步；操作已过时时先读取最新 Operation。 |

`UNKNOWN` 表示已经提交支付，但无法观察结果。沿用同一支付上下文核实，并在返回的 `report_deadline` 前上报最终结果，不要立即发起另一笔支付。详见 [Operation 恢复](/cn/api-reference/mcp/operations)与 [Browser Pay 接口](/cn/api-reference/mcp/browser_pay)。

## 联调验证

上线前，在已配置的环境验证以下场景：

* 两位用户连接同一个 OAuth Client，各自只能看到自己的钱包和 Operation。
* 已有有效购买授权时能够取得凭证；缺少授权时返回用户操作，并能在操作完成后继续。
* 使用已登记平台公钥加密的响应能按范例解密，并得到商户表单可用的支付字段。
* 成功、失败、未提交和结果未知四种情况使用正确关联标识上报。
* 用户授权返回或请求超时恢复后，能够继续原 Operation，不会盲目再次提交支付。

完整购买流程见 [Browser Pay](/cn/guides/agent/browser_pay)。支付卡选择和购买授权管理见 [Wallet Service](/cn/guides/agent/wallet_service)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.