Magento 2 开票时提示发票保存失败、事务回滚未正确完成
Magento 2 开票事务回滚异常排查方案
一、异常本质说明
该报错的触发逻辑与表象对应关系:
- 核心发票写入、订单状态更新、通知邮件发送的操作已执行完成,因此后台状态显示正常、邮件可正常发送
Rolled back transaction has not been completed correctly报错本质是嵌套事务计数异常,并未实际回滚已执行的核心写入操作- 卖家侧交易账户无记录的原因是:Webkul Multivendor 的分账写入操作绑定在事务提交回调中,由于事务状态异常,该回调未触发,因此分账数据未写入
二、定向排查步骤
- 优先检查 Webkul Multivendor 模块的分账逻辑绑定位置:
- 查找模块下
etc/adminhtml/di.xml或etc/di.xml中,针对Magento\Sales\Model\Order\Invoice的保存插件,确认分账写入操作绑定在save_before、save_after还是commit_after节点 - 检查
app/code/Webkul/Marketplace/Model/Sale/Item.php或对应分账模型的保存方法,是否手动实例化了独立的事务对象,与核心开票事务产生嵌套冲突
- 查找模块下
- 检查控制器层的事务调用逻辑:
打开app/code/Webkul/Marketplace/Controller/Order/Invoice.php,定位发票保存相关代码,确认是否存在以下错误逻辑:
这类逻辑会直接破坏 Magento 核心的嵌套事务计数机制,导致状态异常// 错误示例:控制器手动创建事务,覆盖核心事务管理 $transaction = $this->_transactionFactory->create(); $transaction->addObject($invoice)->save(); // 未正确处理事务的提交/回滚逻辑 - 检查 Stripe 支付模块的捕获逻辑:
查找 Stripe 模块中绑定到发票流程的捕获插件,确认捕获操作是在事务提交前还是提交后执行。如果在事务提交前发起 Stripe 远程请求,且请求成功后的写入操作与核心事务存在嵌套,会直接破坏事务状态 - 模块冲突验证:
依次执行以下操作,每次操作后测试开票流程,定位冲突模块:- 执行
php bin/magento module:disable Webkul_AdvancedBooking - 清除缓存:
php bin/magento cache:clean - 测试开票,若报错消失则说明是预订模块逻辑冲突;若报错仍存在,再临时禁用 Stripe 支付模块的发票捕获插件测试
- 执行
- 开启事务调试日志:
在vendor/magento/framework/DB/Transaction.php的rollBack()方法开头添加以下代码,记录回滚触发时的调用栈:
执行一次开票操作后,查看$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/transaction_debug.log'); $logger = new \Zend\Log\Logger(); $logger->addWriter($writer); $logger->info('Rollback triggered', [ 'level' => $this->_level, 'objects' => array_keys($this->_objects), 'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10) ]);var/log/transaction_debug.log的内容,可直接定位触发回滚的具体代码位置
三、快速修复方案
- 若为 Webkul 分账逻辑冲突:将分账写入操作的绑定节点从
invoice_save_after调整为invoice_save_commit_after,确保核心事务完全提交后再执行分账写入,避免嵌套事务冲突 - 若为控制器层事务逻辑错误:移除控制器中手动创建的事务对象,直接调用 Magento 核心的发票保存接口,由核心流程统一管理事务
- 若为 Stripe 捕获逻辑冲突:将 Stripe 捕获操作的触发节点调整为核心事务提交完成后,避免远程请求阻塞事务流程
内容的提问来源于stack exchange,提问作者Pigeon
相关产品推荐
相关产品推荐

