集成选型指南

EDI 还是 Shipping API:你的 3PL 需要哪一个,什么时候两个都要

EDI 和 Shipping API 常被放进同一张对比表里,但它们并不在同一条轨道上。EDI 承载的是客户要求你遵守的业务规则,Shipping API 承载的是承运商实际允许你完成的执行动作。真正要回答的问题不是哪一个更先进,而是哪一种失败你承受得起,以及它发生的时候谁来付这笔钱。

下面用一个具体场景把整条判断链走完:一家已经在正常发货的 3PL,新客户的对接口要求它交换 940 和 945,团队需要弄清楚缺的是哪一环、由谁补上、以及怎样证明整个闭环真的合上了,而不只是证明自己的软件没有报错。

读完之后,你应该能把客户提出的要求写成一张可验收的表,能用失败成本而不是技术代际做选择,并且能在两套系统同时运行时,找到那个必须是唯一的事实来源的对账点。

编辑插画:仓库办公区被分成两半,左边是桌面上摊着单据和打印表格的办公桌,右边是放着包裹、面单打印机和手持扫描枪的打包台,一个小人拿着单页纸走在两半之间,米白背景配一处橙色点缀,构图刻意不对称并带纸纹
两套系统,两种工作,一张纸在中间来回走

一家已经在发货的 3PL,和一位要 940 与 945 的客户

先假设一家跑中型履约业务的 3PL(这是一个明确标注的假设场景,不是某家公司的实录)。它已经把发货里最难的那部分做对了:跨承运商比价、买面单、在打包台打印出来,包裹离开月台几分钟内就把 tracking number 回传给客户的网店。按任何合理的定义,这个仓已经在发货了。

然后一个新客户进来,它的对接口里要两份单据:940 和 945。X12 把 940 定义为 Warehouse Shipping Order,也就是客户发给仓库的出库指令(X12 940 说明);945 是 Warehouse Shipping Advice,仓库回给相关方、确认货已发出的通知,同时带上订购数量和实际发货数量(X12 945 说明)。两份都不是关于面单、费率或 tracking number 的。它们关于客户的业务流程:他让你做了什么,以及你确认你做了什么。

也正是在这一点上,问题通常被问错了形式:「我们到底要 EDI 还是要 API?」团队真正需要回答的问题更窄也更有用:链条上缺的是哪一环?每一环由谁负责提供?以及怎样证明整个环闭合并上了,而不只是证明软件返回了成功码?

一条边界,先说清能省很多返工:交换哪些单据、用哪个版本、带哪些字段、在什么截止时间之前提交,这些都是逐个交易伙伴谈出来的结果。不存在一套所有 3PL 都必须采用的通用单据集,也没有任何外部供应商能替你判断客户的收货流程会接受什么。这篇指南讲的是怎么判断,不是怎么测接口调用,接口层的测试方法在另一篇 WMS 与发货 API 集成测试指南里。

「EDI 老了、API 新」回答的是错的问题

这个说法听起来很务实,实际上是把四个具体问题替换成了一个技术偏好。四个问题分别是:交易伙伴接受哪些单据和哪些交互方式;哪个系统掌握「货真的离开了这栋楼」这条记录;哪个接口负责承运商报价与发货执行;以及返回的信息是否足以完成对方真正要求的业务流程。

这四个问题之所以必须分开问,是因为五个不同的事件经常被当成同一个。它们按顺序发生,由不同系统做出断言,而只有最后一个才是客户流程真正在等的那个。

流程图:五个事件按顺序排列,接口返回成功由 Shipping API 断言,面单生成由 Shipping API 断言,货物离开货位由 WMS 断言,承运商接收包裹由承运商断言,交易伙伴接受单据由客户系统断言
五个事件,五次不同的断言;只有最后一个才结束 940 带来的义务

接口返回成功只说明请求被理解了。它不说明面单有效,不说明货被拣了,更不说明客户系统已经接受了发货通知。面单存在只说明一个标识被占用了;承运商的第一次扫描才说明包裹真的进了网络。链条上最后一个事件才结束 940 带来的义务。

