billwerk_subscriptions-1.x-dev/src/Controller/WebhookListenerController.php

src/Controller/WebhookListenerController.php
<?php

declare(strict_types=1);

namespace Drupal\billwerk_subscriptions\Controller;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Controller\ControllerBase;
use Drupal\billwerk_subscriptions\Event\BillwerkWebhookEvent;
use Drupal\billwerk_subscriptions\Exception\WebhookException;
use Drupal\billwerk_subscriptions\LogHelper;
use Drupal\billwerk_subscriptions\SettingsHelper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Returns responses for Billwerk Subscriptions routes.
 */
final class WebhookListenerController extends ControllerBase {

  /**
   * The constructor.
   *
   * @param \Drupal\billwerk_subscriptions\SettingsHelper $settingsHelper
   *   The Settings Helper.
   * @param \Drupal\billwerk_subscriptions\LogHelper $logHelper
   *   The Log Helper.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
   *   The Event Dispatcher.
   */
  public function __construct(
    protected readonly SettingsHelper $settingsHelper,
    protected readonly LogHelper $logHelper,
    protected readonly EventDispatcherInterface $eventDispatcher,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
    $container->get('billwerk_subscriptions.settings_helper'),
    $container->get('billwerk_subscriptions.log_helper'),
    $container->get('event_dispatcher'),
    );
  }

  /**
   * Listens to incoming Billwerk webhook calls.
   *
   * @param string $secret
   *   The secret to authenticate the webhook call.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response.
   */
  public function listen($secret, Request $request): Response {
    // Only handle webhooks that know the secret to prevent disallowed calls.
    // As the path is public and hard-coded this would be risky Otherwise.
    // @improve: A more secure authentication would be even better!
    if ($secret === $this->settingsHelper->getWebhookSecret()) {
      try {
        // Extract payload.
        // The given data is at a bare minimum for security reasons,
        // so we have to fetch details ourselves, see
        // https://docu.billwerk.plus/api/premium-enterprise/en/webhooks/general/security---reliability.html
        // for explanations and
        // https://docu.billwerk.plus/api/premium-enterprise/en/webhooks/customer-and-contract.html
        // for details about the provided data.
        $payload = $request->getContent();
        if (empty($payload)) {
          $payload = file_get_contents("php://input");
        }
        if (!empty($payload)) {
          $data = Json::decode($payload);
          $webhookEventName = $data["Event"];
        }
        if (!empty($webhookEventName)) {
          $billwerkWebhookEvent = new BillwerkWebhookEvent($payload);
          $this->eventDispatcher->dispatch($billwerkWebhookEvent, BillwerkWebhookEvent::EVENT_NAME_PREFIX . $webhookEventName);
        }
        else {
          throw new WebhookException('Webhook event name could not be determined from the payload!');
        }
        // Billwerk will recognize this call as successful.
        // @see https://docu.billwerk.plus/api/premium-enterprise/en/webhooks/general/security---reliability.html
        return new Response('OK', 200);
      }
      catch (\Exception $e) {
        $this->logHelper->logException($e);
        // Billwerk will repeat failed calls a dozen times!
        // @see https://docu.billwerk.plus/api/premium-enterprise/en/webhooks/general/security---reliability.html
        return new Response($e->getMessage(), 500);
      }
    }
    else {
      // Return a regular Drupal page not found, if the secret does not match.
      throw new NotFoundHttpException();
    }

  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc