custom/plugins/CkoShopware6/src/Subscriber/SystemConfigSubscriber.php line 70

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Cko\Shopware6\Subscriber;
  4. use Checkout\CheckoutApiException;
  5. use Checkout\HttpMetadata;
  6. use Cko\Shopware6\Exception\CheckoutComWebhookNotFoundException;
  7. use Cko\Shopware6\Factory\SettingsFactory;
  8. use Cko\Shopware6\Service\CheckoutApi\CheckoutWebhookService;
  9. use Cko\Shopware6\Service\CheckoutApi\CheckoutWorkflowService;
  10. use Cko\Shopware6\Struct\SystemConfig\SettingStruct;
  11. use Shopware\Core\System\SystemConfig\Event\BeforeSystemConfigChangedEvent;
  12. use Shopware\Core\System\SystemConfig\Event\SystemConfigChangedEvent;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Symfony\Component\HttpFoundation\Response;
  15. use Throwable;
  16. /**
  17.  * This subscriber is used to register the webhook to Checkout.com whenever
  18.  * CkoShopware6.config.checkoutPluginConfigSectionApi config key is updated
  19.  */
  20. class SystemConfigSubscriber implements EventSubscriberInterface
  21. {
  22.     private array $webhookData = [];
  23.     private CheckoutWebhookService $checkoutWebhookService;
  24.     private CheckoutWorkflowService $checkoutWorkflowService;
  25.     private SettingsFactory $settingsFactory;
  26.     public function __construct(
  27.         CheckoutWebhookService $checkoutWebhookService,
  28.         CheckoutWorkflowService $checkoutWorkflowService,
  29.         SettingsFactory $settingsFactory
  30.     ) {
  31.         $this->checkoutWebhookService $checkoutWebhookService;
  32.         $this->checkoutWorkflowService $checkoutWorkflowService;
  33.         $this->settingsFactory $settingsFactory;
  34.     }
  35.     public static function getSubscribedEvents(): array
  36.     {
  37.         return [
  38.             SystemConfigChangedEvent::class => 'onChangeConfig',
  39.             BeforeSystemConfigChangedEvent::class => 'onBeforeChangeConfig',
  40.         ];
  41.     }
  42.     /**
  43.      * To ensure the webhook data won't be replaced by the old value
  44.      */
  45.     public function onBeforeChangeConfig(BeforeSystemConfigChangedEvent $event): void
  46.     {
  47.         if ($event->getKey() !== SettingsFactory::SYSTEM_CONFIG_DOMAIN SettingsFactory::CHECKOUT_PLUGIN_CONFIG_WEBHOOK) {
  48.             return;
  49.         }
  50.         if (empty($this->webhookData)) {
  51.             return;
  52.         }
  53.         $event->setValue($this->webhookData);
  54.     }
  55.     /**
  56.      * Register webhook to checkout.com after updated plugin config
  57.      */
  58.     public function onChangeConfig(SystemConfigChangedEvent $event): void
  59.     {
  60.         if ($event->getKey() !== SettingsFactory::SYSTEM_CONFIG_DOMAIN SettingsFactory::CHECKOUT_PLUGIN_CONFIG_SECTION) {
  61.             return;
  62.         }
  63.         $salesChannelId $event->getSalesChannelId();
  64.         if ($event->getValue() === null) {
  65.             $this->setSettingWebhook(null$salesChannelId);
  66.             return;
  67.         }
  68.         $settings $this->settingsFactory->getSettings($salesChannelId);
  69.         $webhook $this->settingsFactory->getWebhookConfig($salesChannelId);
  70.         $webhookId $webhook->getId();
  71.         // Registering new webhook if there is no registered webhook
  72.         if ($webhookId === null) {
  73.             $this->registerWebhook($settings$salesChannelId);
  74.             return;
  75.         }
  76.         try {
  77.             // skip if webhook already registered
  78.             $this->receiveWebhook($settings$webhookId$salesChannelId);
  79.         } catch (CheckoutComWebhookNotFoundException $e) {
  80.             // Register a new webhook when "retrieveWebhook" returns a 404 status
  81.             $this->registerWebhook($settings$salesChannelId);
  82.         } catch (Throwable $e) {
  83.             // do nothing to make sure this exception does not block any action behind
  84.         }
  85.     }
  86.     private function setSettingWebhook(?array $webhookData null, ?string $salesChannelId null): void
  87.     {
  88.         $this->settingsFactory->set(
  89.             SettingsFactory::SYSTEM_CONFIG_DOMAIN SettingsFactory::CHECKOUT_PLUGIN_CONFIG_WEBHOOK,
  90.             $webhookData,
  91.             $salesChannelId
  92.         );
  93.     }
  94.     private function registerWebhook(SettingStruct $settings, ?string $salesChannelId null): void
  95.     {
  96.         try {
  97.             if ($settings->isAccountType(SettingStruct::ACCOUNT_TYPE_ABC)) {
  98.                 $webhook $this->checkoutWebhookService->registerWebhook($salesChannelId);
  99.             } else {
  100.                 $webhook $this->checkoutWorkflowService->createWorkFlows($salesChannelId);
  101.             }
  102.             // save registered webhook data to system config
  103.             $this->setSettingWebhook($webhook->getVars(), $salesChannelId);
  104.             $this->webhookData $webhook->getVars();
  105.         } catch (Throwable $e) {
  106.             // do nothing to make sure this exception does not block any action behind
  107.         }
  108.     }
  109.     /**
  110.      * @throws CheckoutApiException
  111.      */
  112.     private function receiveWebhook(SettingStruct $settingsstring $webhookId, ?string $salesChannelId): void
  113.     {
  114.         try {
  115.             if ($settings->isAccountType(SettingStruct::ACCOUNT_TYPE_ABC)) {
  116.                 $this->checkoutWebhookService->retrieveWebhook($webhookId$salesChannelId);
  117.             } else {
  118.                 $this->checkoutWorkflowService->getWorkflow($webhookId$salesChannelId);
  119.             }
  120.         } catch (CheckoutApiException $e) {
  121.             $httpMetaData $e->http_metadata;
  122.             if (!$httpMetaData instanceof HttpMetadata) {
  123.                 throw new CheckoutComWebhookNotFoundException($webhookId);
  124.             }
  125.             if ($httpMetaData->getStatusCode() === Response::HTTP_NOT_FOUND) {
  126.                 throw new CheckoutComWebhookNotFoundException($webhookId);
  127.             }
  128.             throw $e;
  129.         }
  130.     }
  131. }