vendor/store.shopware.com/mltisafemultisafepay/src/Subscriber/CheckoutConfirmTemplateSubscriber.php line 88

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /**
  3.  * Copyright © MultiSafepay, Inc. All rights reserved.
  4.  * See DISCLAIMER.md for disclaimer details.
  5.  */
  6. namespace MultiSafepay\Shopware6\Subscriber;
  7. use Exception;
  8. use MultiSafepay\Api\Issuers\Issuer;
  9. use MultiSafepay\Exception\ApiException;
  10. use MultiSafepay\Exception\InvalidApiKeyException;
  11. use MultiSafepay\Exception\InvalidArgumentException;
  12. use MultiSafepay\Shopware6\Factory\SdkFactory;
  13. use MultiSafepay\Shopware6\PaymentMethods\Ideal;
  14. use MultiSafepay\Shopware6\PaymentMethods\MyBank;
  15. use MultiSafepay\Shopware6\PaymentMethods\PaymentMethodInterface;
  16. use MultiSafepay\Shopware6\Service\SettingsService;
  17. use MultiSafepay\Shopware6\Storefront\Struct\MultiSafepayStruct;
  18. use MultiSafepay\Shopware6\Support\Tokenization;
  19. use MultiSafepay\Shopware6\Util\PaymentUtil;
  20. use Psr\Http\Client\ClientExceptionInterface;
  21. use Shopware\Core\Framework\Context;
  22. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  23. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  24. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  25. use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
  26. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  27. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  28. class CheckoutConfirmTemplateSubscriber implements EventSubscriberInterface
  29. {
  30.     /**
  31.      * @var SdkFactory
  32.      */
  33.     private $sdkFactory;
  34.     /**
  35.      * @var EntityRepository
  36.      */
  37.     private $languageRepository;
  38.     /**
  39.      * @var string
  40.      */
  41.     private $shopwareVersion;
  42.     /**
  43.      * @var SettingsService
  44.      */
  45.     private $settingsService;
  46.     /**
  47.      * CheckoutConfirmTemplateSubscriber constructor.
  48.      *
  49.      * @param SdkFactory $sdkFactory
  50.      * @param EntityRepository $languageRepository
  51.      * @param SettingsService $settingsService
  52.      * @param string $shopwareVersion
  53.      */
  54.     public function __construct(
  55.         SdkFactory $sdkFactory,
  56.         EntityRepository $languageRepository,
  57.         SettingsService $settingsService,
  58.         string $shopwareVersion
  59.     ) {
  60.         $this->sdkFactory $sdkFactory;
  61.         $this->languageRepository $languageRepository;
  62.         $this->shopwareVersion $shopwareVersion;
  63.         $this->settingsService $settingsService;
  64.     }
  65.     /**
  66.      * @return array
  67.      */
  68.     public static function getSubscribedEvents(): array
  69.     {
  70.         return [
  71.             CheckoutConfirmPageLoadedEvent::class => 'addMultiSafepayExtension',
  72.             AccountEditOrderPageLoadedEvent::class => 'addMultiSafepayExtension',
  73.         ];
  74.     }
  75.     /**
  76.      * @param CheckoutConfirmPageLoadedEvent $event
  77.      * @throws Exception
  78.      */
  79.     public function addMultiSafepayExtension($event): void
  80.     {
  81.         if (!$event instanceof CheckoutConfirmPageLoadedEvent && !$event instanceof AccountEditOrderPageLoadedEvent) {
  82.             throw new \InvalidArgumentException(
  83.                 'Please provide ' CheckoutConfirmPageLoadedEvent::class . ' or ' .
  84.                 AccountEditOrderPageLoadedEvent::class
  85.             );
  86.         }
  87.         $issuers = [];
  88.         $lastUsedIssuer $gatewayNameWithIssuers $gatewayCodeWithIssuers $activeName null;
  89.         try {
  90.             $struct = new MultiSafepayStruct();
  91.             $salesChannelContext $event->getSalesChannelContext();
  92.             $customer $salesChannelContext->getCustomer();
  93.             if (!is_null($customer)) {
  94.                 $lastUsedIssuer $customer->getCustomFields()['last_used_issuer'] ?? null;
  95.             }
  96.             switch ($event->getSalesChannelContext()->getPaymentMethod()->getName()) {
  97.                 case Ideal::GATEWAY_NAME:
  98.                     $gatewayNameWithIssuers Ideal::GATEWAY_NAME;
  99.                     $gatewayCodeWithIssuers Ideal::GATEWAY_CODE;
  100.                     break;
  101.                 case MyBank::GATEWAY_NAME:
  102.                     $gatewayNameWithIssuers MyBank::GATEWAY_NAME;
  103.                     $gatewayCodeWithIssuers MyBank::GATEWAY_CODE;
  104.                     break;
  105.             }
  106.             try {
  107.                 $sdk $this->sdkFactory->create($salesChannelContext->getSalesChannel()->getId());
  108.             } catch (InvalidApiKeyException $invalidApiKeyException) {
  109.                 return;
  110.             }
  111.             if (!is_null($gatewayCodeWithIssuers)) {
  112.                 $issuers $sdk->getIssuerManager()->getIssuersByGatewayCode($gatewayCodeWithIssuers);
  113.                 $activeName $this->getRealGatewayNameWithIssuers($issuers$lastUsedIssuer$gatewayNameWithIssuers);
  114.             }
  115.             $paymentMethodEntity $event->getSalesChannelContext()->getPaymentMethod();
  116.             $customFields $paymentMethodEntity->getCustomFields();
  117.             $gatewayCode $this->getGatewayCode($paymentMethodEntity->getHandlerIdentifier());
  118.             // Validating if the "component" status of iDEAL is "not" true, so issuers should be shown
  119.             // because is a gateway that can switch just between using components or direct modes
  120.             $isIdealWithComponent = ($gatewayCode === 'IDEAL') && empty($customFields['component']);
  121.             // Validating if the "direct" status of MyBank "is" true, so issuers should be shown
  122.             // because is a gateway that can switch just between using direct or redirect modes
  123.             $isMyBankWithDirect = ($gatewayCode === 'MYBANK') && !empty($customFields['direct']);
  124.             $struct->assign([
  125.                 'tokens' => $this->getTokens($salesChannelContext),
  126.                 'api_token' => !empty($customFields['component']) ? $this->getComponentsToken($salesChannelContext) : null,
  127.                 'template_id' => $this->getTemplateId(),
  128.                 'gateway_code' => $gatewayCode,
  129.                 'env' => $this->getComponentsEnvironment($salesChannelContext),
  130.                 'locale' => $this->getLocale(
  131.                     $event->getSalesChannelContext()->getSalesChannel()->getLanguageId(),
  132.                     $event->getContext()
  133.                 ),
  134.                 'direct' => true,
  135.                 'redirect' => false,
  136.                 'show_tokenization' => $this->showTokenization($salesChannelContext),
  137.                 'issuers' =>  ($isIdealWithComponent || $isMyBankWithDirect) ? $issuers : [],
  138.                 'last_used_issuer' => $lastUsedIssuer,
  139.                 'shopware_compare' => version_compare($this->shopwareVersion'6.4''<'),
  140.                 'payment_method_name' => $activeName,
  141.                 'current_payment_method_id' => $paymentMethodEntity->getId(),
  142.             ]);
  143.             $event->getPage()->addExtension(
  144.                 MultiSafepayStruct::EXTENSION_NAME,
  145.                 $struct
  146.             );
  147.         } catch (InvalidArgumentException ApiException ClientExceptionInterface $exception) {
  148.             /***
  149.              * @TODO add better logging system
  150.              */
  151.         }
  152.     }
  153.     /**
  154.      * @param Issuer[] $issuers
  155.      * @param string|null $lastUsedIssuer
  156.      * @param string|null $gatewayCodeWithIssuers
  157.      * @return string
  158.      */
  159.     private function getRealGatewayNameWithIssuers(array $issuers, ?string $lastUsedIssuer, ?string $gatewayCodeWithIssuers): string
  160.     {
  161.         $result $gatewayCodeWithIssuers ?? '';
  162.         foreach ($issuers as $issuer) {
  163.             if ($issuer->getCode() === $lastUsedIssuer) {
  164.                 return $result ' (' $issuer->getDescription() . ')';
  165.             }
  166.         }
  167.         return $result;
  168.     }
  169.     private function getComponentsToken(SalesChannelContext $salesChannelContext): ?string
  170.     {
  171.         if (!$this->settingsService->getGatewaySetting($salesChannelContext->getPaymentMethod(), 'component')) {
  172.             return null;
  173.         }
  174.         try {
  175.             return $this->sdkFactory->create($salesChannelContext->getSalesChannel()->getId())->getApiTokenManager()
  176.                 ->get()->getApiToken();
  177.         } catch (ApiException ClientExceptionInterface $exception) {
  178.             return null;
  179.         }
  180.     }
  181.     private function getComponentsEnvironment(SalesChannelContext $salesChannelContext): ?string
  182.     {
  183.         if (!$this->settingsService->getGatewaySetting($salesChannelContext->getPaymentMethod(), 'component')) {
  184.             return null;
  185.         }
  186.         return $this->settingsService->isLiveMode() ? 'live' 'test';
  187.     }
  188.     private function getLocale(string $languageIdContext $context): string
  189.     {
  190.         $criteria = new Criteria([$languageId]);
  191.         $criteria->addAssociation('locale');
  192.         $locale $this->languageRepository->search($criteria$context)
  193.             ->get($languageId)->getLocale()->getCode();
  194.         return substr($locale02);
  195.     }
  196.     /**
  197.      * @param string $paymentHandler
  198.      * @return string|null
  199.      */
  200.     private function getGatewayCode(string $paymentHandler): ?string
  201.     {
  202.         foreach (PaymentUtil::GATEWAYS as $gateway) {
  203.             /** @var PaymentMethodInterface $gateway */
  204.             $gateway = new $gateway();
  205.             if ($gateway->getPaymentHandler() === $paymentHandler) {
  206.                 return $gateway->getGatewayCode();
  207.             }
  208.         }
  209.         return null;
  210.     }
  211.     /**
  212.      * @param SalesChannelContext $salesChannelContext
  213.      * @return bool
  214.      */
  215.     private function showTokenization(SalesChannelContext $salesChannelContext): bool
  216.     {
  217.         if ($salesChannelContext->getCustomer()->getGuest()) {
  218.             return false;
  219.         }
  220.         if (!in_array(
  221.             Tokenization::class,
  222.             class_uses($salesChannelContext->getPaymentMethod()->getHandlerIdentifier())
  223.         )) {
  224.             return false;
  225.         }
  226.         return (bool)$this->settingsService->getGatewaySetting(
  227.             $salesChannelContext->getPaymentMethod(),
  228.             'tokenization',
  229.             false
  230.         );
  231.     }
  232.     private function getTokens(SalesChannelContext $salesChannelContext): ?array
  233.     {
  234.         if (!$this->settingsService->getGatewaySetting($salesChannelContext->getPaymentMethod(), 'component')) {
  235.             return null;
  236.         }
  237.         try {
  238.             return $this->sdkFactory->create($salesChannelContext->getSalesChannel()->getId())
  239.                 ->getTokenManager()
  240.                 ->getListByGatewayCodeAsArray($salesChannelContext->getCustomer()->getId(), $this->getGatewayCode($salesChannelContext->getPaymentMethod()->getHandlerIdentifier()));
  241.         } catch (ApiException ClientExceptionInterface $exception) {
  242.             return [];
  243.         }
  244.     }
  245.     private function getTemplateId(): ?string
  246.     {
  247.         return $this->settingsService->getSetting('templateId');
  248.     }
  249. }