2. 接口基础:RESTful API设计原则在采购验收场景中的应用

在采购到货验收流程中,系统间的数据交互频繁且对实时性要求高。RESTful API 作为当前主流的接口设计规范,其核心原则能够有效指导我们构建清晰、可维护、可扩展的验收接口。本章将结合采购验收的实际业务场景,解析 RESTful 六大核心原则的具体应用。

2.1 RESTful 六大核心原则与验收场景映射

REST(Representational State Transfer)是一种架构风格,而非具体协议。以下表格展示了六大原则在采购验收中的落地方式:

原则 采购验收场景解释 典型接口示例
资源导向 将采购订单、到货单、验收项视为资源,通过 URI 定位 /api/v1/purchase-orders/{poId}/receipts
统一接口 使用标准 HTTP 方法(GET/POST/PUT/PATCH/DELETE)操作资源 POST 创建到货单,PATCH 更新验收状态
无状态 每次请求包含全部必要信息,服务端不保存客户端会话状态 请求头携带 + 租户 ID,不依赖 Session
可缓存 对不频繁变动的字典数据(如验收标准)启用缓存 Cache-Control: max-age=3600
分层系统 客户端不直接访问数据库,通过网关、服务层、数据层解耦 API 网关统一鉴权,业务服务处理验收逻辑
按需代码(可选) 服务端可返回可执行脚本扩展客户端功能(极少用) 返回验收规则脚本(仅限沙箱环境)
实践要点: 在验收流程中,无状态 原则最为关键。每次验收操作(如扫码、质检、入库确认)都应携带完整的上下文信息(订单号、批次号、操作人),避免因会话超时导致数据不一致。

2.2 资源命名与 URI 设计规范

采购验收涉及多个资源实体,URI 设计应遵循名词复数、层级清晰、版本控制的原则。以下为推荐的设计模式:

  • 核心资源: 采购订单(purchase-orders)、到货单(receipts)、验收项(inspection-items)、质检报告(quality-reports)。
  • 层级关系: 使用路径参数表达从属关系,如 /purchase-orders/{poId}/receipts/{receiptId}/items。
  • 过滤与排序: 通过查询参数实现,如 ?status=PENDING&sortBy=createdTime,desc。
  • 版本控制: 在 URI 前缀中加入版本号,如 /api/v2/,避免向后兼容问题。
# 推荐 URI 示例
GET    /api/v1/receipts/{receiptId}              # 查询单个到货单详情
POST   /api/v1/receipts                          # 创建到货单(到货登记)
PATCH  /api/v1/receipts/{receiptId}/status       # 更新到货单状态(如:待质检→已质检)
GET    /api/v1/receipts/{receiptId}/items        # 查询到货单下的所有验收项
POST   /api/v1/receipts/{receiptId}/items/{itemId}/inspect  # 提交单个验收项的质检结果
避坑提示: 避免在 URI 中使用动词(如 /createReceipt),应使用 HTTP 方法表达动作。同时,不要将层级嵌套超过 3 层,过深的 URI 会增加维护难度,建议通过查询参数或子资源方式扁平化。

2.3 HTTP 方法与状态码在验收流程中的选择

正确选择 HTTP 方法和状态码是接口可读性的关键。以下为采购验收中常见操作的映射关系:

业务操作 HTTP 方法 成功状态码 失败常见状态码
查询到货单列表 GET 200 OK 400(参数错误)
创建到货单 POST 201 Created 409(重复创建)
更新验收项数量 PATCH 200 OK 422(业务校验失败)
替换整个验收报告 PUT 200 OK 404(资源不存在)
删除作废的验收项 DELETE 204 No Content 403(无权限)
推荐实践: 对于部分更新(如仅修改验收状态),优先使用 PATCH 而非 PUT,避免客户端发送全量数据,减少网络开销和并发冲突风险。

2.4 验收流程接口调用架构图

以下 SVG 图展示了采购验收流程中,各系统间通过 RESTful API 进行交互的典型架构:

