速率限制
为确保系统稳定性和公平使用,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
- 预期请求量(峰值 + 平均)
- 业务场景描述