主题
价格管理
PriceManagementController 对外提供两个接口:
| 接口 | 请求方式 | 地址 | 用途 |
|---|---|---|---|
| 物流品类定位 | POST | /openapi/priceManagement/categories/resolve | 定位主品,返回候选及配套品/附加品 |
| 物流报价计算 | POST | /openapi/priceManagement/calculate | 使用确认后的品类 ID 和货物参数计算报价 |
推荐先定位品类,再调用物流报价。两个接口均遵循基础约定中的 AK/SK HMAC-SHA256 验签规则。
物流品类定位
请求信息
http
POST /openapi/priceManagement/categories/resolve
Content-Type: application/json请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
query | String | 条件必填 | 商品大类、主品名称、品类编码或配套/附加品名称,例如“床类”“实木床”“01-204”“床头柜” |
mainCategoryId | String | 条件必填 | 已确认的主品 ID,取自上一轮的 mainProduct.categoryId 或 mainProducts[].categoryId |
请求规则:
query和mainCategoryId至少传一个。- 两者同时传入时,优先使用
mainCategoryId。 - 首次查询传
query;用户选定候选后,仍调用本接口并传mainCategoryId。 mainCategoryId只能是主品 ID,不能传配套品或附加品 ID。
请求示例一:关键词定位
在 Apifox 中选择 Body -> raw -> JSON:
json
{
"query": "床头柜"
}请求示例二:确认候选主品
json
{
"mainCategoryId": "2011025668681089026"
}示例 ID 仅用于说明。实际调用时必须使用接口返回的真实 categoryId。
响应参数
统一响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
code | Integer | 业务状态码,200 表示请求成功 |
message | String | 响应信息;失败时返回错误原因 |
result | Object | 品类定位结果 |
traceId | String | 链路 ID,存在链路上下文时返回 |
success | Boolean | code=200 时为 true |
result 字段
| 字段 | 类型 | 返回条件 | 说明 |
|---|---|---|---|
matchType | String | 成功时 | 当前定位结果 |
needSelection | Boolean | 成功时 | 是否需要用户选择主品 |
nextAction | String | 成功时 | AI 建议执行的下一步动作 |
matchedCategory | Object | CATEGORY | 匹配到的大类 |
mainProduct | Object | EXACT_MAIN | 唯一定位到的主品 |
mainProducts | Array | CATEGORY、AMBIGUOUS、NOT_FOUND | 主品候选;未找到时为空数组 |
matchedCategory 字段
| 字段 | 类型 | 说明 |
|---|---|---|
categoryCode | String | 大类编码 |
categoryName | String | 大类名称 |
mainProduct / mainProducts[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
categoryId | String | 主品 ID;报价时填入 cargoList[].categoryId |
categoryCode | String | 品类编码 |
categoryGroupCode | String | 所属大类编码 |
categoryGroupName | String | 所属大类名称 |
categoryName | String | 主品名称 |
packingCode | String | 包装方式字典值,未配置时不返回 |
packingName | String | 包装方式名称,未配置时不返回 |
count | String | 单套件数 |
weightKg | String | 单套重量,单位 kg |
volumeM3 | String | 单套体积,单位 m³ |
combinationProduct | Boolean | 是否为组合商品 |
hasComponents | Boolean | 是否存在启用的配套品或附加品 |
components | Array | 仅精确定位且存在子品时返回 |
components[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
categoryId | String | 子品 ID;报价时填入子品的 cargoList[].categoryId |
categoryCode | String | 子品品类编码 |
categoryGroupCode | String | 子品所属大类编码 |
categoryGroupName | String | 子品所属大类名称 |
categoryName | String | 子品名称 |
packingCode | String | 包装方式字典值 |
packingName | String | 包装方式名称 |
componentType | String | MATCHING 配套品,ACCESSORY 附加品 |
componentTypeName | String | 配套品或附加品 |
count | String | 单套件数 |
weightKg | String | 单套重量,单位 kg |
volumeM3 | String | 单套体积,单位 m³ |
业务状态字段
matchType、needSelection 和 nextAction 是接口为 AI 对话流程定义的业务字段,不是品类表原始字段。
matchType | 含义 | 返回数据 |
|---|---|---|
EXACT_MAIN | 已定位唯一主品 | mainProduct |
CATEGORY | 只匹配到商品大类 | matchedCategory、mainProducts |
AMBIGUOUS | 匹配到多个主品 | mainProducts |
NOT_FOUND | 未找到主品、大类或子品关系 | 空的 mainProducts |
nextAction | 触发条件 | AI 动作 |
|---|---|---|
READY_FOR_QUOTE | 唯一主品且没有子品 | 补齐报价参数后直接报价 |
CONFIRM_COMPONENTS | 唯一主品且存在 components | 询问用户运输哪些子品及数量 |
SELECT_MAIN_PRODUCT | 大类或多个候选 | 让用户选择,再传 mainCategoryId 查询 |
REFINE_QUERY | 未找到 | 追问品类、材质、尺寸或用途后重试 |
例如:
json
{
"matchType": "EXACT_MAIN",
"needSelection": false,
"nextAction": "CONFIRM_COMPONENTS"
}表示主品已经唯一确定,但存在配套品或附加品。AI 应先确认本次是否运输这些子品以及数量,再调用报价接口。
实际 JSON 值是 EXACT_MAIN,不包含 Markdown 转义符 \。
返回示例
请求:
json
{
"mainCategoryId": "2011025668681089026"
}响应:
json
{
"message": "",
"code": 200,
"result": {
"matchType": "EXACT_MAIN",
"needSelection": false,
"nextAction": "CONFIRM_COMPONENTS",
"mainProduct": {
"categoryId": "2011025668681089026",
"categoryCode": "01-204",
"categoryGroupCode": "01",
"categoryGroupName": "床类",
"categoryName": "实木床",
"count": "1",
"weightKg": "120",
"volumeM3": "1.80",
"combinationProduct": true,
"hasComponents": true,
"components": [
{
"categoryId": "2011025680000000001",
"categoryCode": "01-301",
"categoryGroupCode": "01",
"categoryGroupName": "床类",
"categoryName": "床头柜",
"componentType": "MATCHING",
"componentTypeName": "配套品",
"count": "1",
"weightKg": "20",
"volumeM3": "0.20"
}
]
}
},
"traceId": "20260912160100-example-main",
"success": true
}物流报价计算
请求信息
http
POST /openapi/priceManagement/calculate
Content-Type: application/json请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sendAddress | String | 是 | 发货地址,需要能够识别省、市、区 |
receiveAddress | String | 是 | 收货地址,需要能够识别省、市、区,同时用于超区费匹配 |
distributionType | String | 否 | 1 自提、2 到楼下、3 到家、4 到家并安装;默认 1 |
merchantWorkNo | String | 否 | 商家会员号;默认从伙伴配置获取 |
bindWorkNo | String | 否 | 指定物流公司会员号 |
cargoList | Array | 是 | 货物列表,至少一项 |
cargoList[].categoryId | String | 是 | 品类定位接口返回的主品或子品 categoryId;旧字段 categoryName 暂时兼容,但不建议继续使用 |
cargoList[].piece | String | 按计费方式 | 本行货物套数 |
cargoList[].suit | String | 按计费方式 | 本行货物件数 |
cargoList[].weight | String | 按计费方式 | 本行货物合计重量,单位 kg |
cargoList[].volume | String | 按计费方式 | 本行货物合计体积,单位 m³ |
cargoList[].parentId | String | 子品必填 | 主品不传;子品传所属主品的 categoryId |
请求示例:主品及配套品
json
{
"sendAddress": "广东省深圳市南山区科技园1号",
"receiveAddress": "广东省广州市天河区体育西路100号",
"distributionType": "4",
"cargoList": [
{
"categoryId": "2011025668681089026",
"piece": "1",
"suit": "1",
"weight": "120",
"volume": "1.80"
},
{
"categoryId": "2011025680000000001",
"parentId": "2011025668681089026",
"piece": "2",
"suit": "2",
"weight": "40",
"volume": "0.40"
}
]
}子品的 parentId 必须指向主品。重量和体积是当前货物行对应数量的合计值。
响应参数
result 是按 totalFee 从低到高排列的报价数组。
| 字段 | 类型 | 说明 |
|---|---|---|
result[].companyWorkNo | String | 物流公司会员号 |
result[].companyName | String | 物流公司名称 |
result[].areaName | String | 命中的价格区域 |
result[].trunkFee | Decimal | 干线费,单位元 |
result[].branchFee | Decimal | 支线费,单位元 |
result[].deliveryInstallFee | Decimal | 送货/安装服务费,单位元 |
result[].excessVolumeFee | Decimal | 超方费,单位元 |
result[].superzoneFee | Decimal | 超区费,单位元 |
result[].totalFee | Decimal | 总费用,单位元 |
返回示例
json
{
"message": "",
"code": 200,
"result": [
{
"companyWorkNo": "300061",
"companyName": "示例物流A",
"areaName": "广州区域",
"trunkFee": 100.00,
"branchFee": 20.00,
"deliveryInstallFee": 30.00,
"excessVolumeFee": 0.00,
"superzoneFee": 0.00,
"totalFee": 150.00
},
{
"companyWorkNo": "300088",
"companyName": "示例物流B",
"areaName": "广州区域",
"trunkFee": 105.00,
"branchFee": 25.00,
"deliveryInstallFee": 35.00,
"excessVolumeFee": 0.00,
"superzoneFee": 10.00,
"totalFee": 175.00
}
],
"traceId": "20260912161000-example-price",
"success": true
}计费说明
- 协议价优先,未配置协议价时使用公布价。
- 干线费根据后台计费方式按体积、套数或重量计算。
- 配送方式影响支线费和送货安装费。
- 超方费按总体积计算。
- 超区费根据
receiveAddress匹配。