密钥、模式、权限范围与版本——以及为什么模式由凭证决定。
每个发往 /v1 的请求都要以 Bearer 令牌的形式携带一个私密密钥:
Authorization: Bearer sk_test_...
由密钥的前缀决定使用哪一种:
| 前缀 | 模式 | 涉及的内容 | | --- | --- | --- | | sk_test_ | 测试 | 模拟链、测试数据,可使用 /v1/test/* | | sk_live_ | 正式 | 真实的链、真实的资金 | | pk_test_ / pk_live_ | 可公开 | 可以安全地在浏览器中使用。只能读取交给它的付款会话,别无其他 |
正式模式是身份的一部分,而不是请求的一部分。没有任何请求头、查询参数或请求体字段可以覆盖它。正因如此,“我刚才是不是在真金白银上操作了”这个问题,才能从系统结构上得到回答,而不必靠代码审查来回答。
未配置正式模式的部署会以 403 live_mode_disabled 拒绝正式密钥,而不是悄悄把它当作测试密钥处理——静默降级意味着真实的付款会消失在测试数据中。
pk_ 密钥按设计就是要写进页面源代码的。除了通过已经交给它们的付款会话令牌,它们什么都不能创建,也什么都不能读取。任何转移资金或披露资金信息的端点都要求使用私密密钥,否则会返回 403 insufficient_scope。
刻意保持粗粒度。只有五个,而不是五十个——五十个看起来很严谨,结果却是每个集成都持有全部五十个,因为没有人能理清自己的代码路径到底需要其中哪一部分。
| 权限范围 | 授予的权限 | | --- | --- | | payments:read | 读取付款、扣款、事件、余额和账本 | | payments:write | 创建和取消付款 | | mandates:write | 创建扣款授权并据此扣款 | | payouts:write | 转出资金——即退款 | | config:write | 链、Webhook 端点、商家设置、密钥 |
没有授予即为拒绝。如果密钥不具备它刚才尝试的操作所需的权限范围,会收到 403 insufficient_scope。
[!note] 退款权限范围实际传输的值仍然是 payouts:write。出款功能已经下线;但这个字符串没有改名,因为每个已签发的密钥都带有它,改名会悄无声息地撤销所有正式集成的这项能力。
密钥看到的响应结构固定为该密钥上的版本。如需对单个请求覆盖它:
Paygate-Version: 2026-08-23
本部署不提供的版本会以 400 unknown_api_version 被拒绝,而不会就近取一个版本——一旦就近取版本,集成就会在不知不觉中开始解析一种它从未适配过的结构。
位于 /app 的商家控制台使用 Cookie 而不是密钥进行认证。两者绝不混用:带有 Authorization 请求头的请求只依据该请求头进行判断,认证失败即返回 401。它绝不会回退到 Cookie——一旦回退,过期的 API 密钥就会在不知不觉中以恰好在该浏览器上登录的那个人的身份获得服务。