采购验收 RESTful API 调用架构图 扫码终端 / Web 端 质检系统 / MES ERP / WMS API 网关(鉴权 / 限流 / 路由) 到货登记服务 质检执行服务 入库确认服务 验收数据库 / 缓存 / 消息队列 说明:所有客户端请求统一经过 API 网关,网关负责鉴权与路由,业务服务通过 RESTful 接口与数据层交互

2.5 验收接口的请求与响应规范

统一的请求/响应结构能显著降低对接成本。以下为推荐的 JSON 格式规范:

// 请求体示例:创建到货单
POST /api/v1/receipts
Content-Type: application/json
Authorization: Bearer <>

{
  "poId": "PO202405001",
  "supplierCode": "SUP001",
  "warehouseCode": "WH01",
  "items": [
    {
      "materialCode": "MAT001",
      "plannedQty": 100,
      "actualQty": 98,
      "batchNo": "B20240501"
    }
  ]
}

// 成功响应示例
HTTP/1.1 201 Created
Content-Type: application/json

{
  "code": 0,
  "message": "success",
  "data": {
    "receiptId": "REC202405001",
    "status": "PENDING_INSPECT",
    "createdTime": "2024-05-20T10:30:00Z"
  }
}

// 业务错误响应示例
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "code": 42201,
  "message": "实际到货数量超过采购订单允许的浮动范围",
  "data": null,
  "errors": [
    {
      "field": "items[0].actualQty",
      "message": "实际数量 98 超出允许范围 [90, 100]"
    }
  ]
}
规范要点:
  • 统一使用 code + message + data 结构,业务错误码(如 42201)便于客户端精准处理。
  • 错误详情放在 errors 数组中,指明具体字段和原因,方便前端定位问题。
  • 时间字段统一使用 ISO 8601 格式(如 2024-05-20T10:30:00Z),避免时区歧义。

2.6 验收流程中的幂等性设计

在到货验收场景中,网络超时或客户端重试可能导致同一验收请求被多次提交。幂等性设计可防止重复创建或重复更新。以下为两种常见实现方式:

实现方式 适用场景 实现要点
客户端幂等键 创建到货单、提交质检结果 客户端生成唯一 Idempotency-Key 请求头,服务端缓存该 Key 对应的响应结果,重复请求直接返回缓存
业务唯一索引 更新验收状态、确认入库 数据库层对 (receiptId, status) 建立唯一联合索引,防止状态重复变更
// 幂等键使用示例
POST /api/v1/receipts
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{
  "poId": "PO202405001",
  // ... 其他字段
}

// 服务端处理逻辑(伪代码)
if (cache.exists(idempotencyKey)) {
  return cache.get(idempotencyKey);  // 返回上一次的响应
}
// 执行业务逻辑并缓存结果
result = createReceipt(requestBody);
cache.set(idempotencyKey, result, ttl=3600);
return result;
注意: 幂等键的过期时间(TTL)应根据业务场景设置。验收流程中建议设置为 1 小时,覆盖客户端自动重试窗口。同时,幂等键应使用 UUID v4 等全局唯一标识,避免冲突。

2.7 验收接口的分页与过滤最佳实践

当查询到货单列表或验收项明细时,数据量可能较大。推荐使用游标分页(Cursor-based Pagination)而非传统偏移分页,以提升性能和数据一致性。

// 游标分页请求示例
GET /api/v1/receipts?status=PENDING_INSPECT&cursor=eyJpZCI6MTAwMH0=&limit=20

// 响应示例
HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": 0,
  "data": {
    "items": [ /* 验收单列表 */ ],
    "nextCursor": "eyJpZCI6MTAyMH0=",
    "hasMore": true
  }
}

// 过滤参数示例(组合使用)
GET /api/v1/receipts?supplierCode=SUP001&warehouseCode=WH01&createdTimeFrom=2024-05-01T00:00:00Z&createdTimeTo=2024-05-20T23:59:59Z
推荐实践: 对于验收项明细查询,建议同时支持按物料编码、批次号、质检状态进行过滤,减少客户端数据拉取量。游标分页的 cursor 参数应使用 Base64 编码,避免特殊字符干扰。