997 在 EDI 方向上暴露的是同一个陷阱。997 Functional Acknowledgment 报告的是单据的语法检查结果,也就是报文和交易集是否收到、能否被解析(997 回执的语义)。它不是业务接受,也不是发货确认。把它当成这两者中的任何一个,就会得到那句经典又昂贵的误读:「我们收到 997 了,这单就算处理完了。」

这条区分决定了责任能不能分派下去。当客户问为什么从没收到 ASN,而你的团队回答「我们的接口返回了成功」,双方说的是两个不同的事件,再争论也对不上。它也解释了一个真实运营里反复出现的模式:当已发数量、单据和 tracking 开始互相矛盾时,团队往往开始考虑换供应商。供应商通常没问题,坏掉的是事件触发器,通常是决定「单据什么时候生成、货物必须处在什么状态它才成立」的那一个。

先填满四列,再决定任何事

在选路之前,先把要求写成一张表:一条要求一行,横向四列。这张表就是整篇文章的工作工具,也是后面每一次争论的裁判。

要求 依赖的事件 由哪个系统负责 闭合闭环的证据
940 出库指令被接收并校验订单收到、解析、被 WMS 接受3PL 的 WMS,经由 EDI 转换层文档控制号对应到一条 WMS 订单号
945 发货通知被回传已拣货、已包装、已交接3PL 的 WMS,经由转换层945 带逐行实发数量,并能回到那张 940
发给客户或零售商的 856 ASN已用承运商完成交接EDI 转换层,数据来自发货接口实物标签上的 SSCC-18 与 ASN 内的编码逐字一致
面单与 tracking 数据承运商接受了这次面单购买发货接口有效的 tracking number,且面单未被作废
库存变动回传每次发货之后的库存移动WMS 到转换层每个 SKU 的调整数量与时间戳

实践中最常断掉的是 ASN 那一行。印在纸箱上的序列货运容器编码,必须和电子单据里携带的编码完全一致,不一致就是收货失败,不是数据质量问题(GS1-128 与 SSCC 标签要求)。

每一列的颗粒度都要拆到位。要求那一列,要拆到单据、版本、字段、提交时点,以及对方期待的受理反馈;事件那一列,要拆到接单、变更、取消、部分出库、面单生成、承运商交接、送达;责任那一列,每一格都要落到一个具体的系统名上,品牌方的 ERP、3PL 的 WMS、EDI 转换层、发货接口、承运商;证据那一列,要列出足以让一个陌生人重建事情经过的记录:文档控制号、订单号与包裹号、有效 tracking number、实际发货数量,以及处理与重试日志。

让这张表真正有牙齿的规则是这一条:某一行的证据列你填不出来,这条要求你现在就接不了。它会在生产环境里失败,而且失败得很难争辩,因为什么都没被记下来。

还有一点要记住:这张表是按交易伙伴分别填的。同一个 3PL 的两个零售客户,完全可能要求不同的单据组合、不同的版本和不同的截止窗口。从一段关系复制到另一段关系的模板是猜测,不是配置。

失败成本到底落在谁头上

两个接口真正有用的差别不是速度,也不是新旧,而是错误的形状。

EDI 是批量对账式的。单据以文件形式批量到达、批量解析,错误在物理事件的下游才浮出来。一份错误的 945、一份缺失的 ASN、或者一张标识不对的面单,通常是在卡车已经开到收货码头时才被发现,更糟的情况是几周后出现在一份回款明细的扣款项里。到那时货已经动了,人工已经花了,只能事后补救。

零售合规体系把这笔成本写得比想象中具体,而不是停留在理论上。公开的扣款规则把 OTIF 未达标、ASN 错误和标签违规分别列为独立的扣款类别,其中 OTIF 罚款常被引用的量级是订单金额的 1% 到 3%(见这份零售商扣款类别汇总);而 ASN 规则的方向是收紧而不是放宽,公开的供应商合规指南已经把 ASN 可用率、ASN 准确率和实物条码准确率拆成单独的计分项(见这份供应商合规指南)。

发货接口是实时逐单式的。一次失败的调用在失败的那一刻就被发现,此时包裹还不存在。你可以重试、改走另一家承运商,或者停下来让人看一眼。所以单次接口失败很便宜。但便宜不等于安全:一个静默重试的循环把同一张面单买了两次,或者一次报价调用在整批订单上悄悄回退到默认服务档位,都会在没人注意的情况下,把逐单问题变成批量问题。

