POST
/v1/connect/token
换取访问令牌
Scope
—
商户自身
两段式的第一段。这是整条链上唯一不带 x-auth-token 的端点,
也是唯一不需要 scope 的。
三件与常见实现不同、写错了会当天返工的事:
- 多令牌可并存。 新换一把不会让旧的失效 —— 多进程的接入方不必
担心两个 worker 互相把对方踢下线。所以请缓存令牌复用到过期前,
而不是每次调用都换一把。
- 签发限流 20 次/分钟/client_id,超了回
rate_limited。
高频换取本身就是接入错误的信号。
- 令牌里那份
scopes只作提示。 判定用的是每请求实时读的
Key 行 —— 后台改 scope / 停用 Key 即时生效,不必等令牌过期。
scopes 出参是展开后的集合:勾了 members:write 会同时看到
members:read。展开发生在判定时而不是入库时,所以规则日后收紧,
存量 Key 会跟着变。
跨环境凭据一律拒,且明确回 environment_mismatch 而不是
「凭据无效」—— 上游同类接口在这里回的是 Invalid client id,
接入方普遍误判成「密钥抄错了」。沙盒 Key 解析到的是一个**影子商户
主体**,与 live 是两批数据:在沙盒里建的会员、记的账,live 上一条都没有。
轮换有重叠窗口:旧密钥在 prev_valid_until 之前仍可换取令牌,
你可以从容换完再让它自然失效。⚠ 那是硬边界不是提醒 ——
过点即刻失效,不留宽限。
前置条件
- API Key 状态为 active 且未过
expires_at - Key 的环境与你打的主机名一致(
api-sandbox.*对沙盒 Key) - live 环境的 Key 必须配了 IP 白名单,且本次出口 IP 命中
请求头
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
x-client-id |
string | 必填 | API Key 的 client_id(商户后台创建 Key 时下发) |
x-api-key |
string | 必填 | API Key 的密钥。⚠ 它不是验签用的那把。 一把 Key 下发两个值:
api_key 只在这里用(我方只存哈希),signing_key 用于
x-signature。拿错了的表现是签名恒不匹配。 |
响应
200已签发
{
"auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expired_at": 1786000800,
"token_type": "Bearer",
"scopes": [
{
"members": "read"
},
{
"members": "write"
},
{
"merchant": "read"
}
]
}400
environment_mismatch 沙盒凭据打在了 live 主机上(或反过来)401
invalid_credentials —— 五种情况同一个响应:头缺失 ·
client_id 不存在 · Key 已停用 · Key 已过期 · 密钥不匹配。
区分开就等于给了一个 client_id 探测接口。429
rate_limited 每个 client_id 每分钟 20 次
调用样例
curl -X POST 'https://api.zise.com/v1/connect/token' \
-H 'authorization: Bearer $TOKEN' \
-H 'x-zise-merchant: $MERCHANT_ID'
const res = await fetch(
"https://api.zise.com/v1/connect/token",
{
method: "POST",
headers: {
"authorization": "Bearer $TOKEN",
"x-zise-merchant": "MERCHANT_ID"
},
},
);
// 金额一律按字符串读,不要 JSON.parse 成 number
const data = await res.json();
import requests
res = requests.post(
"https://api.zise.com/v1/connect/token",
headers={
"authorization": "Bearer $TOKEN",
"x-zise-merchant": "$MERCHANT_ID"
},
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()