vr-shopxo-plugin/docs/17_AUTO_CONFIRM_ON_VERIFY.md

5.5 KiB
Raw Blame History

核销自动确认收货 — 设计与验证

文档类型:功能归档 | 日期2026-06-12 | 关联 ticketTicketService 核销流程


背景

核销流程中,需要将确认收货步骤自动化:核销成功后自动触发确认收货。此前该功能作为 TODO 存在于代码中,本轮完成实现并验证。


原始需求

  1. 核销后自动确认收货
  2. 待收货状态status=3才触发确认收货
  3. 如果已经是确认收货状态status=4幂等返回成功不报错
  4. 如果确认收货失败,回滚核销操作(整个操作在事务内)
  5. 并发安全:使用悲观锁防并发
  6. 短码核销(verifyByShortCode)复用同一逻辑
  7. 已确认收货但未核销的情况核销流程正常走通autoConfirmOrder 返回 code=0 兜底)

技术方案

核心流程图

verifyTicket / verifyTicketById
  │
  ├─ 悲观锁查票SELECT ... lock(true)
  ├─ 核销票(标记 status=1
  ├─ autoConfirmOrder()
  │    ├─ 悲观锁查订单SELECT ... lock(true)
  │    ├─ status==4 → return code=0幂等
  │    ├─ status!=3 → return code=0跳过
  │    └─ status==3 → 调用订单API确认收货
  ├─ 如 autoConfirmOrder 失败 → throw \Exception → 事务回滚
  └─ commit

关键设计决策

决策 理由
不记录核销人与电话号码(staffId, staffMobile 设计文档未提及,避免过度实现
autoConfirmOrder 不做 null 直接返回 缺乏需求约束,静默丢弃会产生不可追踪的数据不一致
使用 if/elseif 而非守卫语句 符合仓库现有风格
悲观锁 防止并发场景下同一订单被重复确认收货

改动清单

[MODIFY] shopxo/app/plugins/vr_ticket/service/TicketService.php

位置 改动
verifyTicketL314附近 核销后调用 autoConfirmOrder,失败则抛异常回滚
verifyTicketByIdL474附近 同上,在事务末尾调用 autoConfirmOrder
autoConfirmOrderL614-L657 新增方法:悲观锁查单 → 状态判断 → 幂等/跳过/确认收货

verifyTicket 事务内调用

// 在 verifyTicket 事务内,核销完成后
$auto_confirm_ret = $this->autoConfirmOrder($order_id);
if ($auto_confirm_ret['code'] != 0) {
    throw new \Exception($auto_confirm_ret['msg']);
}

autoConfirmOrder 方法签名

/**
 * 核销后自动确认收货
 * - 使用悲观锁防并发
 * - status==4幂等返回成功
 * - status!=3跳过
 * @return array ['code'=>0/1, 'msg'=>...]
 */
private function autoConfirmOrder($order_id): array

GitNexus 变更报告

指标
变更符号数 4autoConfirmOrder 新增 + verifyTicket/verifyTicketById/verifyByShortCode 受影响)
变更文件数 1TicketService.php
受影响执行流程 0
风险级别 LOW

测试策略

单元测试(验证码核销 + 待收货订单)

请求:

POST /api.php?s=plugins/index&pluginsname=vr_ticket&pluginscontrol=verifier&pluginsaction=verify
  code=<验证码>  status=<状态>

用例1待收货订单核销核心路径

步骤 预期
1. 手机端下单票品 订单 status=3待发货/待收货)
2. 使用核销码核销 票 status=1订单 status=4
3. 检查订单详情 确认收货时间已记录

用例2已确认收货订单核销幂等

步骤 预期
1. 使用已确认收货订单的核销码核销 票正常核销,不报错

用例3手动确认收货后再核销

步骤 预期
1. 手动确认收货status 3→4 成功
2. 使用核销码核销 票正常核销,autoConfirmOrder 幂等返回

用例4并发核销

步骤 预期
1. 两个核销请求几乎同时到达 只有一个成功,另一个因悲观锁或票状态被拒绝

验证结果

# 需求 实现位置 状态
1 核销后自动确认收货 verifyTicket L314 + verifyTicketById L474 调用 autoConfirmOrder
2 仅待收货才处理 autoConfirmOrder L635: if ($order['status'] != 3) → 跳过
3 已确认收货幂等 autoConfirmOrder L629: if ($order['status'] == 4) → 返回 success
4 确认失败回滚核销 $confirm_ret['code'] != 0throw \Exception,事务回滚
5 悲观锁防并发 订单查询 ->lock(true) (L620),票查询 ->lock(true) (L257, L417)
6 短码核销继承 verifyByShortCode → 委托 verifyTicketById
7 已收货+未核销正常走 autoConfirmOrder 返回 code=0,核销不受影响

未实现项(明确排除)

原因
核销时记录核销人staffId 需求文档未提及
核销时记录电话号码staffMobile 需求文档未提及
autoConfirmOrder$order == null 的静默处理 没有需求约束,不做猜测性实现

未来增强建议

  1. 核销记录表:如需追溯核销人,可扩展 vr_ticket_verification 表增加 staff_id/staff_mobile 字段
  2. 异步确认收货:如确认收货 API 耗时较长,可考虑队列化处理以提高核销吞吐
  3. 核销回调钩子:在 verifyTicket 完成后增加后置钩子(如发送核销通知),使扩展点更清晰