custom/plugins/KlarnaPayment/src/Components/EventListener/PaymentMethodEventListener.php line 50

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace KlarnaPayment\Components\EventListener;
  4. use KlarnaPayment\Components\ConfigReader\ConfigReaderInterface;
  5. use KlarnaPayment\Installer\Modules\PaymentMethodInstaller;
  6. use KlarnaPayment\Installer\Modules\RuleInstaller;
  7. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  8. use Shopware\Core\Framework\Api\Context\SalesChannelApiSource;
  9. use Shopware\Core\Framework\Context;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityIdSearchResultLoadedEvent;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntitySearchResultLoadedEvent;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
  16. use Shopware\Core\Framework\Event\GenericEvent;
  17. use Shopware\Core\System\Language\LanguageEntity;
  18. use Shopware\Core\System\Locale\LocaleEntity;
  19. use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityIdSearchResultLoadedEvent;
  20. use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntitySearchResultLoadedEvent;
  21. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  22. class PaymentMethodEventListener implements EventSubscriberInterface
  23. {
  24.     /** @var ConfigReaderInterface */
  25.     private $configReader;
  26.     /** @var EntityRepositoryInterface */
  27.     private $languageRepository;
  28.     public function __construct(ConfigReaderInterface $configReaderEntityRepositoryInterface $languageRepository)
  29.     {
  30.         $this->configReader       $configReader;
  31.         $this->languageRepository $languageRepository;
  32.     }
  33.     public static function getSubscribedEvents(): array
  34.     {
  35.         return [
  36.             'sales_channel.payment_method.search.id.result.loaded' => ['onSalesChannelIdSearchResultLoaded', -1],
  37.             'payment_method.search.id.result.loaded'               => ['onIdSearchResultLoaded', -1],
  38.             'sales_channel.payment_method.search.result.loaded'    => ['onSalesChannelSearchResultLoaded', -1],
  39.             'payment_method.search.result.loaded'                  => ['onSearchResultLoaded', -1],
  40.         ];
  41.     }
  42.     public function onSalesChannelIdSearchResultLoaded(SalesChannelEntityIdSearchResultLoadedEvent $event): void
  43.     {
  44.         $source $event->getContext()->getSource();
  45.         if (!($source instanceof SalesChannelApiSource)) {
  46.             return;
  47.         }
  48.         if ($this->removeInvalidPaymentMethods($event)) {
  49.             return;
  50.         }
  51.         $this->removeDeactivatedPaymentMethodsIds($event->getResult(), $source->getSalesChannelId());
  52.     }
  53.     public function onIdSearchResultLoaded(EntityIdSearchResultLoadedEvent $event): void
  54.     {
  55.         $source $event->getContext()->getSource();
  56.         if (!($source instanceof SalesChannelApiSource)) {
  57.             return;
  58.         }
  59.         $this->removeDeactivatedPaymentMethodsIds($event->getResult(), $source->getSalesChannelId());
  60.     }
  61.     public function onSalesChannelSearchResultLoaded(SalesChannelEntitySearchResultLoadedEvent $event): void
  62.     {
  63.         $source $event->getContext()->getSource();
  64.         if (!($source instanceof SalesChannelApiSource)) {
  65.             return;
  66.         }
  67.         if ($this->removeInvalidPaymentMethods($event)) {
  68.             return;
  69.         }
  70.         $this->removeDeactivatedPaymentMethods($event->getResult(), $source->getSalesChannelId());
  71.     }
  72.     public function onSearchResultLoaded(EntitySearchResultLoadedEvent $event): void
  73.     {
  74.         $source $event->getContext()->getSource();
  75.         if (!($source instanceof SalesChannelApiSource)) {
  76.             return;
  77.         }
  78.         $this->removeDeactivatedPaymentMethods($event->getResult(), $source->getSalesChannelId());
  79.     }
  80.     private function removeDeactivatedPaymentMethods(EntitySearchResult $resultstring $salesChannelId null): void
  81.     {
  82.         $validPaymentMethods     $this->getValidPaymentMethods($salesChannelId);
  83.         $allKlarnaPaymentMethods $this->getAllKlarnaPaymentMethods();
  84.         $filter = static function (PaymentMethodEntity $entity) use ($validPaymentMethods$allKlarnaPaymentMethods) {
  85.             if (!in_array($entity->getId(), $allKlarnaPaymentMethodstrue)) {
  86.                 return true;
  87.             }
  88.             return in_array($entity->getId(), $validPaymentMethodstrue);
  89.         };
  90.         $filteredPaymentMethods $result->getEntities()->filter($filter);
  91.         $result->assign([
  92.             'total'    => count($filteredPaymentMethods),
  93.             'entities' => $filteredPaymentMethods,
  94.             'elements' => $filteredPaymentMethods->getElements(),
  95.         ]);
  96.     }
  97.     /**
  98.      * @param SalesChannelEntityIdSearchResultLoadedEvent|SalesChannelEntitySearchResultLoadedEvent $event
  99.      */
  100.     private function removeInvalidPaymentMethods(GenericEvent $event): bool
  101.     {
  102.         $salesChannelContext $event->getSalesChannelContext();
  103.         $customer            $salesChannelContext->getCustomer();
  104.         $currencyIsoCode     $salesChannelContext->getCurrency()->getIsoCode();
  105.         $languageId          $salesChannelContext->getSalesChannel()->getLanguageId();
  106.         $billingAddress      $customer $customer->getDefaultBillingAddress() : null;
  107.         $language            $this->getLanguageById($languageId$salesChannelContext->getContext());
  108.         if (!$language || !$billingAddress || !($country $billingAddress->getCountry()) || !($countryIso $country->getIso())) {
  109.             return false;
  110.         }
  111.         /** @var LocaleEntity $locale */
  112.         $locale       $language->getLocale();
  113.         $klarnaLocale strtolower(substr($locale->getCode(), 02)) . '-' strtoupper($countryIso);
  114.         $rule         RuleInstaller::AVAIBILITY_CONDITIONS[$countryIso] ?? null;
  115.         if ($rule === null || $rule['currency'] !== $currencyIsoCode || !in_array($klarnaLocale$rule['locales'], true)) {
  116.             if ($event instanceof SalesChannelEntityIdSearchResultLoadedEvent) {
  117.                 $this->removeAllKlarnaPaymentMethodsIds($event->getResult());
  118.             } else {
  119.                 $this->removeAllKlarnaPaymentMethods($event->getResult());
  120.             }
  121.             return true;
  122.         }
  123.         return false;
  124.     }
  125.     private function removeAllKlarnaPaymentMethods(EntitySearchResult $result): void
  126.     {
  127.         $allKlarnaPaymentMethods $this->getAllKlarnaPaymentMethods();
  128.         $filter = static function (PaymentMethodEntity $entity) use ($allKlarnaPaymentMethods) {
  129.             if (in_array($entity->getId(), $allKlarnaPaymentMethodstrue)) {
  130.                 return false;
  131.             }
  132.             return true;
  133.         };
  134.         $filteredPaymentMethods $result->getEntities()->filter($filter);
  135.         $result->assign([
  136.             'total'    => count($filteredPaymentMethods),
  137.             'entities' => $filteredPaymentMethods,
  138.             'elements' => $filteredPaymentMethods->getElements(),
  139.         ]);
  140.     }
  141.     private function removeAllKlarnaPaymentMethodsIds(IdSearchResult $result): void
  142.     {
  143.         $allKlarnaPaymentMethods $this->getAllKlarnaPaymentMethods();
  144.         $filter = static function (string $paymentMethod) use ($allKlarnaPaymentMethods) {
  145.             if (in_array($paymentMethod$allKlarnaPaymentMethodstrue)) {
  146.                 return false;
  147.             }
  148.             return true;
  149.         };
  150.         $filteredPaymentMethods array_filter($result->getIds(), $filter);
  151.         $result->assign([
  152.             'total'    => count($filteredPaymentMethods),
  153.             'ids'      => $filteredPaymentMethods,
  154.             'entities' => $filteredPaymentMethods,
  155.             'elements' => $filteredPaymentMethods,
  156.         ]);
  157.     }
  158.     private function removeDeactivatedPaymentMethodsIds(IdSearchResult $resultstring $salesChannelId null): void
  159.     {
  160.         $validPaymentMethods     $this->getValidPaymentMethods($salesChannelId);
  161.         $allKlarnaPaymentMethods $this->getAllKlarnaPaymentMethods();
  162.         $filter = static function (string $paymentMethod) use ($validPaymentMethods$allKlarnaPaymentMethods) {
  163.             if (!in_array($paymentMethod$allKlarnaPaymentMethodstrue)) {
  164.                 return true;
  165.             }
  166.             return in_array($paymentMethod$validPaymentMethodstrue);
  167.         };
  168.         $filteredPaymentMethods array_filter($result->getIds(), $filter);
  169.         $result->assign([
  170.             'total'    => count($filteredPaymentMethods),
  171.             'ids'      => $filteredPaymentMethods,
  172.             'entities' => $filteredPaymentMethods,
  173.             'elements' => $filteredPaymentMethods,
  174.         ]);
  175.     }
  176.     private function getValidPaymentMethods(string $salesChannelId null): array
  177.     {
  178.         $config $this->configReader->read($salesChannelId);
  179.         if ($config->get('klarnaType') === 'checkout') {
  180.             $validPaymentMethods array_keys(PaymentMethodInstaller::KLARNA_CHECKOUT_CODES);
  181.         } elseif ($config->get('klarnaType') === 'payments') {
  182.             $validPaymentMethods array_keys(PaymentMethodInstaller::KLARNA_PAYMENTS_CODES);
  183.             $merchantValidKlarnaPaymentsMethods $config->get('allowedKlarnaPaymentsCodes', []);
  184.             if (in_array(PaymentMethodInstaller::KLARNA_PAYMENTS_PAY_NOW_CODE$merchantValidKlarnaPaymentsMethodstrue)) {
  185.                 $additionalValidCodes array_map(
  186.                     static function (string $paymentMethodId) {
  187.                         return PaymentMethodInstaller::KLARNA_PAYMENTS_CODES[$paymentMethodId];
  188.                     },
  189.                     PaymentMethodInstaller::KLARNA_PAYMENTS_CODES_PAY_NOW_STANDALONE
  190.                 );
  191.                 $merchantValidKlarnaPaymentsMethods array_unique(array_merge($merchantValidKlarnaPaymentsMethods$additionalValidCodes));
  192.             }
  193.             $validPaymentMethods array_filter(
  194.                 $validPaymentMethods,
  195.                 static function (string $paymentMethodId) use ($merchantValidKlarnaPaymentsMethods) {
  196.                     return in_array(PaymentMethodInstaller::KLARNA_PAYMENTS_CODES[$paymentMethodId], $merchantValidKlarnaPaymentsMethodstrue);
  197.                 }
  198.             );
  199.         } else {
  200.             $validPaymentMethods = [];
  201.         }
  202.         return $validPaymentMethods;
  203.     }
  204.     private function getAllKlarnaPaymentMethods(): array
  205.     {
  206.         return array_merge(
  207.             array_keys(PaymentMethodInstaller::KLARNA_CHECKOUT_CODES),
  208.             array_keys(PaymentMethodInstaller::KLARNA_PAYMENTS_CODES)
  209.         );
  210.     }
  211.     private function getLanguageById(string $idContext $context): ?LanguageEntity
  212.     {
  213.         $criteria = new Criteria([$id]);
  214.         $criteria->addAssociation('locale');
  215.         return $this->languageRepository->search($criteria$context)->first();
  216.     }
  217. }