管理员在线Capture时页面报错,支付平台后台却显示成功,订单里发票仍是Pending。此时最危险的操作是再点一次Capture。先用交易号确认钱的状态,再修复Magento本地状态。

现象

我保留了一个失败样本,并用同样输入在无缓存或单节点条件下再跑一遍。这样可以把前端假象、缓存和真正的数据问题分开。

排除法

  • 在支付平台查gateway transaction id,不要只看increment_id。
  • 核对sales_payment_transaction是否已有capture记录,invoice的transaction_id是否为空。
mysql -e "SELECT transaction_id,txn_id,txn_type,is_closed,parent_id FROM sales_payment_transaction WHERE order_id=(SELECT entity_id FROM sales_order WHERE increment_id='000000123');"
mysql -e "SELECT entity_id,increment_id,state,grand_total,transaction_id FROM sales_invoice WHERE order_id=(SELECT entity_id FROM sales_order WHERE increment_id='000000123');"
grep -R "000000123" var/log var/report

这里的重点不是把报错暂时消掉,而是让同一操作再执行一次仍保持幂等;因此修复后一定要做第二次重复执行测试。

最终处理

先关闭该订单的人工再次扣款入口。若网关webhook可安全重放,优先按原event id重放,让模块幂等补齐invoice与transaction。不能重放时写一次性修复脚本:在事务内加载订单和发票,核对金额后设置transaction id、pay并保存,同时记录订单history。脚本先在副本演练。

修改范围

  • 先在单个SKU、单个订单或单个Store验证。
  • 保留可回退的旧配置,不覆盖原始证据。
  • 需要批量处理时分批提交并输出成功/失败清单。

检查收尾

  • 网关只有一次capture
  • Magento只有一张对应金额发票
  • payment total_paid与order total_paid一致
  • 退款入口引用正确的capture transaction

验收不只看后台提示“成功”。我还会从前台/API再走一次真实链路,并在下一轮cron、索引或缓存命中后重复检查,确认不是短暂正常。

经验

禁止用SQL直接把state改成paid;这会跳过库存、总额和事件逻辑。

如果线上数据已经不一致,先停掉会继续扩大差异的入口,再修历史数据;否则一边补一边写,最后很难判断哪些记录已经处理。