物流状态更新怎么拿:Webhook 推送 vs 定时轮询
2026-07-26 · 阅读约 6 分钟
要让系统里的物流状态保持最新,通常只有两条路:你主动定时去查(轮询), 或者让服务在状态变化时主动推给你(Webhook)。这篇不堆代码,重点讲两者的取舍—— 实时性、请求量、成本、实现难度分别差在哪,以及什么场景该选哪个。轮询给出可运行的查询代码, Webhook 讲清概念,具体订阅方式指向接口文档。
一、定时轮询:你主动去问
轮询就是每隔一段时间调用一次查询接口,看状态有没有变。实现最简单——一个定时任务加一次
POST /v1/tracking/trace 就够了。关键设计不在于「怎么发请求」,而在于查哪些、多久查一次、什么时候停:
已到终态(签收 / 退回)的单子就该移出队列,别再浪费额度。
import time, requests
API_URL = "https://api.kuaidichaxunapi.com/v1/tracking/trace"
HEADERS = {"Authorization": f"Bearer {KEY}:{SECRET}",
"Content-Type": "application/json"}
# 待跟踪的运单(真实系统里放数据库,而不是内存)
pending = [
{"courierCode": "cainiao", "trackingNumber": "CGD0000123456"},
{"courierCode": "sf", "trackingNumber": "SF9900001234567"},
]
def poll_once(items):
# 一次最多 10 个,按批查
resp = requests.post(API_URL, headers=HEADERS,
json={"items": items[:10]}, timeout=10)
resp.raise_for_status()
done = []
for r in resp.json()["data"]["results"]:
if r["success"] and r["data"]["isDelivered"]:
done.append(r["data"]["trackingNumber"]) # 已签收,移出队列
return done
while pending:
finished = poll_once(pending)
pending = [x for x in pending if x["trackingNumber"] not in finished]
time.sleep(30 * 60) # 每 30 分钟一轮;到终态的不再查 轮询的痛点很直白:状态没变也照查。多数时间包裹「运输中」一动不动,可你每一轮还是要发请求, 额度和请求数都花在了「确认它没变」上。间隔调短,实时性好但更费额度;间隔调长,省额度但延迟大。
二、Webhook 推送:让服务来找你
Webhook(订阅式推送)反过来:你在服务里登记一个接收地址,当某个运单的物流状态发生变化时,
服务端主动把最新状态 POST 到你的地址,你不用反复轮询。好处是明显的——近实时、
只在变化时才有一次请求,既省额度也省掉了满地的定时任务。本服务支持这种推送,
具体的订阅方式、回调携带的字段与安全校验方式,以接口文档为准(本文不臆造端点路径)。
代价在接收端:Webhook 需要你付出一些基础设施与健壮性上的工作——
- 公网可达的端点:得有一个能被外网访问的 HTTPS 接收地址,本地开发时还要用内网穿透之类的工具调试。
- 去重与幂等:推送可能重复送达,接收端要按运单号 + 状态做幂等,避免重复处理。
- 验签与鉴权:要校验请求确实来自服务方,而不是别人伪造,具体校验方式见文档。
- 快速返回:收到后应尽快回 2xx 再异步处理,处理太慢可能触发服务端重推。
换句话说,Webhook 把「反复查」的成本,换成了「建一个可靠接收端」的一次性成本。
三、两种方式对比
| 维度 | 定时轮询 | Webhook 推送 |
|---|---|---|
| 实时性 | 取决于轮询间隔,通常分钟级延迟 | 状态一变即推,接近实时 |
| 请求量 / 额度 | 没变化也反复查,浪费明显 | 仅在变化时产生一次推送,省额度 |
| 实现复杂度 | 低,一个定时任务即可 | 较高,需接收端 + 去重 + 验签 |
| 基础设施 | 只要能发出请求 | 需公网可达的接收服务 |
| 掌控与调试 | 主动发起,易本地重放调试 | 被动接收,靠日志排查 |
| 失败恢复 | 下一轮自动补上 | 依赖服务端重推 + 自己的兜底对账 |
| 适用场景 | 单量小、能接受分钟级延迟 | 单量大、要及时通知用户 |
四、什么时候用轮询
- 在跟踪的包裹不多,几十上百个,分钟级延迟完全可以接受;
- 不想(或不方便)暴露一个公网接收端点,比如纯内网的后台脚本;
- 想快速上线,先用最简单的方式把功能跑起来;
- 只是做对账 / 批处理,本来就是定时批量拉一次的节奏。
五、什么时候用 Webhook
- 在途包裹数量大,轮询的请求量和额度开销已经不划算;
- 业务要求「一签收就通知用户 / 触发下一步」,对延迟敏感;
- 希望少维护定时任务,让系统由事件驱动;
- 已经有一套稳定的接收服务,加一个回调端点成本不高。
六、务实的选择:推送为主,轮询兜底
两者并非二选一。生产环境常见的稳妥做法是混合:以 Webhook 拿到实时性, 再用一个低频轮询做兜底对账——比如每天对仍在途的单子扫一遍, 补上个别可能漏掉的推送。还可以按单子活跃度分档:新单、活跃单走推送,长期不动的单子降低甚至暂停轮询。
一个实用的上手顺序是:先用轮询把功能跑通(成本最低、最好调试),等在途单量涨上来、 或对延迟有了更高要求,再引入 Webhook 把主链路换成推送、轮询退居兜底。
轮询用的查询接口,可参考对接指南与接口文档; Webhook 的订阅方式与回调字段同样见接口文档。无论走哪条路, 免费额度每月 10000 次,邮箱注册即可、无需企业认证——先注册拿密钥,或用首页在线演示试跑一遍。