api-contractlisted
Install: claude install-skill 1398281322-a11y/java-backend-guardrails
# 接口规范
## When to Invoke
新接口、前后端联调约定、开放 API、面试「REST 怎么设计」「错误码怎么定」「金额用元还是分」。
## When NOT
验签防重放 → `api-security`。资源归属越权 → `safe-check`。支付回调报文 → `pay-notify`。幂等落库细节 → `idempotent`。
## 风险(面试考点)
**方法语义(RFC 9110):** GET/HEAD **安全且幂等**(只读、可缓存、可重试)。PUT/DELETE **幂等但不安全**。POST/PATCH **默认不幂等**。GET 写库、GET 带 body、`GET /order/create` 都是扣分项。
业务失败也返回 HTTP 200 且 `code=0`,监控当成功。或反过来所有错误都 500。401 与 403 不分:没登录 vs 没权限。404 可用来隐瞒资源存在(对越权列表也返回 404,不泄露「这个 ID 存在但不属于你」)。
金额用 `double`:对账差一分。时间无时区:报表差一天。分页用巨大 `offset`:深翻页打穿。列表 `null` 当空数组:前端 NPE。创建成功不给 `201` + `Location`,客户端无法跟资源。
版本:路径 `/v1` 或头;**不兼容变更必须新版本**,加字段可兼容。改金额单位、改枚举含义、删必填 = 不兼容。
`Idempotency-Key`(draft-ietf-httpapi):同一 key 必须返回首次结果。同一 key 不同 body → **409/422**,禁止当新单。进行中的同一 key → 409,客户端等,不要再开一单。
## 方案选型(轻量优先)
| 项 | 默认 |
|----|------|
| URL | 复数名词 `/orders/{id}`,动词在方法上 |
| 方法 | GET 查、POST 创建、PUT 全量幂等更新、PATCH 部分、DELETE 删 |
| HTTP | 2xx 成功(创建 **201**+Location;异步 **202**);400 参数;401 未登录;403 无权限;404 无资源;409 冲突/幂等处理中;422 语义无法处理;429 限流;5xx 服务器 |
| 业务码 | body 里 `code` 给业务细分;**不要**用 200 包装未登录 |
| 金额 | 整数 **分**,字段名 `amountFen`;禁止 float |
| 时间 | ISO-8601 带时区或统一 UTC;切日时区写进口径 |
| 分页 | 默认 `id` 游标;管理后台小数据可用 page;禁止 `page=10000` |
| 幂等 | 写接口要 `Idempotency-Key` 或业务号,见 `idempotent` |
| 追踪 | 每个响应 `requestId` / `traceId`;5xx **不回堆栈** |
```json
{
"code": 0,
"message": "ok",
"requestId": "…",
"data": { "amountFen": 19900, "createdAt": "2026-09-01T08:00:00+08:00" }
}
```
列表:`items: []`(空也是数组),`nextCursor`。枚举用字符串并文档化全集。字段命名全链路统一(对外 camelCase 或 s