|
|
@@ -4,6 +4,13 @@
|
|
|
|
|
|
> 更新时间:2026-09-07。当前口径已对齐下单设计稿:帮送/帮取与普通/加急正交、统一分时段运价、完整物品信息、费用明细及创建订单报价校验;闪送仍不接入支付。
|
|
|
|
|
|
+本次调整后的下单契约要点:
|
|
|
+
|
|
|
+- `serviceType` 只区分 `HELP_SEND`(帮送)和 `HELP_PICKUP`(帮取),不再使用 `URGENT` 作为服务类型。
|
|
|
+- 是否加急由独立字段 `deliveryType=NORMAL/URGENT` 表达;帮送和帮取使用同一套分时段基础运价。
|
|
|
+- 报价和创建订单都必须提交取件方式、物品类别、数量、总重量、规格说明和骑手小费;立即取件使用 `deliveryMode=NOW`,预约取件使用 `deliveryMode=SCHEDULED` 并提交取件时间段。
|
|
|
+- App 必须先报价,再把报价 ID、版本及四个费用字段原样回传创建订单接口。后端重新计算不一致时不会创建订单,而会返回最新报价。
|
|
|
+
|
|
|
## 1. 功能范围
|
|
|
|
|
|
当前闪送支持:
|
|
|
@@ -417,12 +424,26 @@ GET /system/flashDelivery/home
|
|
|
"minimumUrgentFee": 15,
|
|
|
"pricingVersion": 1,
|
|
|
"currency": "TWD"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "serviceType": "HELP_PICKUP",
|
|
|
+ "pricingId": 1,
|
|
|
+ "startTime": "00:00",
|
|
|
+ "endTime": "08:00",
|
|
|
+ "startingDistance": 3.00,
|
|
|
+ "startingFare": 60,
|
|
|
+ "distance": 1.00,
|
|
|
+ "freight": 10,
|
|
|
+ "urgentRate": 20.00,
|
|
|
+ "minimumUrgentFee": 15,
|
|
|
+ "pricingVersion": 1,
|
|
|
+ "currency": "TWD"
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-帮送和帮取会返回同一份当前运价摘要。`startTime` 包含、`endTime` 不包含,均为业务当地时间的 `HH:mm`;`24:00` 只会作为结束时间。`services` 为空表示当前时刻没有匹配的统一运价。
|
|
|
+帮送和帮取会返回两条业务场景数据,但两条数据引用同一个 `pricingId`、`pricingVersion` 和费用配置。`startTime` 包含、`endTime` 不包含,均为台北时区的 `HH:mm`;`24:00` 只会作为结束时间。`services` 为空表示当前时刻没有匹配的统一运价。
|
|
|
|
|
|
### 7.2 获取实时报价
|
|
|
|
|
|
@@ -469,6 +490,25 @@ POST /system/flashDelivery/quote
|
|
|
}
|
|
|
```
|
|
|
|
|
|
+报价请求字段:
|
|
|
+
|
|
|
+| 字段 | 类型 | 必填 | 规则 |
|
|
|
+|---|---|---:|---|
|
|
|
+| `serviceType` | string | 是 | `HELP_SEND` 或 `HELP_PICKUP` |
|
|
|
+| `deliveryType` | string | 是 | `NORMAL` 或 `URGENT` |
|
|
|
+| `deliveryMode` | string | 否 | `NOW` 或 `SCHEDULED`,不传按 `NOW` 处理 |
|
|
|
+| `scheduledPickupStartAt` | datetime | 预约时是 | `SCHEDULED` 时为未来三天内的预约开始时间;`NOW` 时不得传 |
|
|
|
+| `scheduledPickupEndAt` | datetime | 预约时是 | 必须比开始时间晚 30 分钟;`NOW` 时不得传 |
|
|
|
+| `packageType` | string | 是 | 取值见 3.3 |
|
|
|
+| `quantity` | integer | 是 | 大于 0 的整数 |
|
|
|
+| `totalWeightKg` | number | 是 | 大于 0 且不超过 20,最多两位小数 |
|
|
|
+| `specification` | string | 否 | 体积或规格说明,去除首尾空格后最长 255 字符 |
|
|
|
+| `tipAmount` | integer | 是 | 骑手小费,非负整数 TWD;没有小费时传 `0` |
|
|
|
+| `pickup` | object | 是 | 完整取件信息,结构和规则见 6.1 |
|
|
|
+| `delivery` | object | 是 | 完整收件信息,结构和规则见 6.1 |
|
|
|
+
|
|
|
+只要业务场景、配送等级、取件时间、物品信息、小费或取送地址发生变化,App 都必须重新调用报价接口,不能继续使用变化前的报价。
|
|
|
+
|
|
|
响应 `data`:
|
|
|
|
|
|
```json
|
|
|
@@ -479,8 +519,8 @@ POST /system/flashDelivery/quote
|
|
|
"scheduledPickupStartAt": "2026-09-08T16:30:00+08:00",
|
|
|
"scheduledPickupEndAt": "2026-09-08T17:00:00+08:00",
|
|
|
"pricingId": 1,
|
|
|
- "startTime": "00:00",
|
|
|
- "endTime": "08:00",
|
|
|
+ "startTime": "16:00",
|
|
|
+ "endTime": "18:00",
|
|
|
"distanceMeters": 4200,
|
|
|
"distanceSource": "ROUTE",
|
|
|
"estimatedDurationSeconds": 900,
|
|
|
@@ -503,7 +543,9 @@ POST /system/flashDelivery/quote
|
|
|
|
|
|
距离规则与现有外卖订单一致:先用路线公里数减去 `startingDistance`;超出不足 `0.5` 公里时 `billableDistance` 为 `0`,达到 `0.5` 但不足 `1` 公里时按 `1` 公里,达到 `1` 公里后按实际超出距离。`distanceFee = roundHalfUp(billableDistance / distance × freight)`,`baseDeliveryFee = startingFare + distanceFee`。普通配送的 `urgentFee=0`;加急配送的 `urgentFee=max(minimumUrgentFee, roundHalfUp(baseDeliveryFee × urgentRate / 100))`;`amount=baseDeliveryFee+urgentFee+tipAmount`。小费不参与加急费计算,预计时长也不参与计价。
|
|
|
|
|
|
-立即配送按报价时刻匹配运价,预约配送按 `scheduledPickupStartAt` 的当地时间匹配运价。创建订单必须回传本次报价;后端会重新计算并逐项精确校验,任何变化都不会创建订单,而是返回最新报价供用户重新确认。
|
|
|
+注意:`baseDeliveryFee` 是已经包含 `distanceFee` 的基础配送费小计。费用合计时不要再次把 `distanceFee` 加入总金额;`distanceFee` 仅用于向用户解释基础配送费中有多少是距离附加费。
|
|
|
+
|
|
|
+立即配送按报价时刻匹配运价,预约配送按 `scheduledPickupStartAt` 的台北时间匹配运价。创建订单必须回传本次报价;后端会重新计算并逐项精确校验,任何变化都不会创建订单,而是返回最新报价供用户重新确认。
|
|
|
|
|
|
### 7.3 创建闪送订单
|
|
|
|
|
|
@@ -511,23 +553,11 @@ POST /system/flashDelivery/quote
|
|
|
POST /system/flashDelivery/orders
|
|
|
```
|
|
|
|
|
|
-请求体在报价请求字段基础上增加:
|
|
|
+创建请求必须完整包含 7.2 的所有报价请求字段,并在同一个 JSON 对象中增加以下字段。下例只展示新增部分,实际请求不能省略 7.2 中的业务场景、配送等级、取件方式、适用的预约时间段、物品、小费和完整取送地址:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
- "serviceType": "HELP_SEND",
|
|
|
- "deliveryType": "URGENT",
|
|
|
- "packageType": "DOCUMENT",
|
|
|
- "quantity": 1,
|
|
|
- "totalWeightKg": 3.50,
|
|
|
- "specification": "30 x 20 x 10 cm",
|
|
|
- "tipAmount": 5,
|
|
|
- "pickup": {},
|
|
|
- "delivery": {},
|
|
|
- "clientRequestId": "FD-20260901-USER1001-0001",
|
|
|
- "deliveryMode": "SCHEDULED",
|
|
|
- "scheduledPickupStartAt": "2026-09-02T10:00:00+08:00",
|
|
|
- "scheduledPickupEndAt": "2026-09-02T10:30:00+08:00",
|
|
|
+ "clientRequestId": "FD-20260908-USER1001-0001",
|
|
|
"pricingId": 1,
|
|
|
"pricingVersion": 1,
|
|
|
"quotedBaseDeliveryFee": 72,
|
|
|
@@ -561,6 +591,42 @@ POST /system/flashDelivery/orders
|
|
|
|
|
|
若运价版本、路线或费用发生变化,响应 `code=500`、`msg=报价已变化,请重新确认最新费用`,并在 `data` 返回与报价接口相同的完整最新报价。App 必须更新费用明细并要求用户再次确认,不能自动用旧报价重试。
|
|
|
|
|
|
+报价变化响应示例:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "code": 500,
|
|
|
+ "msg": "报价已变化,请重新确认最新费用",
|
|
|
+ "data": {
|
|
|
+ "serviceType": "HELP_SEND",
|
|
|
+ "deliveryType": "URGENT",
|
|
|
+ "deliveryMode": "SCHEDULED",
|
|
|
+ "scheduledPickupStartAt": "2026-09-08T16:30:00+08:00",
|
|
|
+ "scheduledPickupEndAt": "2026-09-08T17:00:00+08:00",
|
|
|
+ "pricingId": 2,
|
|
|
+ "startTime": "16:00",
|
|
|
+ "endTime": "18:00",
|
|
|
+ "distanceMeters": 4200,
|
|
|
+ "distanceSource": "ROUTE",
|
|
|
+ "estimatedDurationSeconds": 900,
|
|
|
+ "startingDistance": 3.00,
|
|
|
+ "startingFare": 60,
|
|
|
+ "distance": 1.00,
|
|
|
+ "freight": 10,
|
|
|
+ "urgentRate": 25.00,
|
|
|
+ "minimumUrgentFee": 15,
|
|
|
+ "billableDistance": 1.20,
|
|
|
+ "distanceFee": 12,
|
|
|
+ "baseDeliveryFee": 72,
|
|
|
+ "urgentFee": 18,
|
|
|
+ "tipAmount": 5,
|
|
|
+ "amount": 95,
|
|
|
+ "currency": "TWD",
|
|
|
+ "pricingVersion": 2
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
创建时,后端会移除收件手机号中的空白、`+`、`-`、`(`、`)` 后,匹配有效且未删除的普通用户账号。仅在恰好匹配一个账号时把该账号固化为收件人;无匹配或重复匹配均不绑定。此绑定只执行一次,历史订单不会因收件人之后注册或修改手机号而自动认领。
|
|
|
|
|
|
### 7.4 查询用户订单列表
|
|
|
@@ -842,7 +908,7 @@ POST /system/address/{id}/top
|
|
|
| token 已过期 | 登录态失效 | 清理登录态并重新登录 |
|
|
|
| 对应取件时段暂无可用运价 | 立即时刻或预约开始时刻没有匹配统一运价 | 重新选择取件时间或稍后重试 |
|
|
|
| 报价已变化,请重新确认最新费用 | 运价版本、路线或费用与创建请求回传值不一致 | 用响应 `data` 刷新费用并让用户再次确认 |
|
|
|
-| 物品数量、总重量或规格信息不正确 | 数量非正整数、重量不在 0 至 20kg 或规格过长 | 返回物品信息页修正 |
|
|
|
+| 物品数量、总重量或规格信息不正确 | 数量非正整数、重量不大于 0、超过 20kg、小数超过两位或规格过长 | 返回物品信息页修正 |
|
|
|
| 取件地址和收件地址不能相同 | 地址文本相同或经纬度完全相同 | 要求用户修改地址 |
|
|
|
| 配送距离不能超过 40 公里 | 服务端路线距离超限 | 提示当前路线不可下单 |
|
|
|
| 预约取件时段无效 | 时间已过、超过三天或不是 30 分钟 | 重新选择预约时段 |
|
|
|
@@ -859,7 +925,7 @@ POST /system/address/{id}/top
|
|
|
- 首页只展示 `/home` 返回的当前时段可用服务,不在 App 中维护启停状态或默认价格。
|
|
|
- 报价和创建订单都提交 `serviceType`、`deliveryType`、配送方式、完整物品信息、骑手小费及取送坐标。
|
|
|
- 创建订单原样回传报价的配置 ID、版本、基础配送费、距离费、加急费和总金额;报价变化时展示最新明细并重新确认。
|
|
|
-- 金额按整数 TWD 展示,并分别显示基础配送费、距离费、加急费、骑手小费和总金额;不显示支付成功、骑手收入、时长费或尖峰费用。
|
|
|
+- 金额按整数 TWD 展示;`baseDeliveryFee` 已包含 `distanceFee`,距离费只作为基础配送费的明细展示,总金额只按 `baseDeliveryFee + urgentFee + tipAmount` 计算;不显示支付成功、骑手收入、时长费或尖峰费用。
|
|
|
- 创建订单具备稳定的 `clientRequestId` 重试策略。
|
|
|
- 预约时间满足未来三天内、固定 30 分钟的约束。
|
|
|
- App 使用响应体 `code` 判断成功或失败。
|