Shopware 6 Store API从购物车创建订单时添加Order扩展数据
Shopware 6 Store API 从购物车创建订单时保存扩展字段解决方案
核心问题说明
Store API 的 /checkout/order 端点(从购物车创建订单)默认不支持直接传递订单扩展数据,原因是该端点基于购物车流程设计,不像 Admin API 的 /api/order 那样直接操作订单实体。要让扩展字段在订单创建时就被保存,有两种可行方案:
方案1:通过购物车中转扩展数据,再同步到订单
利用购物车作为数据载体,在订单创建前的事件中将购物车的扩展数据映射到订单:
- 更新购物车,添加扩展数据
调用 Store API 的/checkout/cart端点,将需要保存的myText放到购物车的自定义扩展或自定义字段中:
{ "extensions": { "myOrderExtension": { "myText": "待保存的文本内容" } } }
或者使用购物车自定义字段:
{ "customFields": { "my_text": "待保存的文本内容" } }
- 订阅订单创建前事件,同步数据
编写事件订阅器,在OrderBeforePersistingEvent触发时,从购物车提取数据并赋值给订单的扩展实体:
<?php namespace YourPlugin\Subscriber; use Shopware\Core\Checkout\Order\Event\OrderBeforePersistingEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class OrderExtensionSyncSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ OrderBeforePersistingEvent::class => 'syncExtensionData', ]; } public function syncExtensionData(OrderBeforePersistingEvent $event): void { $order = $event->getOrder(); $cart = $event->getCart(); // 从购物车扩展提取数据并赋值给订单扩展 $cartExtension = $cart->getExtension('myOrderExtension'); if ($cartExtension) { $orderExtension = $order->getExtension('myOrderExtension') ?? new \YourPlugin\Entity\OrderExtensionEntity(); $orderExtension->setMyText($cartExtension->getMyText()); $order->addExtension('myOrderExtension', $orderExtension); } // 若用自定义字段的方式,同步逻辑如下 $cartCustomFields = $cart->getCustomFields(); if (isset($cartCustomFields['my_text'])) { $orderExtension = $order->getExtension('myOrderExtension') ?? new \YourPlugin\Entity\OrderExtensionEntity(); $orderExtension->setMyText($cartCustomFields['my_text']); $order->addExtension('myOrderExtension', $orderExtension); } } }
- 注册订阅器
在插件的services.xml中配置订阅器:
<service id="YourPlugin\Subscriber\OrderExtensionSyncSubscriber"> <tag name="kernel.event_subscriber"/> </service>
方案2:装饰订单服务,直接处理请求体中的扩展字段
通过装饰 OrderService,直接从 /checkout/order 的请求体中提取扩展数据并赋值给订单:
- 创建装饰器类
<?php namespace YourPlugin\Service; use Shopware\Core\Checkout\Order\SalesChannel\OrderService; use Shopware\Core\Checkout\Order\SalesChannel\OrderServiceInterface; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; use Shopware\Core\System\SalesChannel\SalesChannelContext; class ExtendedOrderService extends OrderService { private OrderServiceInterface $innerService; public function __construct(OrderServiceInterface $innerService) { $this->innerService = $innerService; } public function createOrder(RequestDataBag $data, SalesChannelContext $context) { // 从请求体提取myText字段 $myText = $data->get('myText'); $orderResponse = $this->innerService->createOrder($data, $context); // 将字段赋值给订单扩展 if ($myText) { $order = $orderResponse->getOrder(); $orderExtension = $order->getExtension('myOrderExtension') ?? new \YourPlugin\Entity\OrderExtensionEntity(); $orderExtension->setMyText($myText); $order->addExtension('myOrderExtension', $orderExtension); } return $orderResponse; } }
- 配置装饰器
在services.xml中注册装饰器:
<service id="YourPlugin\Service\ExtendedOrderService" decorates="Shopware\Core\Checkout\Order\SalesChannel\OrderService"> <argument type="service" id="YourPlugin\Service\ExtendedOrderService.inner"/> </service>
- 调用
/checkout/order时传递字段
请求体中直接添加myText字段:
{ "myText": "待保存的文本内容", "paymentMethodId": "xxx", "shippingMethodId": "xxx", // 其他必填字段... }
为什么直接传扩展字段无效?
Store API 的 /checkout/order 端点由 CheckoutOrderRoute 处理,其请求验证器 CheckoutOrderRouteRequestValidator 默认只处理购物车及订单基础字段,不会自动映射到订单扩展实体。而 Admin API 的 /api/order 是直接操作订单实体,因此支持扩展字段的直接传递。
内容的提问来源于stack exchange,提问作者Marcus
相关产品推荐
相关产品推荐

