3. API 设计原则:RESTful 设计规范、资源命名、HTTP 方法选择、状态码定义
在支付风控评分通道的 API 设计中,遵循统一的 RESTful 设计规范是保障接口可维护性、可扩展性与团队协作效率的基石。本节将围绕资源命名、HTTP 方法选择与状态码定义三个核心维度展开,确保 API 设计既符合行业标准,又能精准表达风控业务语义。
3.1 RESTful 设计核心规范
REST(Representational State Transfer)是一种基于资源的架构风格。在风控评分通道中,我们将每一次评分请求、规则配置、模型版本、策略集均视为“资源”,通过统一的接口对资源进行增删改查操作。核心规范包括:
- 无状态性:每次请求包含所有必要信息(如商户 ID、签名、时间戳),服务端不保存客户端会话状态。
- 统一接口:使用标准 HTTP 方法操作资源,通过 URI 定位资源,通过请求体/查询参数传递业务数据。
- 资源导向:URI 只表示资源,不表示动作。例如
/v1/score/orders表示订单评分资源,而非/v1/score/doScoring。 - 版本管理:在 URI 中显式携带版本号(如
/v1/、/v2/),避免向后兼容问题。
设计原则速查: 资源 URI 使用名词复数形式,禁止动词;层级关系用斜杠表示;查询参数用于过滤与排序,不用于资源标识。
3.2 资源命名规范
资源命名直接影响 API 的可读性与一致性。支付风控评分通道的资源命名遵循以下规则:
| 资源类别 | 命名示例 | 说明 |
|---|---|---|
| 评分订单 | /v1/score/orders |
表示所有评分订单的集合 |
| 单笔评分订单 | /v1/score/orders/{order_id} |
通过唯一标识定位单个订单 |
| 规则配置 | /v1/rules |
风控规则集合资源 |
| 单条规则 | /v1/rules/{rule_id} |
通过规则 ID 定位 |
| 模型版本 | /v1/models |
评分模型版本集合 |
| 策略集 | /v1/strategies |
评分策略组合集合 |
| 评分结果明细 | /v1/score/orders/{order_id}/details |
子资源,表示某订单的评分明细 |
命名避坑: 避免使用下划线(
_)或驼峰命名,推荐全小写加连字符(-)。例如使用 risk-level 而非 riskLevel 或 risk_level。
3.3 HTTP 方法选择
每个 HTTP 方法对应一种标准操作。在风控评分通道中,方法选择必须严格遵循语义,避免滥用 POST 或 GET 执行非预期操作。
| HTTP 方法 | 操作语义 | 风控评分通道典型场景 | 请求体 | 响应体 |
|---|---|---|---|---|
| GET | 查询资源 | 查询评分订单列表、查询单笔评分结果、查询规则详情 | 无 | 资源表示 |
| POST | 创建资源 | 提交评分请求、创建新规则、注册新模型版本 | 创建所需数据 | 新资源表示 + 201 |
| PUT | 全量更新资源 | 更新规则全部字段、替换策略集配置 | 完整资源数据 | 更新后资源表示 |
| PATCH | 部分更新资源 | 修改规则状态(启用/禁用)、更新模型版本描述 | 部分字段数据 | 更新后资源表示 |
| DELETE | 删除资源 | 删除废弃规则、移除测试模型版本 | 无 | 204 无内容 |
重要约束: 评分请求(
POST /v1/score/orders)是幂等性敏感操作。若业务要求幂等,应在请求头中携带 Idempotency-Key,服务端根据该键去重,避免重复扣分或重复风控判定。
3.4 状态码定义
状态码是 API 响应语义的第一道关口。风控评分通道必须覆盖成功、客户端错误、服务端错误三大类,并针对风控业务扩展特定状态码。
3.4.1 成功状态码
| 状态码 | 含义 | 使用场景 |
|---|---|---|
| 200 OK | 请求成功 | GET 查询成功、PUT/PATCH 更新成功 |
| 201 Created | 资源创建成功 | POST 创建评分订单、创建规则成功 |
| 204 No Content | 操作成功,无返回体 | DELETE 删除成功、部分异步操作确认 |
3.4.2 客户端错误状态码
| 状态码 | 含义 | 风控业务典型场景 |
|---|---|---|
| 400 Bad Request | 请求参数错误 | 缺少必填字段、字段格式错误、JSON 解析失败 |
| 401 Unauthorized | 身份认证失败 | 签名无效、API Key 过期、时间戳偏差过大 |
| 403 Forbidden | 无权限访问 | 商户未开通该评分通道、IP 白名单校验失败 |
| 404 Not Found | 资源不存在 | 查询不存在的订单 ID、规则 ID 无效 |
| 409 Conflict | 资源冲突 | 重复的幂等键、规则名称已存在、版本号冲突 |
| 422 Unprocessable Entity | 业务校验失败 | 评分金额超出限额、风控规则条件逻辑矛盾 |
| 429 Too Many Requests | 请求频率超限 | 商户 QPS 超过阈值、触发限流策略 |
3.4.3 服务端错误状态码
| 状态码 | 含义 | 处理建议 |
|---|---|---|
| 500 Internal Server Error | 服务端内部错误 | 记录错误日志,返回通用错误码,不暴露内部细节 |
| 502 Bad Gateway | 上游服务不可用 | 模型推理服务超时、数据库连接异常 |
| 503 Service Unavailable | 服务暂时过载或维护 | 返回 Retry-After 头,客户端应等待后重试 |
状态码最佳实践: 所有错误响应体必须包含
error_code(业务错误码)和 error_message(可读描述),便于客户端快速定位问题。例如:{"error_code": "RATE_LIMIT_EXCEEDED", "error_message": "请求频率超过每秒 100 次限制"}。
3.5 API 设计流程总览
下图展示了从资源识别到状态码定义的完整设计流程,帮助团队在 API 设计阶段建立统一规范。
3.6 错误响应体规范
统一的错误响应结构有助于客户端实现通用错误处理逻辑。推荐使用以下 JSON 格式:
{
"error_code": "INVALID_PARAMETER",
"error_message": "字段 'amount' 必须为正整数",
"request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-03-21T10:30:00Z",
"details": [
{
"field": "amount",
"reason": "金额不能为负数",
"value": -100
}
]
}
提示:
request_id 字段必须由服务端生成并返回,便于后续日志追踪与问题排查。客户端在报错时应主动提供该 ID 给技术支持。
3.7 幂等性设计
支付风控场景对幂等性要求极高,避免因网络重试导致重复评分或重复扣减。设计要点如下:
- 幂等键机制:客户端在 POST 请求头中携带
Idempotency-Key,服务端缓存该键与响应结果,相同键的重复请求直接返回缓存结果。 - 键有效期:建议幂等键有效期为 24 小时,过期后允许重新提交。
- 键生成规则:推荐使用 UUID v4,确保全局唯一。
- 冲突处理:若幂等键已存在但请求体不一致,返回 409 Conflict。
// 幂等评分请求示例
POST /v1/score/orders
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"merchant_id": "M10086",
"order_id": "ORD20250321001",
"amount": 29900,
"currency": "CNY",
"payee_account": "2088****1234"
}
注意: GET、PUT、DELETE 方法本身具有幂等性,无需额外实现幂等键。PATCH 方法视具体实现而定,若为增量更新则建议也支持幂等键。
3.8 分页与过滤设计
对于列表查询接口(如查询评分订单列表),必须支持分页与过滤,避免一次性返回大量数据导致性能问题。
| 参数 | 类型 | 说明 | 示例 |
|---|---|---|---|
page |
integer | 页码,从 1 开始 | ?page=1 |
page_size |
integer | 每页条数,默认 20,最大 100 | ?page_size=50 |
status |
string | 按状态过滤 | ?status=approved |
created_at_gt |
string (ISO 8601) | 创建时间大于 | ?created_at_gt=2025-03-01T00:00:00Z |
sort_by |
string | 排序字段,支持 created_at、amount |
?sort_by=-created_at(降序) |
// 分页响应示例
{
"data": [
{
"order_id": "ORD20250321001",
"status": "approved",
"score": 85,
"created_at": "2025-03-21T10:30:00Z"
}
],
"pagination": {
"page": 1,
"page_size": 20,
"total_count": 156,
"total_pages": 8
}
}
设计要点: 分页响应必须包含
total_count 和 total_pages,方便客户端渲染分页控件。排序字段使用前缀 - 表示降序,无前缀表示升序。
3.9 版本管理策略
API 版本管理是长期维护的必备手段。推荐在 URI 中嵌入版本号,并遵循以下策略:
- 主版本号:不兼容变更时递增(如
/v1/→/v2/)。 - 向后兼容:新增字段、新增可选参数、扩展枚举值均属于兼容变更,无需升级版本。
- 废弃周期:旧版本至少维护 6 个月,废弃前通过响应头
Deprecation: true和Sunset: Sat, 20 Sep 2025 23:59:59 GMT通知客户端。 - 版本映射:服务端内部可维护版本路由表,将不同版本的请求映射到对应的处理逻辑。
// 废弃版本响应头示例
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 20 Sep 2025 23:59:59 GMT
Content-Type: application/json
{
"message": "此 API 版本将于 2025 年 9 月 20 日废弃,请迁移至 /v2/score/orders"
}
最佳实践: 在 API 文档首页明确列出每个版本的当前状态(稳定/废弃/已下线),并附上迁移指南。建议使用 OpenAPI 3.0 规范自动生成文档,确保版本信息与代码同步。