跳到主要内容

速率限制

为确保系统稳定性和公平使用,LawPay168 API 对请求频率有限制。

速率限制规则

限制时间窗口
60 请求 / 分钟 / 商户60 秒滚动窗口

计数基于 Merchant ID,未鉴权请求按 IP 计数。

速率限制头

每个 API 响应都包含:

Header描述
X-RateLimit-Limit当前窗口内允许的请求数
X-RateLimit-Remaining当前窗口内剩余可用请求数
X-RateLimit-Reset重置时间(毫秒级 epoch,注意是毫秒不是秒)

示例:

HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 55
X-RateLimit-Reset: 1735661247312
Content-Type: application/json

超过限制

超过限制时返回 429 Too Many Requests

{
"success": false,
"error": {
"code": 1300,
"message": "Rate limit exceeded. Please try again later.",
"details": {
"limit": 100,
"windowMs": 60000,
"resetTime": 1735661247312
},
"timestamp": "2026-01-15T10:30:00.123Z"
},
"meta": {
"timestamp": "2026-01-15T10:30:00.123Z"
}
}

error.details.resetTime 与响应头 X-RateLimit-Reset 一致。客户端应等到该时间点再重试。

最佳实践

1. 处理 429

async function apiRequest(path, options) {
const response = await fetch(`https://${API_HOST}${path}`, options);

if (response.status === 429) {
const body = await response.json();
const resetTime = body.error?.details?.resetTime ||
Number(response.headers.get('X-RateLimit-Reset'));
const waitMs = Math.max(0, resetTime - Date.now()) + 100;
await new Promise(r => setTimeout(r, waitMs));
return apiRequest(path, options);
}

return response.json();
}

2. 指数退避重试

async function fetchWithRetry(path, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(`https://${API_HOST}${path}`, options);

if (response.status === 429) {
const body = await response.json();
const baseWait = Math.max(0,
(body.error?.details?.resetTime || Date.now() + 1000) - Date.now()
);
// 失败指数加抖动:2^attempt * baseWait + 0..500ms
const waitMs = Math.pow(2, attempt) * baseWait + Math.random() * 500;
await new Promise(r => setTimeout(r, waitMs));
continue;
}

if (response.ok) return await response.json();
throw new Error(`HTTP ${response.status}`);
}
throw new Error('exhausted retries');
}

3. 客户端令牌桶

如果你的工作负载经常爆发,建议在客户端做速率整形(例如 90 req/min 留 10% 余量):

class TokenBucket {
constructor(ratePerMinute = 90) {
this.capacity = ratePerMinute;
this.tokens = ratePerMinute;
this.refillIntervalMs = 60_000 / ratePerMinute;
setInterval(() => {
this.tokens = Math.min(this.capacity, this.tokens + 1);
}, this.refillIntervalMs);
}
async take() {
while (this.tokens <= 0) {
await new Promise(r => setTimeout(r, this.refillIntervalMs));
}
this.tokens--;
}
}

提高限额

如需更高的速率限制,请联系 LawPay168 团队,并附上:

  • 商户 ID
  • 预期请求量(峰值 + 平均)
  • 业务场景描述

下一步