《互联网产品的客户端架构·交易、增长与平台化》附录 C 交易端评审清单

可以带进评审会的交易端清单:按所有权、状态机、金额、幂等与重复、失败路径、优惠与会员、增长与实验、埋点与观测、安全与隐私、发布与回滚十组问题逐项提问,每组给出通过标准与常见缺陷,另附「未验证」栏、评审记录模板、快速版十问与不通过判据,供方案评审与上线前评审直接使用。

怎么用这份清单

这份清单面向两类评审:方案评审与上线前评审。

  • 方案评审关注「判断对不对」:所有权、状态机、失败路径、验证方式。
  • 上线前评审关注「证据够不够」:测试覆盖、灰度策略、回滚方案、观测指标。

清单按十组问题组织,每组有若干提问、通过标准与常见缺陷。评审时不必逐条念,挑与本方案相关的组;但**「未验证」栏必须每次填**。

一个使用建议:把清单当成提问工具,而不是打分表。交易端的风险很少来自「少写了一个字段」,多来自「没人问过这个问题」。

第一组:所有权

要问的问题:

  • 价格、库存、订单状态、支付结果分别由谁写?
  • 端上有没有直接修改这些字段的路径?
  • 预演值与服务端值冲突时,以谁为准?
  • 服务端返回值是否覆盖端上乐观状态?

通过标准:

  • 每个关键字段有唯一写入方,且写在文档里。
  • 端上只读服务端字段,或只写明确属于自己的字段(如购物车勾选)。
  • 预演值有明确标注,不进入提交。

常见缺陷:

  • 「端上先改,服务端再纠正」,用户看到数字跳变。
  • 库存由端上扣减,超卖后互相甩锅。
  • 订单状态在端上与服务端各有一套枚举。

第二组:状态机

要问的问题:

  • 订单、支付、退款各有几个状态?终态是哪几个?
  • 非法迁移是拒绝还是忽略?
  • 「结果未知」是独立状态还是被归入失败?
  • 状态迁移是否有测试覆盖每一条边?

通过标准:

  • 三套状态机分开定义,迁移表可枚举。
  • 非法迁移返回明确错误,不静默成功。
  • unknown 有独立出口,且出口不提供「重新支付」。
  • 每条允许的迁移至少一条测试,每条禁止的迁移至少一条测试。

常见缺陷:

  • 用一个 status 字段装三种状态。
  • 状态机用黑名单校验,新状态被放行。
  • 超时直接把订单置为取消,不检查是否已支付。

第三组:金额

要问的问题:

  • 金额用什么类型?是否全程整数分?
  • 有哪几个金额口径?字段名是否统一?
  • 端上能算到哪一步?实付是否只由服务端给?
  • 优惠、运费、退款的分摊规则是什么?舍入差由谁吸收?

通过标准:

  • 全部金额整数分,币种与金额成对。
  • 端上最多预演到应付金额,且标注「预估」。
  • 部分退款的分摊由服务端计算,端上不二次分配。
  • 有 0 元、1 分、超大金额、跨币种的展示用例。

常见缺陷:

  • 用浮点数计算金额,出现 0.1 + 0.2 类误差。
  • 商品页价格直接用于提交。
  • 端上把优惠按比例分摊,产生 1 分误差。
  • 金额字段叫 total,不同页面含义不同。

第四组:幂等与重复

要问的问题:

  • 提交订单的幂等键在哪生成?重试时是否复用?
  • 同一幂等键重复提交,返回同一订单还是新建订单?
  • 支付回调重复到达,处理是否幂等?
  • 用户快速点击两次,端上有没有防抖之外的保护?

通过标准:

  • 幂等键在用户动作开始时生成,覆盖整个重试周期。
  • 服务端对同一键返回同一结果,不产生第二笔订单。
  • 回调按事件 ID 或渠道交易号去重。
  • 端上按钮置灰只是体验优化,幂等由服务端保证。

常见缺陷:

  • 每次重试生成新幂等键。
  • 把 orderId 当幂等键,而创建订单前还没有 orderId。
  • 只做端上防抖,换设备或杀进程后重复提交。

第五组:失败路径

要问的问题:

  • 网络超时后,端上认为成功还是失败?
  • 结果未知时,用户能看到什么、能点什么?
  • 支付拉起失败、回跳丢失、App 被杀,分别怎么恢复?
  • 失败文案是否说满了?

通过标准:

  • 超时归入「未知」,提供查询入口,不提供重复支付。
  • 每个失败状态有对应文案与下一步动作。
  • 恢复路径不依赖用户记住刚才发生了什么。
  • 文案不承诺「一定退款」「立即到账」。

常见缺陷:

  • 超时提示「支付失败,请重试」,用户付了两次。
  • 回跳丢失后停在空白页。
  • 失败文案把「处理中」写成「已退款」。

第六组:优惠与会员

要问的问题:

  • 券的可用性由谁判定?端上判定与服务端是否同源?
  • 叠加规则是「先券后折」还是「先折后券」?门槛按哪个金额算?
  • 会员价与券能否叠加?积分何时发放?
  • 价格变化后优惠失效,是否有明确提示?

通过标准:

  • 最终可用性与金额由服务端返回,端上只做展示。
  • 不可用原因具体到条件,不只置灰。
  • 会员与券的叠加规则写在一处,端上不重复实现。
  • 积分有流水,余额可重算。

常见缺陷:

  • 端上算券,服务端再算一遍,两边规则漂移。
  • 券不可用只显示「不满足使用条件」。
  • 会员价展示与结算价不一致。
  • 积分只有余额没有流水。

第七组:增长与实验

要问的问题:

  • 分流键是什么?同一用户是否稳定命中同一组?
  • 实验配置拉取失败时,端上用默认值还是阻塞?
  • 曝光在什么时候打?路由缓存会不会重复曝光?
  • 活动页降级后,用户还能不能完成主流程?

