Skip to content
// 0x
0x07 // 后端实践

从单体到管道:解耦订单同步与发货单创建

背景

最近在重构一个老旧的 Shopify 集成模块,核心是一条 600 多行的 PHP 脚本 sync-orders.php。看名字就知道它只做一件事——同步订单。但当你读进去之后会发现,它其实做了三件完全不同的事:

  1. 从 Shopify API 拉取订单数据
  2. 解析并存入本地数据库
  3. 在 WMS 系统中创建出库单、分配库存批次

这种”顺手把后面的事也做了”的模式在遗留系统中很常见。在初期它确实是高效的——一个脚本搞定所有,部署简单,理解直观。但随着需求增加,这种耦合开始暴露问题。

问题的表现

数据不一致

最直接的触发点是:订单同步是定时任务,而 WMS 系统的出库单表可能因为各种原因不可用。如果同步过程中出库单创建失败,数据就陷入了不一致状态:

订单已存入 (shopify_orders) ✅
出库单创建失败 (shipping)    ❌
库存批次未分配 (lineitem)    ❌

重试整个同步又会导致订单数据重复插入。修复需要手动清理数据再从头跑。

故障半径过大

当仓库同事在操作 WMS 时(比如月底盘点锁表),订单同步定时任务恰好触发,结果整个同步失败——连订单数据都没拉下来。本来订单数据是可以先落地的,出库单可以等锁释放后再处理,但作为一个单体脚本,要么全做要么全不做。

测试困难

一条脚本里混杂了 API 调用和数据库写入,很难单独测试某个环节。想测试”从 Shopify 拉数据”的逻辑,必须先确保 WMS 的表结构和库存数据完整。反过来,想测试”出库单创建”的逻辑,又必须先跑一遍完整的订单同步。

解耦方案

核心思路:从单体脚本变为管道式架构,两个阶段各自独立运行

第一阶段:订单获取 (sync-orders)

只负责:

不再关心 WMS 出库单、库存分配这些事情。

第二阶段:出库单创建 (create-shipments)

只负责:

不关心 Shopify API、GraphQL、网络延迟这些事。

修改前(单体):
  sync-orders.php
    ├─ Shopify API
    ├─ shopify_orders 写入
    ├─ shipping 写入
    ├─ lineitem 写入
    ├─ inventry 批次分配
    └─ 全部或全不

修改后(管道):
  sync-orders.php --orders-only
    ├─ Shopify API
    ├─ shopify_orders 写入
    └─ shopify_lineitem 写入

  create-shipments.php
    ├─ shipping 写入
    ├─ lineitem 写入
    ├─ inventry 批次分配
    └─ order_status → shipment_created

兼容性

旧的一步到位模式通过 sync-orders.php(不带 --orders-only)保留,仍可继续使用。新用户可以选择两步模式,也可以切换到一步到位的旧模式。script.php(web 执行端点)中注册了新脚本,可以通过 UI 按钮触发。

一个意外的收获

在解耦过程中,需要仔细检查脚本中每条 SQL 语句的上下文。这一查才发现,这个脚本一直在往 shipping 表写入硬编码的 owner 值。而在系统的出库单列表中,用户按 owner 过滤数据,导致不同公司的用户看不到自己对应的 Shopify 订单。

更深入一看,三条 P0 安全漏洞同时浮现:

漏洞发现方式
SSL 证书验证全局关闭审阅 ShopifyClient 时发现 CURLOPT_SSL_VERIFYPEER = false
OAuth CSRF state 未校验审阅 callback 时发现 session 存了 token 但从未比较
开放重定向审阅 auth.php 时发现 return_url 没有任何校验

这些漏洞和本次解耦没有直接的因果关系,但它们在同一段代码路径上埋了这么久而未被发现,说明对老代码的”触碰”本身就有安全价值——每次重构都是一次免费的代码审计。

最终效果

解耦后的数据流:

客户在 Shopify 下单

        ▼  sync-orders --orders-only
Shopify 订单数据已落地(不创建出库单)

        ▼  create-shipments(可在不同时间触发)
WMS 出库单 + 库存分配完成

        ▼  仓库拣货发货

测试验证覆盖:

01-sync-orders.sh   ✅ orders=3 lineitems=6 shipments=0
02-create-shipments.sh  ✅ shipments=3 source=shopify owner=correct_company
03-single-order.sh  ✅ order_status preserved

每个阶段可以独立测试、独立重试、独立监控。

总结

解耦订单同步与出库单创建带来的直接好处:

遗留系统的重构很多时候不是引入新功能,而是让已有的功能变得可观测、可控制、可独立失败。这次解耦就是一个小而完整的案例。


Share this post on:

Previous Post
扩展 AI 编码助手的本地能力 — 浏览器自动化与共享终端
Next Post
WMS 与 Shopify 的数据交响:订单同步全链路解析