本教程使用 Sandbox UAT 示例。请先按如何获取平台凭据向 Clink 申请平台
client_id 和 client_secret。示例中的邮箱、用户 ID 和 Token 都是占位值。1. 准备环境和平台凭据
Clink 为每个环境分别配置凭据。不要混用 Sandbox UAT 和 Production 的 Token、用户连接、支付方式或卡关联。
RESTful API 使用 Pre-registration 签发的平台
client_id 和 client_secret,与 MCP 共用同一个平台 client。申请方式、Clink 登记的内容和 RSA 公钥见如何获取平台凭据。开通时要登记首次用户授权使用的 redirect_uri,以及 Portal Scope portal:read portal:write。
除平台凭据外,后端还要保存 CLINK_API_BASE_URL。用户 Token、解密后的卡字段和支付凭证只能保存在可信服务端,不要放进浏览器代码、URL、日志、Agent 输入或普通业务消息。
2. 获取平台 Token
使用平台凭据调用 OAuth token endpoint。平台 Token 只用于服务端管理用户连接和换取 Portal Token,不能直接调用用户 Portal API,也不能代替用户授权。expires_in 缓存平台 Token,到期后重新获取。
3. 为用户获取 Portal Token
Customer Portal API 使用代表单个 Clink 用户的 Portal Token。先在你的系统中验证用户邮箱,并将 Clink 用户与稳定的平台用户 ID 关联。 新用户,或已在当前平台有有效授权的用户,只需要email。已有 Clink 用户第一次授权当前平台时,还需要重定向和 PKCE 字段。建议每次请求前都生成随机 state 和 PKCE code_verifier,计算 S256 code_challenge,并将它们临时绑定到平台用户:
已授权用户
如果用户是新用户,或已经为当前平台完成授权,接口会返回 Portal Token:customer_id。调用 Customer Portal API 时使用:
需要用户授权
如果 Clink 找到了用户,但当前平台还没有有效的授权连接,响应会是:authorization_url 原样交给对应用户。用户完成 OAuth 回调后,确认 state 属于发起请求的平台用户并校验 iss,再重新调用 Portal Token 接口取得 Token。不要跳过授权、修改授权 URL,也不要把授权链接交给模型改写。用户取消或拒绝授权时,重新发起一次授权请求。
Portal Token 只访问当前用户的数据。它不能调用 /mcp;MCP 用户 Token 也不能调用 /agent/platform/**。
Token 过期和重新获取
Portal Token 只有 access token,没有 refresh token。过期后,用平台 Token 重新调用 Portal Token 接口换取;如果当前平台对该用户的授权已失效,接口会再次返回authorization_required。平台 Token 始终是获取用户 Token 的权限来源,只能保存在服务端。
4. 在服务端持久化用户 Token
Portal Token 是代表单个用户的服务端凭据。获取或刷新后,平台必须按平台用户和环境加密持久化保存 Token、过期时间、customer_id 和已授予的 Scope;不要只保存在当前请求或 Agent 进程内存中。
- 使用平台自己的稳定用户 ID 作为主键,不要用邮箱作为主键,也不要跨用户或环境复用 Token。
- 调用 Portal API 前从服务端安全存储读取 Token,并检查
expires_in;过期后用平台 Token 重新换取。Portal Token 没有 refresh token。 - Token 刷新或重新换取时原子更新存储,避免并发请求覆盖新 Token。授权失效时删除本地失效 Token,重新引导用户完成授权。
- Token 只能在可信服务端使用,不要写入浏览器代码、URL、日志、Agent 输入、普通业务消息或客户端存储。
5. 读取账户和支付方式
使用 Portal Token 验证当前用户状态:url 原样展示给用户,并把它当作凭证处理:不要转发、截图或写入日志。用户完成 Clink 托管页面后,再重新读取支付方式。绑卡会话不创建购买授权;如果要一次完成绑卡和授权,见下一步的“绑卡并签约”。不要在平台页面收集真实卡号或 CVV。
6. 创建购买授权
Browser Pay 需要先有适用于本次购买的、已激活的购买授权(指令)。payment_instrument_id 决定签约模式:
instruction_id、status、activation_url 和 activation_expires_at。激活步骤:
- 把
activation_url只发给目标用户,在用户自己的浏览器中打开。它是激活链接,不是 Portal Token,但拿到链接的人可以在有效期内取得该用户的 Clink 浏览器登录态,不要转发、截图或写入日志。 - 轮询
GET /agent/platform/authorizations/{instructionId},直到status为ACTIVE。 - 从指令中读取覆盖本次购买的
mandate_id,下一步获取凭证时使用。
CREATED 或 PENDING,不会授权任何消费。request_id 是幂等键:24 小时内用完全一致的参数重试会返回同一条指令;同一 request_id 携带不同参数返回 409。完整字段见 Portal 接口参考。
需要查看当前用户的授权时:
7. 使用 Browser Pay 获取支付凭证
商户浏览器应先读取最终结账页的金额、币种、商户信息和订单标识。平台后端再使用已激活指令的instruction_id、覆盖本次购买的 mandate_id 和这些真实结账信息,请求一次性支付凭证。
Browser Pay 的凭证接口属于 Portal API:
amount 使用主货币单位的十进制字符串,merchant_url 必须是 HTTPS 结账页地址。client_reference_id 是本次购买的幂等键:请保存它,回报结果时使用同一个值;相同参数重试会返回同一凭证,不会重复签发。商品明细 products 和收货地址 shipping_address 等可选字段见 Portal 接口参考。
响应模式取决于平台是否在 Clink 登记了公钥:
解密后或明文返回的卡字段只在受控的结账执行器中短暂使用,不要写入日志、数据库、模型上下文或浏览器 local storage,也不要在结账后保留。以解密后 payload 中的有效期为准判断凭证可用时间,
expires_at 只是估算。凭证响应超时时,用同一个 client_reference_id 重试取回原凭证,不要重新创建授权。
8. 在商户页面完成支付
你的浏览器执行器负责:- 打开商户结账页并读取最终金额、币种和商户信息。
- 确认这些信息与购买授权和支付凭证的请求完全一致。
- 在受信任的支付填充组件中使用凭证,不让模型或普通日志看到真实卡字段。
- 提交商户订单并读取商户页面或订单接口的最终结果。
- 在结果明确后调用支付结果接口。
9. 确认支付结果
确认商户结果后,用同一个client_reference_id 回报结果。这是确认交易结果的唯一入口:
回报规则:
- 最终结果需要在凭证签发后 24 小时内(
report_deadline之前)回报,超时返回410。 FAILED和NOT_SUBMITTED时可以带failure_reason,例如CARD_DECLINED、AMOUNT_CHANGED或BUYER_CANCELLED。paid_amount和currency_code必须成对出现;与授权金额不一致时,响应返回paid_amount_mismatch: true。- 已记录成功后再回报失败(或反过来)返回
409(result_already_reported)。
相关文档
- 如何获取平台凭据:申请
client_id和client_secret,以及三种注册方式。 - Agent Portal 总览:能力边界、Token 类型和 API 列表。
- Portal token:换取用户 Portal Token 的请求、响应和授权状态。
- Portal 接口:账户、支付方式、购买授权、凭证、结果、订单和设置接口。
- Browser Pay 指南:商户浏览器结账、凭证保护和结果恢复。
- 加密凭证解密:解密
key/payload的示例。 - 如何对接 MCP:通过 MCP + OAuth 接入 Browser Pay。
- 如何对接 Vault SDK:Agent 只接触占位卡的 SDK 接入方式。