失败模式 影响范围 被发现的位置 谁承担成本 补救动作
同一条发货指令被处理两次一张订单发了两次月台上,出现两箱时3PL,直到它能证明这是重复件进来的指令单据上加幂等键
ASN 迟交或从未发出整批货在收货处被拒或被扣款客户收货码头品牌方,然后转嫁回链条上游在交接时而不是打包时生成 ASN
标签标识与 ASN 不一致整批货在门口被拒收收货月台门口看合同约定,通常是 3PL在打印时校验 SSCC-18,而不是打包时
面单作废重出,新 tracking number 没有回传客户看到的是一张已发货订单的过期 tracking几天后的一张客服工单3PL,外加品牌方的口碑把 tracking 变更做成一个事件,喂给单据层
部分出库,但没有任何单据反映它订单显示为全部发出月底对账时3PL945 带逐行实发数量,并补一份新的 ASN
静默重试把同一张面单买两次成本问题,不是履约问题,直到账单到来账单复核时3PL面单购买做幂等,并加重复告警

这张表的重点在第四列。在判断哪个接口「更好」之前,先确认你的运营能吸收哪些失败、哪些会落到一个事后会给你开账单的人头上。真正拉开差距的是第二列:接口错误赔一个包裹,单据错误赔一整票货,或者赔掉一次收货预约。

四种结果:你现在的状况该走哪条路

大多数 3PL 需要的不是一个技术结论,而是一个和现状匹配的方向。下面四种情况覆盖了大多数案例。

当前状况 应优先采取的路径
客户没有 EDI 要求,现有接口已经满足业务交换按实际发货需求评估发货接口,不要因为订单量增长就自动启动 EDI 项目
客户明确要求 EDI,仓库已经能完成承运商发货补齐文档转换、交易伙伴映射和验收测试,缺口不在发货这一侧
EDI 交换已经正常,但缺少所需承运商或比价能力补一层运输执行能力,不要重做一个已经跑通的文件层
两种能力都有,但已发数量、单据和 tracking 对不上先检查事件触发与 ID 映射,再考虑是否更换供应商
流程图:第一个问题是有没有交易伙伴要求 EDI 单据,答是则问仓库是否已能完成承运商发货,能则补文档层,不能则两者都要按序上;答否则问是否需要逐单比价,需要则只要 Shipping API,不需要则暂时都上
三个问题进,四种结果出;先问有没有外部强制,再问执行缺口

「暂时都不需要」值得被明确写出来,因为它是一个合法答案。一个只服务少数 DTC 品牌、只用一两家承运商、没有零售合规要求、发货量还不足以支撑伙伴接入与字段映射成本的仓库,不需要 EDI 项目。它需要的是可靠的承运商执行和干净的记录。EDI 变成必须,是因为外部有人强制要求它,而不是因为仓库长大了。

判断顺序在任何规模上都一样:第一,有没有外部强制,也就是有没有一个交易伙伴的流程要求这些单据;第二,有没有现有技术栈覆盖不到的运输执行需求,比如逐单对比、增加承运商、服务档位选择;第三,也只有第三,两套系统是否需要互相对账,这是一个设计问题,不是采购问题。

成本,以及两套并跑时的那个对账点

成本对比总是以同一种方式出错:拿接口的按次调用价格去比 EDI 的订阅费,然后到此为止。真正吃钱的项都没进来。伙伴接入、字段映射、和对方团队一起做的端到端测试、伙伴改版本或加字段之后的持续维护,以及每次单据在生产环境失败后的异常处理。接口那一侧对应的隐藏项是集成工作量、监控,以及自动重试解决不了、需要人工去处理的那些失败。要比的是在明确期限内每单的总持有成本,不是每笔交易的标价。

两套同时跑的时候,分工是干净的,而且值得写下来:EDI 负责你向客户做出的承诺,也就是出库指令、发货通知、ASN 和库存回传。执行层则负责在承运商那里完成动作:买面单、拿 tracking、交接、以及选择走哪个服务档位。不要让任何一方去干另一方的活。

