209 家快递协议收敛成一个门面:global-logistics 接入笔记
问题场景
做跨境订单轨迹,最烦的不是快递不送到,而是每家的接口协议都不一样:有的要 OAuth2,有的是签名,报文 XML/JSON 混用,状态语义各说各话。接 4 家就得维护 4 套鉴权和解析逻辑,DHL / FedEx / UPS 这种还各自有独立的认证流程。
global-logistics 是一个 PHP Composer 包,把“哪家快递、走国内还是国际、返回什么形状的数据”这些差异收敛到一层门面后面。业务方只传一个单号,它自动识别承运商并返回统一结构的 Tracking / TrackingEvent。
收敛逻辑
整体是“门面 + 注册表 + 适配器”:
- Detector 内置 187 条单号正则规则,顺序敏感,优先命中国内通道,输出「通道 + 承运商代码」。
- CarrierFactory 按通道 → 代码 → 适配器类的注册表实例化适配器,统一注入配置与 HTTP 客户端。
- 各适配器实现 CarrierInterface,各自处理 OAuth2、签名、XML/JSON 和状态映射,最终输出统一模型。
Logistics静态门面是唯一入口。
已内置 209 家承运商:国内 45 家,国际 164 家(DHL / FedEx / UPS / USPS、各国邮政 S10)。
值得注意的设计
- 状态统一为 TrackStatus 7 种枚举:待揽收 / 运输中 / 派送中 / 已签收 / 异常 / 退回 / 未知。业务层不用再做一层状态翻译。
- 密钥零硬编码,各家密钥全部经配置注入,
config/logistics.php里有 209 家的密钥占位模板。 - HTTP 层是 PSR-18:
OAuthTokenClient负责 OAuth2 token 懒加载与缓存,RetryingClient做失败重试。默认 Guzzle,可替换为任意 PSR-18 客户端。 - 框架自动发现:Laravel / ThinkPHP 8 / Hyperf / Webman / Yii 2。
- 支持回调签名验证
verifyCallbackSignature(),承运商订阅推送时校验来源。 - 统一异常体系:认证失败 / 单号不存在 / 网络错误 / 承运商未注册 / 接口错误,可统一捕获。
二次开发相关路径
src/Carriers/Domestic/ # 国内 45 家适配器
src/Carriers/International/ # 国际 164 家适配器
src/Resources/carrier-registry.php # 209 家承运商注册表
src/Resources/detector-rules.php # 187 条单号规则
src/Framework/ # 各框架自动发现
config/logistics.php # 密钥配置模板
docs/superpowers/ # 设计规格与实施计划
tests/fixtures/ # 各承运商 track / empty / error 夹具
新增承运商的路子就是照模板补一个适配器,再补两条注册信息,工作量在预期范围内。
快速开始
...bash
composer require erikwang2013/global-logistics
...php
use GlobalLogistics\Logistics;
Logistics::configure([ /* 各家密钥经配置注入,如 sf / dhl 等 */ ]);
$tracking = Logistics::track('SF1234567890');
echo $tracking->status->name; // DELIVERED
echo $tracking->latestDescription; // 快件已签收
密钥建议通过环境变量或框架 .env 注入,别写进仓库。
边界与不适用场景
- 环境要求 PHP 8.2+,Composer 依赖时留意。
- 不调用
configure()时门面以空配置初始化,只支持无需密钥的承运商。 - 单号识别依赖内置 187 条规则;规则覆盖不到时,仍需用
domestic()/international()显式指定承运商。 - 各家承运商原始扩展字段是否透传、具体状态映射细节,原文未提供;需要以对应适配器实现和
tests/fixtures为准。
测试
项目自带 1663 个测试用例、6662 条断言,不依赖真实密钥可跑全量测试。
以上为个人使用/理解记录,仅供参考。