二期内容提交

This commit is contained in:
2026-08-04 10:07:45 +08:00
parent b2b4ff429d
commit 57b54a5236
184 changed files with 13195 additions and 5 deletions
@@ -67,13 +67,160 @@ paths:
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无分配权限}
/openapi/v1/inbound-measurements:
post:
summary: 提交第三方长宽高测量结果
description: >-
只写 fl_third_party_call_log、fl_inbound_measurement、fl_inbound_measurement_item
和 HTTP 幂等结果,不审核、不计费、不入库,也不改变入库单状态。
签名串依次为 METHOD、原始 PATH、X-Timestamp、X-Nonce、Idempotency-Key、
原始 UTF-8 body 的 SHA-256 小写十六进制,六部分使用 LF(\n)连接且末尾不追加换行。
三层语义:Nonce 防短时重放;Idempotency-Key 标识一次 HTTP 写操作;
appKey + eventNo 标识第三方业务事件。
security:
- measurementAppKey: []
measurementTimestamp: []
measurementNonce: []
measurementSignature: []
parameters:
- {$ref: '#/components/parameters/XTimestamp'}
- {$ref: '#/components/parameters/XNonce'}
- {$ref: '#/components/parameters/IdempotencyKey'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementCallbackRequest'}
responses:
'200': {description: 成功或业务失败,按响应体字符串 code 判断;非法签名返回 A0401}
'413': {description: 请求体超过网关限制}
'415': {description: Content-Type 不支持}
/openapi/v1/inbound-measurements/events/{eventNo}:
get:
summary: 查询第三方测量事件状态
description: GET 签名串的 Idempotency-Key 行为空字符串,body 摘要为空字节 SHA-256。
security:
- measurementAppKey: []
measurementTimestamp: []
measurementNonce: []
measurementSignature: []
parameters:
- name: eventNo
in: path
required: true
schema: {type: string, pattern: '^[A-Za-z0-9._:-]{1,128}$'}
- {$ref: '#/components/parameters/XTimestamp'}
- {$ref: '#/components/parameters/XNonce'}
responses:
'200': {description: 成功或业务失败,按响应体字符串 code 判断}
/api/platform/inbounds:
get:
summary: 分页查询入库单
description: 需要 platform:firstleg:inbound:list 权限;仅使用 V2 四个页签
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tab, in: query, schema: {type: string, enum: [WAIT_MEASURE, WAIT_REVIEW, WAIT_FEE_SEND, INBOUNDED]}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无查询权限}
/api/platform/inbounds/{inboundId}:
get:
summary: 查询入库单详情
description: 需要 platform:firstleg:inbound:view 权限
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无查看权限}
/api/platform/v1/inbounds/{inboundId}/measurements/approve:
post:
summary: 审核通过测量
description: 需要 firstleg:inbound:measurement-review 权限;客服审核通过后自动计费、发布费用给客户并完成入库,客户无需确认。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
responses:
'200': {description: 成功或业务失败}
/api/platform/v1/inbounds/{inboundId}/measurements/reject:
post:
summary: 驳回测量
description: 需要 firstleg:inbound:measurement-review 权限;只退回测量数据修改,已确认托盘和库位占用保持不动。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
responses:
'200': {description: 成功或业务失败}
/api/platform/v1/inbounds/{inboundId}/measurements/submit:
post:
summary: 提交测量完成
description: 测量提交后立即按总体积拆分普通托盘、分配并确认占用库位,再进入客服待审核;无普通空闲位时共享 A0。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功时 processStatus=MEASURE_PENDING、measureReviewStatus=PENDING,且库位已 OCCUPIED}
'403': {description: 无测量提交权限}
/api/merchant/v1/first-leg/orders/{orderId}/inbound-billing:
get:
summary: 客户查询已完成入库结果和最新已发布费用
description: 需要 merchant:order:view 权限;客户只读查看,不需要确认费用,未完成客服审核发布时不可见。
parameters:
- {name: orderId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 非本租户或无订单查看权限}
/api/platform/v1/inbounds/{inboundId}/measurements/exception-release:
post:
summary: 测量异常放行
description: 需要 firstleg:inbound:exception-release 权限
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
responses:
'200': {description: 成功或业务失败}
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
measurementAppKey:
type: apiKey
in: header
name: X-App-Key
description: 分配给测量服务商的应用标识
measurementTimestamp:
type: apiKey
in: header
name: X-Timestamp
description: Unix 毫秒时间戳
measurementNonce:
type: apiKey
in: header
name: X-Nonce
description: 每次请求唯一的随机串
measurementSignature:
type: apiKey
in: header
name: X-Signature
description: HMAC-SHA256 小写十六进制签名
parameters:
XTimestamp:
name: X-Timestamp
in: header
required: true
schema: {type: string, pattern: '^[0-9]{13}$', example: '1785551400000'}
XNonce:
name: X-Nonce
in: header
required: true
schema: {type: string, minLength: 1, maxLength: 128}
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
schema: {type: string, minLength: 1, maxLength: 128}
TenantId:
name: tenantId
in: query
@@ -93,6 +240,39 @@ components:
in: query
schema: {type: integer, format: int64, minimum: 1, maximum: 200, default: 20}
schemas:
InboundMeasurementCallbackRequest:
type: object
required: [eventNo, warehouseCode, inboundCode, deviceCode, measuredAt, items]
properties:
eventNo: {type: string, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$', example: M202608010001}
warehouseCode: {type: string, maxLength: 50, example: CN-YW-01}
inboundCode: {type: string, maxLength: 40, example: RK202608010001}
deviceCode: {type: string, maxLength: 64, example: DEVICE-01}
measuredAt: {type: string, format: date-time, example: '2026-08-01T10:30:00+08:00'}
items:
type: array
minItems: 1
maxItems: 500
items: {$ref: '#/components/schemas/InboundMeasurementItem'}
InboundMeasurementItem:
type: object
required: [itemNo, boxSpecification, lengthCm, widthCm, heightCm, quantity]
properties:
itemNo: {type: string, maxLength: 32, example: '001'}
boxSpecification: {type: string, maxLength: 64, example: '61.5x42x42cm', description: 入库单绑定的箱规明细}
lengthCm: {type: number, exclusiveMinimum: true, minimum: 0, example: 50.20}
widthCm: {type: number, exclusiveMinimum: true, minimum: 0, example: 40.10}
heightCm: {type: number, exclusiveMinimum: true, minimum: 0, example: 30.00}
quantity: {type: integer, minimum: 1, maximum: 1000000, example: 5}
sourceImageUrl: {type: string, maxLength: 2048, nullable: true, description: 仅随原始报文留档,不直接写文件中心}
InboundMeasurementEventResponse:
type: object
properties:
eventNo: {type: string}
inboundCode: {type: string}
accepted: {type: boolean}
status: {type: string, enum: [RECEIVED]}
receivedAt: {type: string, format: date-time}
AssignRequest:
type: object
required: [assigneeId, assigneeName]