错误代码 (Error Codes)
ZTDX API 使用标准的 HTTP 状态码和自定义错误代码来指示请求的成功或失败状态。
HTTP 状态码
| 状态码 | 说明 | 常见原因 |
|---|---|---|
| 200 | OK | 请求成功 |
| 400 | Bad Request | 参数错误、业务逻辑违规 |
| 401 | Unauthorized | 未授权、JWT过期、签名验证失败 |
| 403 | Forbidden | 无权访问该资源 |
| 404 | Not Found | 资源不存在 |
| 429 | Too Many Requests | 触发频率限制 |
| 500 | Internal Server Error | 服务器内部错误 |
| 503 | Service Unavailable | 服务暂时不可用(维护中) |
错误响应格式
所有错误都以统一的 JSON 格式返回:
{
"error": "余额不足,需要 653.25 USDT 作为保证金",
"code": "INSUFFICIENT_BALANCE",
"details": {
"required": "653.25",
"available": "500.00",
"token": "USDT"
}
}
字段说明
| 字段 | 类型 | 描述 |
|---|---|---|
| error | string | 人类可读的错误描述 |
| code | string | 错误代码(UPPER_SNAKE_CASE) |
| details | object | 可选的错误详情 |
认证相关错误
INVALID_SIGNATURE_FORMAT
HTTP状态码: 400
描述: 签名格式无效
原因:
- 签名不是有效的十六进制字符串
- 签名长度不正确
- 缺少
0x前缀(如果需要)
解决方案:
// ✅ 正确
signature: "0xabcdef123456..." // 0x开头,130个字符
// ❌ 错误
signature: "abcdef123456..." // 缺 少0x
signature: "0x123" // 长度不足
SIGNATURE_INVALID
HTTP状态码: 401
描述: EIP-712 签名验证失败
原因:
- 签名使用了错误的私钥
- TypedData 结构不匹配
- Domain 配置不正确
- Timestamp 不匹配
解决方案:
// 检查 Domain
const domain = {
name: "ZTDX",
version: "1",
chainId: 421614, // 确保正确
verifyingContract: vaultAddress // 确保正确
};
// 检查 Timestamp
const timestamp = Math.floor(Date.now() / 1000); // 秒级
TIMESTAMP_EXPIRED
HTTP状态码: 400
描述: 时间戳已过期(超过5分钟)
解决方案:
// 始终使用最新的时间戳
const timestamp = Math.floor(Date.now() / 1000);
NONCE_INVALID
HTTP状态码: 400
描述: Nonce 无效或已使用
解决方案:
// 重新获取 nonce
const { nonce } = await fetch(`/api/v1/auth/nonce/${address}`).then(r => r.json());
TOKEN_EXPIRED
HTTP状态码: 401
描述: JWT Token 已过期
解决方案:
// 重新登录获取新 token
await login(address, signature, timestamp);
TOKEN_INVALID
HTTP状态码: 401
描述: JWT Token 无效或格式错误
解决方案:
// 确保 token 格式正确
headers: {
'Authorization': `Bearer ${token}` // 注意 Bearer 前缀
}
订单相关错误
INSUFFICIENT_BALANCE
HTTP状态码: 400
描述: 可用余额不足
详情:
{
"error": "余额不足,需要 653.25 USDT 作为保证金",
"code": "INSUFFICIENT_BALANCE",
"details": {
"required": "653.25",
"available": "500.00"
}
}
解决方案:
- 充值更多资金
- 降低订单数量
- 增加杠杆倍数(谨慎)
INVALID_SYMBOL
HTTP状态码: 400
描述: 不支持的交易对
解决方案:
// 查询支持的交易对
const markets = await fetch('/api/v1/markets').then(r => r.json());
INVALID_LEVERAGE
HTTP状态码: 400
描述: 杠杆倍数超出范围(1-50)
解决方案:
// 确保杠杆在有效范围内
const leverage = Math.min(Math.max(userLeverage, 1), 50);
INVALID_AMOUNT
HTTP状态码: 400
描述: 订单数量无效
原因:
- 数量 <= 0
- 数量小于最小订单量
- 数量超过最大订单量
解决方案:
// 检查市场配置
const market = await getMarket('BTCUSDT');
if (amount < parseFloat(market.min_order_size)) {
throw new Error('数量小于最小订单量');
}
PRICE_REQUIRED
HTTP状态码: 400
描述: 限价单必须指定价格
解决方案:
// 限价单必须有价格
{
order_type: "limit",
price: "65000.00" // 必填
}
// 市价单不需要价格
{
order_type: "market"
// price 不填或填null
}
ORDER_NOT_FOUND
HTTP状态码: 404
描述: 订单不存在
原因:
- 订单ID错误
- 订单已被删除
ORDER_NOT_CANCELLABLE
HTTP状态码: 400
描述: 订单状态不允许取消
原因:
- 订单已完全成交(
filled) - 订单已取消(
cancelled) - 订单已拒绝(
rejected)
解决方案:
// 检查订单状态
const order = await getOrder(orderId);
if (['open', 'pending', 'partially_filled'].includes(order.status)) {
await cancelOrder(orderId);
} else {
console.log('订单不可取消');
}
ORDER_NOT_OWNED
HTTP状态码: 403
描述: 无权操作此订单(不属于当前用户)
仓位相关错误
POSITION_NOT_FOUND
HTTP状态码: 404
描述: 仓位不存在
POSITION_NOT_OWNED
HTTP状态码: 403
描述: 无权操作此仓位
INSUFFICIENT_COLLATERAL
HTTP状态码: 400
描述: 减少保证金后,剩余保证金不足
解决方案:
// 检查清算状态
const liq = await getLiquidationStatus(positionId);
const maxRemovable = position.collateral - liq.min_collateral_usd;
LIQUIDATION_RISK
HTTP状态码: 400
描述: 操作后健康系数过低,接近清算
解决方案:
- 减少移除的保证金数量
- 先增加保证金再操作
触发订单相关错误
INVALID_TRIGGER_PRICE
HTTP状态码: 400
描述: 触发价格无效
原因:
- 多仓的止盈价格 <= 当前价格
- 多仓的止损价格 >= 当前价格
- 空仓的止盈价格 >= 当前价格
- 空仓的止损价格 <= 当前价格
解决方案:
// 多仓
if (position.side === 'long') {
takeProfitPrice > markPrice; // ✅
stopLossPrice < markPrice; // ✅
}
// 空仓
if (position.side === 'short') {
takeProfitPrice < markPrice; // ✅
stopLossPrice > markPrice; // ✅
}
TRIGGER_ORDER_NOT_FOUND
HTTP状态码: 404
描述: 触发订单不存在
TRIGGER_ORDER_NOT_CANCELLABLE
HTTP状态码: 400
描述: 触发订单不可取消(已触发或已取消)
推荐相关错误
CODE_ALREADY_EXISTS
HTTP状态码: 409
描述: 用户已有推荐码
解决方案:
// 查询现有推荐码
const dashboard = await get('/api/v1/referral/dashboard');
console.log('您的推荐码:', dashboard.referral_code);
CODE_NOT_FOUND
HTTP状态码: 404
描述: 推荐码不存在
ALREADY_BOUND
HTTP状态码: 409
描述: 已绑定推荐人,不可更改
SELF_REFERRAL
HTTP状态码: 400
描述: 不能使用自己的推荐码
NO_PENDING_EARNINGS
HTTP状态码: 400
描述: 没有待领取的佣金
BELOW_MINIMUM
HTTP状态码: 400
描述: 低于最低领取金额(10 USDT)
充值提现相关错误
INVALID_TOKEN
HTTP状态码: 400
描述: 不支持的代币
解决方案:
// 当前仅支持 USDT
const supportedTokens = ['USDT'];
INVALID_AMOUNT
HTTP状态码: 400
描述: 金额无效(< 最小金额或 > 最大金额)
最小金额:
- 充值: 10 USDT
- 提现: 10 USDT
WITHDRAW_NOT_FOUND
HTTP状态码: 404
描述: 提现记录不存在
WITHDRAW_NOT_CANCELLABLE
HTTP状态码: 400
描述: 提现不可取消(已确认或已完成)
可取消状态: pending
不可取消: processing, completed, failed, cancelled
系统相关错误
DATABASE_ERROR
HTTP状态码: 500
描述: 数据库错误
解决方案: 稍后重试
MATCHING_ERROR
HTTP状态码: 500
描述: 撮合引擎错误
解决方案: 稍后重试
RATE_LIMIT_EXCEEDED
HTTP状态码: 429
描述: 超过频率限制
限制:
- 公开接口: 100次/分钟
- 私有接口: 60次/分钟
- 订单操作: 20次/秒
解决方案:
// 实现指数退避重试
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.code === 'RATE_LIMIT_EXCEEDED' && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}
SERVICE_UNAVAILABLE
HTTP状态码: 503
描述: 服务暂时不可用(维护中)
解决方案: 等待服务恢复,关注公告
错误处理最佳实践
1. 统一错误处理
class ZTDXAPIError extends Error {
constructor(response) {
super(response.error);
this.code = response.code;
this.details = response.details;
this.name = 'ZTDXAPIError';
}
}
async function apiCall(url, options) {
const response = await fetch(url, options);
const data = await response.json();
if (!response.ok) {
throw new ZTDXAPIError(data);
}
return data;
}
// 使用
try {
const order = await apiCall('/api/v1/orders', {
method: 'POST',
body: JSON.stringify(orderData)
});
} catch (error) {
if (error instanceof ZTDXAPIError) {
console.error('API错误:', error.code, error.message);
console.error('详情:', error.details);
} else {
console.error('网络错误:', error);
}
}
2. 特定错误处理
async function createOrderWithErrorHandling(orderData) {
try {
return await createOrder(orderData);
} catch (error) {
switch (error.code) {
case 'INSUFFICIENT_BALANCE':
alert('余额不足,请先充值');
navigateTo('/deposit');
break;
case 'TIMESTAMP_EXPIRED':
// 自动重试
console.log('时间戳过期,重试中...');
orderData.timestamp = Math.floor(Date.now() / 1000);
return createOrderWithErrorHandling(orderData);
case 'SIGNATURE_INVALID':
alert('签名验证失败,请重新登录');
logout();
break;
case 'INVALID_LEVERAGE':
alert(`杠杆倍数必须在 1-${error.details.max_leverage} 之间`);
break;
default:
alert(`创建订单失败: ${error.message}`);
}
throw error;
}
}
3. 用户友好的错误提示
const errorMessages = {
'INSUFFICIENT_BALANCE': '余额不足,请先充值',
'INVALID_SYMBOL': '不支持此交易对',
'TIMESTAMP_EXPIRED': '请求超时,请重试',
'SIGNATURE_INVALID': '签名验证失败,请重新登录',
'ORDER_NOT_FOUND': '订单不存在',
'RATE_LIMIT_EXCEEDED': '请求过于频繁,请稍后再试'
};
function showError(error) {
const message = errorMessages[error.code] || error.message || '未知错误';
toast.error(message);
}
4. 日志记录
function logError(error, context) {
console.error('[ZTDX API Error]', {
code: error.code,
message: error.message,
details: error.details,
context,
timestamp: new Date().toISOString(),
userAgent: navigator.userAgent
});
// 发送到日志服务
logService.error({
source: 'ztdx-api',
error: error.code,
message: error.message,
context
});
}