快递查询API

← 技术博客

物流状态更新怎么拿: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 次,邮箱注册即可、无需企业认证——先注册拿密钥,或用首页在线演示试跑一遍。