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

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