通过标准:

  • 分流键稳定且与埋点标识一致。
  • 配置有本地缓存与默认值,失败不阻塞交易主链路。
  • 曝光去重规则明确,重复曝光可被识别。
  • 活动降级不影响下单、支付等核心动作。

常见缺陷:

  • 用随机数分流,用户刷新后换组。
  • 配置接口失败导致首页白屏。
  • 曝光打在渲染函数里,每次重渲染都上报。
  • 活动页挂了,入口仍然指向它。

第八组:埋点与观测

要问的问题:

  • 关键事件有哪些?事件契约是否版本化?
  • 上报失败是否重试?重试是否去重?
  • 支付链路的漏斗能否用 orderId 串起来?
  • 线上出问题时,看哪几个指标能定位?

通过标准:

  • 关键事件有 schema,字段变更走版本。
  • 上报队列有上限、有丢弃策略、有去重。
  • 端上事件与服务端事件共享 orderId 或 traceId。
  • 至少有三个核心指标:下单成功率、支付成功率、退款完成率。

常见缺陷:

  • 事件字段随手加,下游解析失败。
  • 上报失败无限重试,耗电又重复。
  • 漏斗各步骤用不同标识,无法串联。
  • 只有「支付成功」一个点,失败原因全靠猜。

第九组:安全与隐私

要问的问题:

  • 端上是否持有支付密钥、渠道私钥?
  • 订单、地址、手机号在日志里是否脱敏?
  • 分享链接、邀请参数是否可被篡改?
  • 退款、改价等敏感操作是否有二次校验?

通过标准:

  • 密钥只在服务端,端上不落盘。
  • 日志脱敏,埋点不含明文手机号与地址。
  • 分享参数有签名或服务端校验。
  • 敏感操作有身份校验与操作留痕。

常见缺陷:

  • 把渠道密钥写进客户端配置。
  • 埋点带上完整收货地址。
  • 邀请码可枚举,被刷奖励。
  • 客服后台可直接改价,无审计。

第十组:发布与回滚

要问的问题:

  • 这次改动能否独立回滚?回滚后数据是否兼容?
  • 新旧版本客户端同时存在时,接口是否兼容?
  • 灰度比例与观察指标是什么?
  • 出现资金问题时,止损动作是什么?

通过标准:

  • 前后端改动可分别回滚,或明确绑定发布。
  • 接口向后兼容,旧客户端不崩。
  • 灰度有明确指标与停止条件。
  • 有资金止损预案:关闭入口、降级支付渠道、人工退款流程。

常见缺陷:

  • 数据库字段直接改名,旧版本读写失败。
  • 只测新客户端,旧版本白屏。
  • 灰度只看 crash,不看支付成功率。
  • 出事后没有关闭入口的开关。

「未验证」栏

每次评审结束前,把下面这张表填完:

结论证据验证方式负责人截止时间
例:重复提交不会产生两笔订单缺待补 L2 用例张三上线前
例:回调重复到达幂等有L3 用例李四已完成

规则:

  • 「结论」写成可证伪的句子,不写「已处理」「没问题」。
  • 「证据」指测试用例、压测报告、对账结果,不指代码位置。
  • 没有证据的结论一律标「缺」,不因为「大家都知道」而放行。
  • 截止时间必须早于上线时间;上线前无法验证的,写进风险台账并给出降级方案。

这一栏是整份清单最重要的部分。交易端的事故,几乎都能在评审时找到一条「当时没人验证」的结论。

评审记录模板

评审对象:
评审类型:方案 / 上线前
参与人:
结论:通过 / 有条件通过 / 不通过

必改项:
1.
2.

建议项:
1.

未验证项:
| 结论 | 证据 | 验证方式 | 负责人 | 截止时间 |

风险与降级:

「有条件通过」必须写清条件与验证人;「不通过」要给出重新评审的时间,而不是无限期挂起。

快速版清单

时间有限时,至少问这十个问题:

  1. 价格、库存、订单状态、支付结果分别谁写?
  2. 三套状态机的终态是哪几个?
  3. 结果未知时,用户能点什么?
  4. 金额是否全程整数分?实付由谁给?
  5. 幂等键在哪生成,重试是否复用?
  6. 回调重复到达会怎样?
  7. 券不可用时,用户看得到原因吗?
  8. 配置拉取失败会阻塞下单吗?
  9. 漏斗能否用 orderId 串起来?
  10. 出资金问题时,止损开关在哪?

十个问题里有一个答不上来,就不该直接上线。

小结

评审的价值不在清单本身,而在它逼着团队把「默认成立」的假设说出来。

三句话总结:

  1. 所有权不清,后面全是争论。
  2. 状态与金额不分开,故障无法表达。
  3. 没有证据的结论,等于没有结论。

把这份清单带进评审会,重点看「未验证」栏,而不是看打了多少个勾。

常见错误与边界

  • 把清单当打分表,勾完就通过,不看证据。
  • 只评审新功能,不评审对旧版本客户端的兼容。
  • 未验证项写「已知」,但没有负责人与截止时间。
  • 评审结论写「通过」,风险台账却是空的。
  • 只问「有没有测」,不问「测的是不是这条结论」。
  • 把端上防抖当成幂等保证。
  • 忽略资金止损开关,出事后只能发版。
  • 评审记录不落库,下次评审从零开始。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《互联网产品的 AI 架构·平台化与治理》附录 C 平台化评审清单
  2. 《互联网产品的 AI 架构·平台化与治理》附录 B 能力目录与配额字段速查
  3. 《互联网产品的 AI 架构·平台化与治理》附录 A 治理角色与职责速查