Magento 2.2.3通过sales_order_save_after观察者自动创建发票报错
解决Magento 2.2.3中自动生成发票的事务冲突问题
我来帮你搞定这个棘手的问题!你遇到的报错和发票生成异常,核心原因是**sales_order_save_after事件本身就运行在Magento订单保存的事务上下文里**,手动加事务操作会和原生事务机制冲突,导致回滚异常;而去掉事务后,发票的持久化操作没在正确的事务流程里完成,所以只更新了订单状态,实际发票数据没写入数据库。
修正后的观察者代码
直接替换你的MyCompany/MyModule/Observer/SalesOrderSaveAfter.php代码,用Magento官方推荐的方式生成发票,避免手动事务操作:
<?php namespace MyCompany\MyModule\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Sales\Model\Service\InvoiceService; use Magento\Framework\DB\Transaction; use Magento\Sales\Model\Order\Invoice; class SalesOrderSaveAfter implements ObserverInterface { /** @var InvoiceService */ private $invoiceService; /** @var Transaction */ private $transaction; public function __construct( InvoiceService $invoiceService, Transaction $transaction ) { $this->invoiceService = $invoiceService; $this->transaction = $transaction; } public function execute(Observer $observer) { $order = $observer->getOrder(); // 关键:只处理可开票且未处理过的订单,避免重复执行 if (!$order->canInvoice() || $order->getState() !== \Magento\Sales\Model\Order::STATE_PROCESSING) { return $this; } try { // 用官方服务创建发票 $invoice = $this->invoiceService->prepareInvoice($order); // 校验发票是否有商品数量,避免空发票 if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( __('无法创建空发票,请检查订单商品。') ); } // 设置发票捕获方式并注册 $invoice->setRequestedCaptureCase(Invoice::CAPTURE_ONLINE); $invoice->register(); $order->setIsInProcess(true); // 用Magento事务工厂处理关联保存,无需手动管理事务 $this->transaction ->addObject($invoice) ->addObject($order) ->save(); } catch (\Exception $e) { // 异常时记录到订单备注,不影响订单保存 $order->addStatusHistoryComment( __('自动生成发票失败:%1', $e->getMessage()), false ); $order->save(); } return $this; } }
核心要点说明
- 别碰手动事务:Magento在触发
sales_order_save_after时,订单保存的事务还没提交,手动开事务会触发嵌套事务冲突,这就是报错的根源。 - 用官方服务类:
InvoiceService和Transaction是Magento原生的发票处理工具,能完美兼容系统的事务流程,确保发票和订单状态同步保存。 - 加重复校验:
$order->canInvoice()会自动判断订单是否已开票、是否符合开票条件,避免重复执行逻辑导致的异常。 - 异常兜底:捕获所有异常并写入订单备注,这样即使发票生成失败,订单也能正常保存,方便后续排查问题。
额外检查步骤
- 确认你的
etc/events.xml配置正确(如果还没加的话):
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="sales_order_save_after"> <observer name="mycompany_mymodule_auto_invoice" instance="MyCompany\MyModule\Observer\SalesOrderSaveAfter" /> </event> </config>
- 清理缓存并重新编译:
php bin/magento cache:clean php bin/magento setup:di:compile
这样调整后,订单提交时就能自动生成有效发票,也不会再出现事务回滚的报错了。
内容的提问来源于stack exchange,提问作者AJK
相关产品推荐
相关产品推荐