最容易出问题的正是分工模糊的那一块:如果发货接口悄悄变成了「已发数量」的事实来源,而 945 报的是另一套数字,那么下面这个陷阱就已经形成了。

编辑插画:零售商收货月台,一名工人在卷帘门前一手拿夹板一手拿扫描枪,身旁码着托盘纸箱,最近的一只箱子上能看到标签,传送带向仓库深处延伸,米白背景配一处橙色点缀,构图轻微不对称并带纸纹,安静的纪实感
单据错误的账单,通常是在这里生成的

修法是一个事件、一条记录。把「这票货存在了」这唯一的时刻定义清楚,在那一点写记录,然后让两边都从这一条记录读数。这条记录同时带着文档控制号、订单号、包裹号和 tracking number,任何一方都能从客户的一个问题一路走到一个具体的包裹。这是订单、发货、包裹与面单的数据模型里讲的同一套标识纪律,也是运费与发货运营的 RACI里讲的同一个归属问题。

对账必须发生在事件触发点上,而不是发生在报表里。报表告诉你数字已经不一致了,通常已经太晚,改不了原因;触发点在对的时刻开火,分歧根本不会被创建出来。如果一个仓库每个月都要靠人工把单据和发货记录对一遍,正确的下一步是去找那个缺失的触发器,而不是加人手去做报表。

最后一个实际问题:两套系统之间的边界要划在哪里。一个渠道中立的运输层可以承担承运商那一侧的全部执行,让 EDI 转换层只负责对客户的单据承诺(了解这层执行能力)。边界划清之后,判断「要不要补 EDI」和「要不要扩承运商覆盖」就变成了两个互不干扰的决定,这也是先上门户还是先上 API这类上线顺序问题背后的同一件事。

验收:四个失败场景

一个流程不是靠一次成功的发货证明的,而是靠它怎么恢复。四个场景覆盖了单据与承运商链条最常见的中断方式,每一个都应该有一份写好的答案,回答三个问题:谁处理、保留什么关联、怎样确认恢复完成。

失败场景 谁处理 保留什么关联 怎样确认恢复完成
同一条发货指令到达两次WMS 通过订单参考号识别重复并拦住第二条,单据层抑制重复回执伙伴的文档控制号,加上映射到同一条发货记录的内部订单号第二条单据在日志里被标记为重复处理,且 WMS 里只存在一条发货记录
一张订单只发出一部分商品WMS 按包裹分组各建一条发货记录,单据层发送带逐行实发数量的发货通知原始订单号、行标识,以及每个包裹号绑定的 tracking number发货通知、ASN 与 WMS 记录里的订购数量与实发数量逐行一致
面单作废后重出一张,tracking number 变了发货接口作废并重出,异常或 tracking 变更事件被路由到单据层包裹号不变,tracking number 带版本,两个值都保留客户系统里显示的是当前有效的 tracking number,且替换过程在事件历史里可查
货已经发出,但回传单据失败由异常队列负责,门户里留一个人工检查点,承运商交接不重复执行交接时创建的发货记录、文档控制号,以及处理日志条目单据重试或重发成功,发货记录在实物侧和单据侧都显示为已完成

关于怎么用这张表,有两点说明。第一,这些是业务验收,不是集成测试,接口层的测试机制属于WMS 与发货 API 测试指南的范围。第二,要拿客户真实的单据和识别码来跑,不要用团队自己编的测试数据,生产环境里真正会出问题的地方,来自真实的伙伴格式。

其中两个场景值得单独展开:面单作废重出之后会发生什么,在未使用与已作废面单那篇里有更细的运营口径;把一张订单拆成多次发货的真实成本,在分批发货成本框架里算过一遍。至于决定一票货到底能不能报成「已发货」的状态语义,见订单状态与追踪状态那篇。

一个季度能做完的四步

这是一个顺序,不是一份菜单。每一步都假设上一步已经稳定。

第一步,把承运商执行路径仪表化。先做一家承运商的比价、面单和 tracking 调用,并让日志记下请求了什么、返回了什么、重试了什么。没有这份日志,之后每一次分歧都只是观点之争。

