最近对一个提供 SAAS 装箱算法服务的公司 Paccurate 做了逆向分析。无意间发现了对方的 接口文档 Swagger UI 页面,发现了新大陆。 这种接口文档和平时使用的 YApi 有所不同,使用的是 OPENAI 3.0 规范,然后用 Swagger UI 把 json 可读性再进一步提高,同时能够生成示例报文。这种规范对开发很友好,可以直接交给开发使用工具生成类文件,且自动注释。虽然 YApi 也可以导出成 swaggerjson 用于自动生成类文件,但是目前受限于 YApi 的维护质量,并不能用于自动生成。
Paccurate 是如何提供服务的?
从接口来看,对方只有 1 个接口,结构非常复杂。一切入参都是要调用方提供的,也就是说它卖的是装箱计算,而不是卖一个管理系统。一切用到的入参,包括基础资料、规则等等都要买家自己的系统实现。买家不是简单的做接口对接,而是要先依据 Paccurate 接口提供的能力和自己的业务场景进行匹配分析,然后决定本地系统需要增加哪些管理功能,然后再使用接口让 Paccurate 返回计算结果。 从字段描述上看,可以逆向推断出来它可以支持下面的业务场景、规则、算法可调整的维度、业务约束、结果的可视化。
1. 场景
| 场景 | 实现机制 |
|---|---|
| 从候选箱型中选最优箱 | boxTypes[] + boxTypeChoiceGoal(两种目标:lowest-cost / most-items)+ boxTypeChoiceStyle(actual 真计算 / estimated 快估算) |
| 动态生成「可裁」的箱型 用于自动折箱机 | boxTypeGenerators + xList/xRange/yList/yRange/zList/zRange + limits(按 Metric 约束)+ priceComponents(按 Metric 阶梯定价) |
| 单 SKU 原包装出货 | boxTypeGenerator.operation = pack-as-is,加 price: -1 抑制多物合箱 |
| 基于已装箱再装箱 | boxes[] 输入预装好的箱子,算法会优先填满 |
2. 12 种 Rule 覆盖的业务规则
| Rule | 业务含义 |
|---|---|
| internal-space | 物品内部有可用空间(如花盆里装铅笔),递归嵌套 |
| alternate-dimensions | 同一物品有「替代尺寸」可用(如特殊情况下可以撕了包装装进去) |
| exclude / exclude-all | 物与物互斥(化学品不能和食品混装) |
| pack-as-is | 强制一物一箱(有能直接发货的原厂包装就不再套) |
| irregular(仅 roll) | 卷状物(布卷、纸卷),按外接圆柱 bounding box 处理 |
| lock-orientation | 锁定物品方向(只能朝某个轴摆放) |
| fragile | 易碎品:包裹厚度 / 上压重量上限 / onTopOnly / 优先级互斥 |
| group-pack | 小件按倍数自动合箱(如 8 件装) |
| set-properties | 运行时改写物品 property(驱动 propertyConstraints) |
| pack-sequence | 多阶段装箱:kitting / 内盒外箱 / 托盘装车,reduce 子枚举 default / pack-as-is / box-to-item / box-to-item-optional,支持 key 隔离并行组 |
| bounded-fill | 限定填充率上限(如不超过 80% 留空隙) |
3. 装箱算法可调维度
- 物品排序 itemSort:volume / largest-box-needed / largest-girth / density / weight / combined / set-volume 等 12 种
- 放置策略 placementStyle:default / corner / wedge / mound / orb
- 方向 coordOrder:决定先沿哪根轴铺货
- 稳定性: layFlat / interlock / corners / allowableOverhang
- 装载合并 cohortPacking + cohortMax:同类物最多分几堆
- 回填控制 boxTypeChoiceLookback:已开箱是否允许装后续不同 sequence 的物品
4. 业务约束
- reservedSpace / usableSpace:包装材料预留率
- itemsPerBoxMax / itemSetsPerBoxMax / itemsInlineMax:箱内数量上限
- propertyConstraints:基于 item 自定义数值属性的累计上限(如单箱总价值≤5000,总重<25kg)
- rateTable:可内嵌 FedEx/UPS 真实费率表,自动算 DimWeight 并比较 ground / air / 2-day 等服务
- outer.dimensionChange:内外径差,用于纸箱套纸箱的嵌套场景
5. 可视化
- SVG/PNG 装箱图(视角、摆放顺序)
- imageScaleStyle:跨箱可比尺寸
- requestFingerprint / responseFingerprint / packUuid:可追溯、可在 Pacurate PCS 后台按单检索
思考
- 场景–经验–壁垒,它的 API 文档等于把场景暴露给了所有人,只剩下具体算法实现没有暴露了,任何一个竞争者可以省去不少调研成本。它的接口等于让竞争敌手省去了最麻烦的业务场景抽象设计,只要完成算法部分就复刻了服务能力。变相的提供了一份教材。
- 虽然接口包罗万象,但意味着它卖的是复杂场景下的计算服务,调用方必须依然依赖一个管理系统去管理基础资料、规则等等。同时也意味着它无法作为一个闭环系统,单独给买方创造价值,必须得 ERP 、WMS等单独为它集成才行。但优点在于,如果要提供闭环价值,并不是说补全基础资料管理、规则管理就可以了,还意味着后续每一次销售它都得跟客户五花八门的系统做定制化对接。它把极其珍贵的行业经验(场景)大方地写在说明书(Swagger)上,换取了极简的对接流程;同时,它把最繁重的“数据治理”脏活累活全丢给了客户的管理系统。一次开发之后就不需要很重的研发团队了,只需要销售团队。
- 适合哪些情况。 如果我作为买方,虽然提供的功能很诱人,但考虑到自己要付出的二开成本,可能只有自己场景简单,只需要简单的快速实现一些规则的时候才会选它。而且场景越复杂,数据治理要求越高,这点在现场是不靠谱的,最后垃圾进垃圾出。 而且如果就电商场景而言,中国跟美国的快递定价标准不同,中国经常一口价,只有极限压缩体积能够带来明显的运费节省时更有诱惑力。
- 两难困境。 如果我 SKU 非常多,规则特别多,那么数据治理成本过高,与其入库浪费时间测量,我还不如自己员工肉眼判断最合适的。 如果我 SKU 较少,这种 SAAS 服务商通常按调用量收费,我可以利用缓存技术最大限度的减少调用。 在国外可以通过健全的法规,禁止买家缓存,但是在国内肯定白搭。
- 基础工具的使用。 虽然 swagger openapi 效率很高,但是一是依赖高质量的维护,二是有些三个月培训班就半路出家的开发可能并不知道这样高效的工具,阻碍了这种规范得到广泛的使用。