本文档供用户端 App 和骑手端 App 接入闪送功能使用,以当前后端实现为准。文档只描述接口契约和业务流程,不包含 App 前端实现代码。
当前闪送支持:
当前不包含支付、退款、骑手收入、结算、代购垫付、自动派单和骑手放弃订单。
设计原型中的支付方式选择、已付款状态、附近骑手上线数量、预计接单时间和骑手收益金额均为静态示意,接口不提供这些数据,App 不应展示或请求它们。
接口路径均为相对路径,实际请求地址为:
{baseUrl}{接口路径}
除特别说明外,用户端和骑手端接口都必须携带以下请求头:
| 请求头 | 必填 | 说明 |
|---|---|---|
token |
是 | App 登录后取得的 JWT。不要放在 Authorization 中 |
Content-Type |
POST JSON 接口必填 | application/json |
用户身份和骑手身份均由 token 解析,请求体中不提交 userId 或 riderId。
成功响应:
{
"code": 200,
"msg": "操作成功",
"data": {}
}
无返回数据的成功响应通常不含 data:
{
"code": 200,
"msg": "操作成功"
}
业务失败响应:
{
"code": 500,
"msg": "当前订单状态不允许此操作"
}
登录失效响应:
{
"code": 401,
"msg": "token已过期,请重新登录!"
}
App 必须以响应体 code 判断业务是否成功,不能只依赖 HTTP 状态码。msg 已由后端国际化,可直接用于错误提示。
列表接口的分页数据位于 data 中,不使用若依传统的顶层 rows/total:
{
"code": 200,
"msg": "操作成功",
"data": {
"records": [],
"total": 0,
"current": 1,
"size": 10,
"pages": 0
}
}
page 默认 1,小于 1 时按 1 处理。size 默认 10,范围为 1 至 100。records、total、current 和 size。2026-09-02T10:00:00+08:00。currency 固定为 TWD;startingFare、freight、distanceFee 和 amount 都是整数,不带小数。distanceMeters 单位为米。startingDistance、distance 以及报价中的 billableDistance 单位为公里,可保留两位小数。estimatedDurationSeconds 单位为秒,路线服务降级时可能为 null。distanceSource 为 ROUTE 时表示地图驾车路线,为 STRAIGHT_LINE 时表示地图服务不可用后使用直线距离降级。serviceType| 值 | 含义 |
|---|---|
HELP_SEND |
帮送 |
HELP_PICKUP |
帮取 |
URGENT |
加急送 |
是否可下单以首页接口当前实际返回的服务为准。运价没有启停状态;只有当前时间命中已配置运价时段的服务才会返回,不要在 App 中假定三种服务始终全部可用。
packageType| 值 | 含义 |
|---|---|
DOCUMENT |
文件 |
GIFT |
礼品 |
CLOTHING |
服饰 |
BEAUTY |
美妆 |
DAILY_NECESSITIES |
日用品 |
FOOD_INGREDIENTS |
食材 |
ELECTRONICS |
数码产品 |
SMALL_APPLIANCE |
小家电 |
OTHER |
其他 |
packageSize| 值 | 含义 |
|---|---|
SMALL |
不超过 5kg |
MEDIUM |
不超过 12kg |
LARGE |
不超过 20kg |
接口只提交重量档,不提交精确重量。
deliveryMode| 值 | 含义 |
|---|---|
NOW |
立即配送,也是未传值时的默认值 |
SCHEDULED |
预约配送 |
预约配送要求:
scheduledPickupStartAt 和 scheduledPickupEndAt 都必填。WAITING_ACCEPTANCE,但在预约开始时间到达前不会出现在骑手待抢列表中。立即配送时不得传 scheduledPickupStartAt 和 scheduledPickupEndAt。
statusWAITING_ACCEPTANCE -> ACCEPTED -> PICKED_UP -> DELIVERED -> COMPLETED
| |
+---- 用户可取消 +---- 用户可取消
| 值 | 含义 | 下一步 |
|---|---|---|
WAITING_ACCEPTANCE |
待骑手接单 | 骑手抢单,或用户取消 |
ACCEPTED |
骑手已接单 | 骑手确认取件,或用户取消 |
PICKED_UP |
骑手已取件 | 骑手确认送达 |
DELIVERED |
骑手已送达 | 用户确认收货;超过 24 小时可由系统自动完成 |
COMPLETED |
已完成 | 终态 |
CANCELLED |
已取消 | 终态 |
WAITING_ACCEPTANCE 或 ACCEPTED 状态可取消;在 DELIVERED 状态可确认收货。抢单为并发原子操作。即使列表中仍显示订单,也可能已被其他骑手抢走;收到失败响应后应刷新待抢列表。
闪送订单接口不接收文件,只接收上传完成后的 HTTP(S) 图片 URL。
App 可复用现有上传接口:
| 方法 | 路径 | Content-Type | 参数 |
|---|---|---|---|
| POST | /utils/Upload |
multipart/form-data |
文件字段名 file |
成功响应示例:
{
"code": 200,
"msg": "上传成功",
"data": "/profile/upload/2026/09/01/example.jpg"
}
该接口返回的 data 可能是相对资源路径。提交给闪送接口前,必须补全为外部可访问的绝对 URL,例如:
https://api.example.com/profile/upload/2026/09/01/example.jpg
图片 URL 规则:
http:// 或 https:// URL,必须包含主机名。senderImageUrls 可不传,最多 9 张。报价和创建订单中的 pickup、delivery 使用以下结构:
{
"name": "王小明",
"phone": "0912345678",
"address": "台北市信义区市府路1号",
"addressDetail": "3楼A室",
"city": "台北市",
"area": "信义区",
"handoffMethod": "请电话联系",
"longitude": 121.5645,
"latitude": 25.033
}
| 字段 | 类型 | 必填 | 规则 |
|---|---|---|---|
name |
string | 是 | 最长 64 字符 |
phone |
string | 是 | 最长 32 字符 |
address |
string | 是 | 完整主地址,最长 255 字符 |
addressDetail |
string | 否 | 楼层、门牌等,最长 255 字符 |
city |
string | 否 | 最长 64 字符;用于骑手抢单前的区域展示 |
area |
string | 否 | 最长 64 字符;用于骑手抢单前的区域展示 |
handoffMethod |
string | 否 | 交接说明,最长 40 字符 |
longitude |
number | 是 | -180 至 180 |
latitude |
number | 是 | -90 至 90 |
取件和收件地址不能是相同地址文本,也不能使用完全相同的经纬度。
App 完整详情使用以下订单字段,响应的 data 直接返回这些字段,不再套用 order、images、logs 包装。
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 订单主键,后续接口路径使用此值 |
orderNo |
string | 闪送订单号 |
serviceType |
string | 服务类型 |
status |
string | 当前状态 |
packageType |
string | 包裹类型 |
packageSize |
string | 包裹重量档 |
deliveryMode |
string | NOW 或 SCHEDULED |
scheduledPickupStartAt |
datetime/null | 预约开始时间 |
scheduledPickupEndAt |
datetime/null | 预约结束时间 |
pinRequired |
boolean | 是否需要交付 PIN |
pickup |
object | 取件地址快照,结构见 6.1 |
delivery |
object | 收件地址快照,结构见 6.1 |
distanceMeters |
number | 配送距离,单位米 |
distanceSource |
string | ROUTE 或 STRAIGHT_LINE |
estimatedDurationSeconds |
number/null | 预计时长,单位秒 |
amount |
integer | 订单金额,整数 TWD |
currency |
string | TWD |
userNote |
string/null | 用户备注 |
acceptedAt |
datetime/null | 接单时间 |
pickedUpAt |
datetime/null | 取件时间 |
deliveredAt |
datetime/null | 送达时间 |
completedAt |
datetime/null | 完成时间 |
cancelledAt |
datetime/null | 取消时间 |
cancelReason |
string/null | 取消原因 |
createTime |
datetime | 创建时间 |
updateTime |
datetime | 更新时间 |
用户列表摘要固定字段为:id,orderNo,serviceType,status,packageType,deliveryMode,scheduledPickupStartAt,scheduledPickupEndAt,pickupAddress,pickupDetailAddress,deliveryAddress,deliveryDetailAddress,estimatedDurationSeconds,amount,currency,deliveredAt,createTime。用户列表不返回联系人、电话、精确坐标、照片、日志或计价审计字段。
骑手列表摘要固定字段为:id,orderNo,serviceType,status,packageType,packageSize,deliveryMode,scheduledPickupStartAt,scheduledPickupEndAt,pinRequired,pickupAddress,pickupDetailAddress,deliveryAddress,deliveryDetailAddress,pickupDistanceMeters,distanceMeters,estimatedDurationSeconds,amount,currency,createTime。newTask 分页响应额外返回 nearbyTaskCount 和 highestOrderAmount,不返回尖峰倍率或骑手收入字段。
用户创建订单、用户订单详情、中单骑手详情及抢单成功响应的 data 结构为:
{
"id": 101,
"orderNo": "FD1234567890",
"serviceType": "URGENT",
"status": "ACCEPTED",
"packageType": "DOCUMENT",
"packageSize": "SMALL",
"deliveryMode": "NOW",
"scheduledPickupStartAt": null,
"scheduledPickupEndAt": null,
"pinRequired": true,
"pickup": {},
"delivery": {},
"distanceMeters": 4200,
"distanceSource": "ROUTE",
"estimatedDurationSeconds": 900,
"amount": 90,
"currency": "TWD",
"userNote": null,
"acceptedAt": "2026-09-01T10:20:00+08:00",
"pickedUpAt": null,
"deliveredAt": null,
"completedAt": null,
"cancelledAt": null,
"cancelReason": null,
"createTime": "2026-09-01T10:00:00+08:00",
"updateTime": "2026-09-01T10:20:00+08:00",
"senderImageUrls": [
"https://api.example.com/profile/upload/sender-1.jpg"
],
"pickupImageUrls": [],
"deliveryImageUrls": [],
"rider": {
"name": "陈骑手",
"avatar": "https://api.example.com/avatar.jpg",
"rating": 4.9,
"imUserId": "10086",
"longitude": 121.56,
"latitude": 25.03
},
"deliveryPinCode": "4821"
}
senderImageUrls、pickupImageUrls 和 deliveryImageUrls 分别表示寄件、取件和送达图片数组。status、acceptedAt、pickedUpAt、deliveredAt、completedAt 和 cancelledAt 展示进度。deliveryPinCode 只向订单所属用户返回,并且只在启用 PIN 时出现;骑手响应永不返回此字段。rider 只向用户返回。订单未接单时为 null。骑手对象不包含真实电话号码,联系入口使用 imUserId 打开 IM 会话,原型中的通话按钮没有接口支撑。ACCEPTED 或 PICKED_UP 时向用户返回,其他状态下经纬度为 null。平台订单详情是审计专用契约,仍可返回 {order,images,logs};App 不应依赖或解析该结构。
所有接口均要求用户登录 token。
GET /system/flashDelivery/home
响应 data:
{
"services": [
{
"serviceType": "HELP_SEND",
"pricingId": 1,
"startTime": "00:00",
"endTime": "08:00",
"startingDistance": 3.00,
"startingFare": 60,
"distance": 1.00,
"freight": 10,
"pricingVersion": 1,
"currency": "TWD"
}
]
}
只返回当前时间命中运价时段的服务。startTime 包含、endTime 不包含,均为业务当地时间的 HH:mm;24:00 只会作为结束时间。services 为空表示当前时段没有可下单的闪送服务。
POST /system/flashDelivery/quote
请求体:
{
"serviceType": "HELP_SEND",
"packageType": "DOCUMENT",
"packageSize": "SMALL",
"pickup": {
"name": "王小明",
"phone": "0912345678",
"address": "台北市信义区市府路1号",
"addressDetail": "3楼A室",
"city": "台北市",
"area": "信义区",
"handoffMethod": "请电话联系",
"longitude": 121.5645,
"latitude": 25.033
},
"delivery": {
"name": "李小华",
"phone": "0987654321",
"address": "台北市大安区信义路三段56号",
"addressDetail": "1楼",
"city": "台北市",
"area": "大安区",
"handoffMethod": "交给本人",
"longitude": 121.538,
"latitude": 25.0335
}
}
响应 data:
{
"serviceType": "HELP_SEND",
"pricingId": 1,
"startTime": "00:00",
"endTime": "08:00",
"distanceMeters": 4200,
"distanceSource": "ROUTE",
"estimatedDurationSeconds": 900,
"startingDistance": 3.00,
"startingFare": 60,
"distance": 1.00,
"freight": 10,
"billableDistance": 1.20,
"distanceFee": 12,
"amount": 72,
"currency": "TWD",
"pricingVersion": 1
}
计价规则与现有外卖订单一致:先用路线公里数减去 startingDistance;超出不足 0.5 公里时 billableDistance 为 0,达到 0.5 但不足 1 公里时按 1 公里,达到 1 公里后按实际超出距离。里程费用按 billableDistance / distance * freight 计算并四舍五入为整数 TWD,最终 amount = startingFare + distanceFee。预计时长不参与计价,也没有最低价、每分钟价格或尖峰倍率。
报价仅用于展示。创建订单时后端会重新匹配当前运价时段并计算最新路线和金额,因此最终金额可能与先前报价不同。当前时间没有匹配时段时,接口返回“当前时段暂无可用运价”。
POST /system/flashDelivery/orders
请求体在报价请求字段基础上增加:
{
"serviceType": "HELP_SEND",
"packageType": "DOCUMENT",
"packageSize": "SMALL",
"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",
"pinRequired": true,
"senderImageUrls": [
"https://api.example.com/profile/upload/sender-1.jpg"
],
"userNote": "文件请勿折叠"
}
| 新增字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
clientRequestId |
string | 是 | 客户端幂等请求号,去除首尾空格后最长 64 字符 |
deliveryMode |
string | 否 | 不传时默认为 NOW |
scheduledPickupStartAt |
datetime | 预约时必填 | 预约开始时间 |
scheduledPickupEndAt |
datetime | 预约时必填 | 必须比开始时间晚 30 分钟 |
pinRequired |
boolean | 否 | 不传时默认为 true |
senderImageUrls |
string[] | 否 | 寄件图片,最多 9 张 |
userNote |
string | 否 | 最长 500 字符 |
同一用户使用相同 clientRequestId 重试时,后端返回第一次创建的订单,不会重复创建。一次下单动作生成一个请求号;网络超时重试必须复用原请求号,新下单必须生成新请求号。使用旧请求号但修改请求体,仍会返回旧订单。
成功响应 data 为完整详情对象,初始状态为 WAITING_ACCEPTANCE。创建响应中的 amount 是最终整数订单金额。
GET /system/flashDelivery/orders?page=1&size=10
查询参数:
| 参数 | 必填 | 说明 |
|---|---|---|
page |
否 | 默认 1,小于 1 时按 1 处理 |
size |
否 | 默认 10,范围为 1 至 100 |
仅查询当前用户,按创建时间倒序返回全部状态的订单摘要。接口不接受 status、scene 或 serviceType;响应 data.records 中每项为用户列表摘要对象。
设计原型中的“待接单、配送中、已完成、已取消”筛选页签当前没有对应查询参数。第一版建议只展示“全部”列表;如需页签,只能基于当前页数据本地过滤,且不应依赖它得到准确的分页总数。
GET /system/flashDelivery/orders/{id}
仅订单所属用户可访问。响应 data 直接为 App 完整订单字段,包括订单快照、三类图片数组、骑手摘要和可选的交付 PIN,不返回原始状态日志。响应不包含支付状态或支付方式字段,详情页不要展示“已付款”等支付信息。
POST /system/flashDelivery/orders/{id}/cancel
请求体:
{
"reason": "行程有变,不需要配送"
}
reason 必填,去除首尾空格后不能为空,最长 500 字符。WAITING_ACCEPTANCE 和 ACCEPTED 状态允许用户取消。PICKED_UP 之后需要平台介入,用户端不能直接取消。POST /system/flashDelivery/orders/{id}/confirmReceipt
无请求体。仅 DELIVERED 状态可操作,成功后状态变为 COMPLETED。
所有接口均要求骑手登录 token,且账号 userType 必须为 2。
GET /system/flashDelivery/rider/orders?page=1&size=10&tab=newTask&longitude=121.5&latitude=25.0
查询参数:
| 参数 | 必填 | 说明 |
|---|---|---|
page |
否 | 默认 1,小于 1 时按 1 处理 |
size |
否 | 默认 10,范围为 1 至 100 |
tab |
否 | 默认 newTask;可选 newTask、toPickup、delivering、completed 或 cancelled |
longitude |
否 | 骑手当前位置经度;newTask 传入时用于附近范围、取件点距离和排序,范围 -180 至 180 |
latitude |
否 | 骑手当前位置纬度;newTask 传入时用于附近范围、取件点距离和排序,范围 -90 至 90 |
页签映射:
tab |
对应状态 | 查询范围 |
|---|---|---|
newTask |
WAITING_ACCEPTANCE |
当前可抢任务 |
toPickup |
ACCEPTED |
当前骑手本人任务 |
delivering |
PICKED_UP |
当前骑手本人任务 |
completed |
DELIVERED、COMPLETED |
当前骑手本人任务 |
cancelled |
CANCELLED |
当前骑手本人任务 |
除 newTask 外只查询当前骑手本人任务。闪送没有退款流程,不提供外卖列表中的 refund 页签。
newTask 的 longitude 和 latitude 仅用于附近范围筛选、计算取件点距离和排序;其他页签忽略坐标。列表按页签和骑手范围完成服务端过滤后再分页,不由 App 拉取完整集合后过滤。
newTask 分页响应的 data 除 records、total、current、size 外,还返回 nearbyTaskCount 和 highestOrderAmount。不返回尖峰倍率或骑手收入字段。amount 是用户支付的订单金额,页面文案不得表述为“预估收益”或“收益”;nearbyTaskCount 是附近待抢订单数,不是上线骑手数。
所有页签的 data.records 使用骑手列表摘要字段:
{
"id": 101,
"orderNo": "FD1234567890",
"serviceType": "URGENT",
"status": "WAITING_ACCEPTANCE",
"packageType": "DOCUMENT",
"packageSize": "SMALL",
"deliveryMode": "NOW",
"scheduledPickupStartAt": null,
"scheduledPickupEndAt": null,
"pinRequired": true,
"pickupAddress": "台北市信义区市府路1号",
"pickupDetailAddress": "3楼A室",
"deliveryAddress": "台北市大安区信义路三段56号",
"deliveryDetailAddress": "1楼",
"pickupDistanceMeters": 420,
"distanceMeters": 4200,
"estimatedDurationSeconds": 900,
"amount": 90,
"currency": "TWD",
"createTime": "2026-09-01T09:00:00+08:00"
}
接单前列表可展示完整的取件、送达文字地址(包括详细地址),但不得返回联系人、电话、实际 PIN、精确坐标、用户备注、图片凭证、状态日志、用户 ID、幂等号或计价审计字段。列表中的文字地址不能作为精确坐标使用。
GET /system/flashDelivery/rider/orders/{id}
响应 data 始终直接返回订单字段,顶层结构保持稳定,不使用 {order,images,logs} 包装,也不要求 App 判断 data.order。接单前隐藏联系人、电话、实际 PIN、精确坐标和履约图片;联系人姓名与电话一样都不返回,列表和详情不要按设计原型渲染“·联系人姓名”。当前骑手接单后,详情接口才补齐其有权限查看的完整履约信息。
POST /system/flashDelivery/rider/orders/{id}/accept
无请求体。抢单成功后状态变为 ACCEPTED,响应 data 直接返回完整订单字段;订单已被其他骑手抢走时返回“订单已被其他骑手接走”。
POST /system/flashDelivery/rider/orders/{id}/pickup
请求体:
{
"imageUrls": [
"https://api.example.com/profile/upload/pickup-1.jpg"
]
}
仅订单骑手可在 ACCEPTED 状态调用。图片至少 1 张、最多 9 张;成功后状态变为 PICKED_UP。
POST /system/flashDelivery/rider/orders/{id}/deliver
启用 PIN 的订单:
{
"imageUrls": [
"https://api.example.com/profile/upload/delivery-1.jpg"
],
"pinCode": "4821"
}
未启用 PIN 的订单可不传 pinCode:
{
"imageUrls": [
"https://api.example.com/profile/upload/delivery-1.jpg"
]
}
仅订单骑手可在 PICKED_UP 状态调用。图片至少 1 张、最多 9 张。PIN 校验失败时不会保存送达图片,也不会改变订单状态;成功后状态变为 DELIVERED。
地址簿由闪送和现有收货业务共用。以下接口都要求用户登录 token,并且只能操作当前用户自己的地址。
GET /system/address/getaddress?keyword=王小明
keyword 可选,同时搜索姓名、电话、主地址和详细地址。置顶地址优先,响应 data 为地址数组。
GET /system/address/getaddressxq?id={addressId}
响应 data 为地址对象。
POST /system/address/address
新增地址不传 id;修改地址传本人地址的 id:
{
"id": null,
"name": "王小明",
"phone": "0912345678",
"address": "台北市信义区市府路1号",
"addressDetail": "3楼A室",
"longitude": 121.5645,
"latitude": 25.033,
"country": "TW",
"province": "台北市",
"city": "台北市",
"area": "信义区",
"annexes": null
}
| 字段 | 必填 | 规则 |
|---|---|---|
name |
是 | 最长 64 字符 |
phone |
是 | 最长 32 字符 |
address |
是 | 最长 255 字符 |
addressDetail |
否 | 最长 255 字符 |
longitude |
是 | -180 至 180 |
latitude |
是 | -90 至 90 |
country、province、city、area |
否 | 各最长 64 字符 |
annexes |
否 | 最长 1000 字符 |
后端忽略客户端身份字段,地址所有者始终取自 token。保存成功后 data 返回保存后的地址对象。
地址簿对象不含 handoffMethod。把地址用于闪送报价或下单时,需要映射联系人、地址和坐标,并按本次订单另行填写交接方式。
DELETE /system/address/{id}
无请求体,仅可删除本人地址。
POST /system/address/{id}/top
无请求体。置顶只影响当前用户地址簿的排序。
msg 含义 |
常见原因 | App 处理建议 |
|---|---|---|
| token 已过期 | 登录态失效 | 清理登录态并重新登录 |
| 当前时段暂无可用运价 | 当前时间没有匹配所选服务的运价时段 | 刷新首页服务列表或稍后重试 |
| 取件地址和收件地址不能相同 | 地址文本相同或经纬度完全相同 | 要求用户修改地址 |
| 配送距离不能超过 40 公里 | 服务端路线距离超限 | 提示当前路线不可下单 |
| 预约取件时段无效 | 时间已过、超过三天或不是 30 分钟 | 重新选择预约时段 |
| 订单已被其他骑手接走 | 并发抢单失败 | 刷新待抢列表 |
| 当前订单状态不允许此操作 | 页面状态已过期或重复操作 | 重新拉取订单详情 |
| 交付 PIN 不正确 | 骑手提交 PIN 错误 | 保留页面并重新输入 PIN |
| 闪送订单不存在或无权访问 | ID 不存在或不属于当前账号 | 返回列表并刷新数据 |
| 凭证图片地址无效 | URL 不是完整 HTTP(S) 地址 | 检查上传结果并补全资源域名 |
/home 返回的当前时段可用服务,不在 App 中维护启停状态或默认价格。clientRequestId 重试策略。code 判断成功或失败。data.records 和 data.total 取值。ACCEPTED -> PICKED_UP -> DELIVERED 顺序操作。