第二步,搭起面向客户的单据通路。转换、伙伴映射,以及一轮和对方一起跑的测试,结尾要拿到对方书面的接受结论,而不是你自己这边的结论。如果两个客户要求不同的单据组合,一次做一个。

第三步,在上量之前先把这个对账事件建好。定义清楚哪一个时刻创建发货记录,让单据层和报表层都从这条记录读数。跳过这一步的仓库,会在第一个旺季发现问题,而那时候已经没有任何时间做设计了。

第四步,故意去测失败路径。发一条重复指令、在拣货中途取消订单、打印之后作废面单、刻意打断出站单据然后看队列怎么反应。顺利路径只能证明集成是存在的,失败路径才能证明这套运营真的能跑。

三个常见的误判值得在这里收口。「客户说要 EDI,所以我们只需要 EDI」:客户的要求覆盖的是单据,它没说仓库能不能比价、能不能打出合规标签、能不能产出 ASN 必须携带的 tracking 数据;一个建在无法产出这些值的执行层之上的单据层,会生成形式上正确、事实上错误的单据。「我们有接口,所以我们已经集成了」:一次接口集成覆盖的是承运商执行,它不会创建订单记录、不会生成 ASN 或发货通知,也不会在客户的收货预约有风险时提醒任何人。「两套系统都上线了,所以我们就安全了」:覆盖率是记录的属性,不是连接的属性;两套互相矛盾的系统比一套加人工复核更糟,因为分歧在有人被扣款之前都是看不见的。

现在回到开头那个仓库:手里拿着客户对 940 和 945 的要求,旁边是一台工作正常的面单打印机。决定下一步的问题不是哪个技术更新,而是:如果这条链条今晚断掉,谁会知道、什么时候知道、最后由谁买单。把这三个问题答清楚,EDI、Shipping API 还是两者都要,就不再是一场争论,而是一份规格说明。如果缺口在承运商执行那一侧,可以从自建集成与采购方案的对比接着往下看。

常见问题

不是。客户的要求覆盖的是单据,它不覆盖这些单据里必须携带的数据从哪里来。ASN 里要放 tracking number 和包裹标识,945 里要放逐行实发数量,这些值都产生在承运商执行层。如果执行层产不出这些值,单据会形式上正确、事实上错误。缺的往往不是 EDI 项目,而是执行层。
940 是客户发给仓库的出库指令,方向是从买方系统到仓库;945 是仓库回传的发货通知,方向是从仓库回到客户或相关方,用来确认货已发出,并带上订购数量和实际发货数量。两侧都能承载业务含义,但只有 945 才把「货真的出去了」这件事告诉对方,所以它必须在实物出货之后生成,而不是在打印面单的时候。
不算。997 报告的只是单据的语法检查结果,也就是报文和交易集有没有收到、能不能被解析。它既不表示业务上接受了这份单据,也不表示货已经发出。用 997 去回答「为什么我没收到 ASN」,等于在回答另一个问题,客户不会接受这个答案。
先修事件触发和标识映射,不要先换供应商。绝大多数不一致来自三个可归因的原因:单据生成得太早(面单打印时就生成,而不是交接之后)、部分出库只更新了 WMS 没更新单据、作废与重出被算成两次发货。把「这票货存在了」定义成一个唯一的时刻,让两边都从同一条记录读数,分歧就不会被创建出来。
当没有交易伙伴强制要求单据,而且现有的执行能力已经覆盖真实的发货需求时。只服务少数 DTC 品牌、只用一两家承运商、没有零售合规程序的仓库,需要的是可靠的执行和干净的记录,而不是一套 EDI 程序。EDI 变成必须,是因为外部有人强制它;一个仓不会因为订单变多就自动需要 EDI,只会因为客户的要求变了才需要。

把执行层这一侧变成可核对的数

EasyShippingX 是一个渠道中立的物流层:把美国境内的承运商选项放在一起比较,再通过 Portal、Excel 或 API 执行,具体服务与费率以账户已开通清单为准。上线前按发货仓、目的地和包裹属性核验覆盖与总费用,并用小批量试单确认轨迹、账单和备用路径;自动路由或回退须单独配置并验证。