# 错误码

HTTP 状态码、BACEN 错误码和应用特定错误响应的参考。

## 前提条件

- 了解 RFC 7807 Problem Details 格式
- 熟悉 BACEN PIX 错误码体系

## 错误响应格式

所有错误遵循 RFC 7807（`application/problem+json`）：

```json
{
  "type": "https://api.fluxiq.com/errors/validation-error",
  "title": "Validation Error",
  "status": 422,
  "detail": "The field 'amount' must be a positive integer in centavos",
  "instance": "/api/v1/transactions",
  "errors": [
    {
      "field": "amount",
      "message": "must be a positive integer"
    }
  ]
}
```

## HTTP 状态码

| 状态 | 含义 | 常见原因 |
|------|------|----------|
| 200 | 成功 | 请求成功 |
| 201 | 已创建 | 资源已创建 |
| 400 | 错误请求 | 无效请求体、缺少字段 |
| 401 | 未授权 | 无效/过期/已列入黑名单的 Token |
| 403 | 禁止 | RBAC 权限拒绝 |
| 404 | 未找到 | 资源不存在 |
| 409 | 冲突 | 重复资源（幂等性） |
| 422 | 无法处理 | 验证错误 |
| 429 | 请求过多 | 超过速率限制 |
| 500 | 服务器内部错误 | 意外的服务器错误 |
| 503 | 服务不可用 | 断路器打开 |

## BACEN 错误码

迁移期间种子化了 161 个 BACEN 错误码。常见错误码：

### DICT 错误

| 代码 | 描述 | HTTP 状态 |
|------|------|-----------|
| AB03 | 无效账户 | 400 |
| AB09 | 账户未找到 | 404 |
| AC03 | 无效收款方账户 | 400 |
| AC06 | 账户已冻结 | 422 |
| BE01 | 与终端客户不一致 | 400 |
| DT02 | 无效日期/时间 | 400 |
| ED05 | 清算失败 | 500 |
| FF07 | 无效用途 | 400 |
| RC09 | 无效文件格式 | 400 |
| RUTA | 路由未找到 | 404 |

### SPI 错误

| 代码 | 描述 | HTTP 状态 |
|------|------|-----------|
| AB03 | 账户已冻结 | 422 |
| AB09 | 无效账号 | 400 |
| AC03 | 无效收款方账户 | 400 |
| AC06 | 账户已关闭 | 422 |
| AG03 | 不支持的交易 | 400 |
| AM02 | 金额超过限额 | 422 |
| AM09 | 无效金额 | 400 |
| BE01 | 终端客户不一致 | 400 |
| DS04 | 订单被拒绝 | 422 |
| RC01 | 银行标识符不正确 | 400 |
| RR04 | 监管原因 | 422 |

## 应用错误

### 认证

| 错误 | 状态 | 详情 |
|------|------|------|
| `invalid_credentials` | 401 | 用户名或密码不正确 |
| `account_blocked` | 401 | 10 次失败尝试后账户已锁定 |
| `account_inactive` | 401 | 管理员已停用账户 |
| `token_expired` | 401 | JWT Token 已过期 |
| `token_blacklisted` | 401 | Token 在注销时已撤销 |
| `mfa_required` | 401 | 需要 MFA 验证 |
| `invalid_mfa_code` | 401 | TOTP 代码不正确 |
| `rate_limited` | 429 | 登录尝试过多（10次/15分钟） |

### 授权

| 错误 | 状态 | 详情 |
|------|------|------|
| `permission_denied` | 403 | 用户缺少所需权限 |
| `invalid_target_system` | 403 | SSO Token target_system 不匹配 |

### 交易

| 错误 | 状态 | 详情 |
|------|------|------|
| `duplicate_e2e_id` | 409 | 端到端 ID 已存在 |
| `insufficient_balance` | 422 | 清算余额不足 |
| `invalid_amount` | 422 | 金额必须为正整数（分） |
| `invalid_key` | 404 | PIX 密钥在 DICT 中未找到 |
| `idempotency_conflict` | 409 | 相同幂等性键但不同请求体 |

### 基础设施

| 错误 | 状态 | 详情 |
|------|------|------|
| `circuit_open` | 503 | 断路器已打开 |
| `service_unavailable` | 503 | 下游服务不可达 |
| `nats_publish_failed` | 500 | 发布 NATS 消息失败 |
| `db_connection_failed` | 500 | 数据库连接错误 |

## 错误查询

`Shared.Bacen.ErrorLookup` 提供运行时错误码解析：

```elixir
# 按 BACEN 代码查询
ErrorLookup.get_error("AB03")
# => %{code: "AB03", description: "Account blocked", category: "account"}
```

查询表缓存在 ETS 中，10 分钟刷新间隔。

## 预期结果

查阅本参考后：

- 了解 RFC 7807 错误响应格式
- 了解常见 BACEN 错误码及其含义
- 了解认证、交易和基础设施的应用特定错误码
