custom/plugins/KlarnaPayment/src/Components/EventListener/OrderDeliveriesWrittenEventListener.php line 69

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace KlarnaPayment\Components\EventListener;
  4. use KlarnaPayment\Components\Client\ClientInterface;
  5. use KlarnaPayment\Components\Client\Hydrator\Request\AddShippingInfo\AddShippingInfoRequestHydratorInterface;
  6. use KlarnaPayment\Components\Client\Hydrator\Request\GetOrder\GetOrderRequestHydratorInterface;
  7. use KlarnaPayment\Components\Client\Hydrator\Response\GetOrder\GetOrderResponseHydratorInterface;
  8. use KlarnaPayment\Components\Exception\AddShippingInfoFailed;
  9. use KlarnaPayment\Components\Helper\OrderDeliveryHelper\OrderDeliveryHelperInterface;
  10. use Psr\Log\LoggerInterface;
  11. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryDefinition;
  12. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
  13. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionCollection;
  14. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
  15. use Shopware\Core\Checkout\Order\OrderEntity;
  16. use Shopware\Core\Defaults;
  17. use Shopware\Core\Framework\Context;
  18. use Shopware\Core\Framework\DataAbstractionLayer\EntityWriteResult;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
  20. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  21. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  22. class OrderDeliveriesWrittenEventListener implements EventSubscriberInterface
  23. {
  24.     /** @var OrderDeliveryHelperInterface */
  25.     private $orderDeliveryHelper;
  26.     /** @var LoggerInterface */
  27.     private $logger;
  28.     /** @var GetOrderRequestHydratorInterface */
  29.     private $getOrderRequestHydrator;
  30.     /** @var GetOrderResponseHydratorInterface */
  31.     private $getOrderResponseHydrator;
  32.     /** @var ClientInterface */
  33.     private $client;
  34.     /** @var AddShippingInfoRequestHydratorInterface */
  35.     private $addShippingInfoRequestHydrator;
  36.     public function __construct(
  37.         OrderDeliveryHelperInterface $orderDeliveryHelper,
  38.         LoggerInterface $logger,
  39.         GetOrderRequestHydratorInterface $getOrderRequestHydrator,
  40.         GetOrderResponseHydratorInterface $getOrderResponseHydrator,
  41.         ClientInterface $client,
  42.         AddShippingInfoRequestHydratorInterface $addShippingInfoRequestHydrator
  43.     ) {
  44.         $this->orderDeliveryHelper            $orderDeliveryHelper;
  45.         $this->logger                         $logger;
  46.         $this->getOrderRequestHydrator        $getOrderRequestHydrator;
  47.         $this->getOrderResponseHydrator       $getOrderResponseHydrator;
  48.         $this->client                         $client;
  49.         $this->addShippingInfoRequestHydrator $addShippingInfoRequestHydrator;
  50.     }
  51.     public static function getSubscribedEvents(): array
  52.     {
  53.         return [
  54.             EntityWrittenContainerEvent::class => 'handleOrderDeliveryChange',
  55.         ];
  56.     }
  57.     public function handleOrderDeliveryChange(EntityWrittenContainerEvent $containerEvent): void
  58.     {
  59.         $event $containerEvent->getEventByEntityName(OrderDeliveryDefinition::ENTITY_NAME);
  60.         if ($event === null || $event->hasErrors() === true || $event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  61.             return;
  62.         }
  63.         // every tracking code entered will create a result containing all trackingcodes. only the last is the final result
  64.         $writeResults $event->getWriteResults();
  65.         /** @var EntityWriteResult $writeResult */
  66.         $writeResult end($writeResults);
  67.         $payload         $writeResult->getPayload();
  68.         $orderId         $payload['orderId'] ?? null;
  69.         $orderDeliveryId $payload['id'] ?? null;
  70.         $trackingCodes   $payload['trackingCodes'] ?? null;
  71.         $stateId         $payload['stateId'] ?? null;
  72.         if (!$orderDeliveryId || $writeResult->getOperation() === EntityWriteResult::OPERATION_DELETE) {
  73.             return;
  74.         }
  75.         /** @var OrderDeliveryEntity $orderDelivery */
  76.         $orderDelivery $this->orderDeliveryHelper->getOrderDeliveryById($orderDeliveryId$event->getContext());
  77.         if ($this->orderDeliveryHelper->orderDoesContainRelevantShippingInformation($orderDelivery) === false) {
  78.             return;
  79.         }
  80.         /**
  81.          * orderId and trackingCodes are given when trackingCodes have been updated
  82.          * stateId is given on stateChange
  83.          */
  84.         if (($orderId && !empty($trackingCodes)) || $stateId) {
  85.             $this->updateShippingInfo($orderDelivery$event->getContext());
  86.         }
  87.     }
  88.     private function updateShippingInfo(OrderDeliveryEntity $orderDeliveryContext $context): void
  89.     {
  90.         /** @var OrderEntity $order */
  91.         $order $orderDelivery->getOrder();
  92.         /** @var OrderTransactionCollection $transactions */
  93.         $transactions $order->getTransactions();
  94.         /** @var OrderTransactionEntity $transaction */
  95.         $transaction $transactions->last();
  96.         /** @var array<string,mixed> $klarnaValues */
  97.         $klarnaValues  $transaction->getCustomFields();
  98.         $klarnaOrderId $klarnaValues['klarna_order_id'];
  99.         $captureId $this->getCaptureId($klarnaOrderId$order->getSalesChannelId(), $context);
  100.         if (!$captureId) {
  101.             $this->logger->error('No captureId for order returned', [
  102.                 'klarnaOrderId' => $klarnaOrderId,
  103.                 'transactionId' => $transaction->getId(),
  104.             ]);
  105.             return;
  106.         }
  107.         $this->sendShippingInfo($klarnaOrderId$captureId$orderDelivery$transaction$context);
  108.     }
  109.     private function sendShippingInfo(
  110.         string $klarnaOrderId,
  111.         string $captureId,
  112.         OrderDeliveryEntity $orderDelivery,
  113.         OrderTransactionEntity $transaction,
  114.         Context $context
  115.     ): void {
  116.         try {
  117.             $dataBag = new RequestDataBag();
  118.             $dataBag->add([
  119.                 'klarna_order_id' => $klarnaOrderId,
  120.                 'capture_id'      => $captureId,
  121.             ]);
  122.             $request $this->addShippingInfoRequestHydrator->hydrate($dataBag$orderDelivery$transaction$context);
  123.             if (empty($request->getShippingInfos())) {
  124.                 return;
  125.             }
  126.             $response $this->client->request($request$context);
  127.             if ($response->getHttpStatus() !== 204) {
  128.                 throw new AddShippingInfoFailed((string) $response->getHttpStatus(), $response->getResponse());
  129.             }
  130.         } catch (AddShippingInfoFailed $e) {
  131.             $this->logger->error($e->getMessage(), [
  132.                 'klarnaOrderId' => $klarnaOrderId,
  133.                 'captureId'     => $captureId,
  134.                 'response'      => $response ?? null/** @phpstan-ignore-line */
  135.                 'request'       => $request ?? null/** @phpstan-ignore-line */
  136.             ]);
  137.         } catch (\Throwable $e) {
  138.             $this->logger->error('Error while adding shipping infos', [
  139.                 'klarnaOrderId' => $klarnaOrderId,
  140.                 'captureId'     => $captureId,
  141.                 'error'         => $e->getMessage(),
  142.                 'request'       => $request ?? null,
  143.             ]);
  144.         }
  145.     }
  146.     private function getCaptureId(string $klarnaOrderIdstring $salesChannelIdContext $context): ?string
  147.     {
  148.         $captureId null;
  149.         try {
  150.             $dataBag = new RequestDataBag();
  151.             $dataBag->add([
  152.                 'klarna_order_id' => $klarnaOrderId,
  153.                 'salesChannel'    => $salesChannelId,
  154.             ]);
  155.             $request  $this->getOrderRequestHydrator->hydrate($dataBag);
  156.             $response $this->client->request($request$context);
  157.             if ($response->getHttpStatus() !== 200) {
  158.                 return null;
  159.             }
  160.             $order     $this->getOrderResponseHydrator->hydrate($response$context);
  161.             $captureId $order->getLastCaptureId();
  162.         } catch (\Throwable $e) {
  163.             $this->logger->error('Error receiving capture id', [
  164.                'klarnaOrderId' => $klarnaOrderId,
  165.                'error'         => $e->getMessage(),
  166.             ]);
  167.         }
  168.         return $captureId;
  169.     }
  170. }