custom/plugins/StripeShopwarePayment/src/Webhook/StripeWebhookController.php line 91

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright (c) Pickware GmbH. All rights reserved.
  4.  * This file is part of software that is released under a proprietary license.
  5.  * You must not copy, modify, distribute, make publicly available, or execute
  6.  * its contents or parts thereof without express permission by the copyright
  7.  * holder, unless otherwise permitted by law.
  8.  */
  9. declare(strict_types=1);
  10. namespace Stripe\ShopwarePayment\Webhook;
  11. use Psr\Log\LoggerInterface;
  12. use Shopware\Core\Framework\Context;
  13. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  14. use Stripe\Exception\ExceptionInterface as StripeExceptionInterface;
  15. use Stripe\ShopwarePayment\OrderTransactionLocking\OrderTransactionLockingException;
  16. use Stripe\ShopwarePayment\StripeApi\StripeApiFactory;
  17. use Symfony\Component\HttpFoundation\JsonResponse;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\Routing\Annotation\Route;
  21. class StripeWebhookController
  22. {
  23.     /**
  24.      * @var StripeApiFactory
  25.      */
  26.     private $stripeApiFactory;
  27.     /**
  28.      * @var StripeWebhookEventDispatcher
  29.      */
  30.     private $stripeWebhookEventDispatcher;
  31.     /**
  32.      * @var StripeWebhookRegistrationService
  33.      */
  34.     private $stripeWebhookRegistrationService;
  35.     /**
  36.      * @var LoggerInterface
  37.      */
  38.     private $logger;
  39.     public function __construct(
  40.         StripeApiFactory $stripeApiFactory,
  41.         StripeWebhookEventDispatcher $stripeWebhookEventDispatcher,
  42.         StripeWebhookRegistrationService $stripeWebhookRegistrationService,
  43.         LoggerInterface $logger
  44.     ) {
  45.         $this->stripeApiFactory $stripeApiFactory;
  46.         $this->stripeWebhookEventDispatcher $stripeWebhookEventDispatcher;
  47.         $this->stripeWebhookRegistrationService $stripeWebhookRegistrationService;
  48.         $this->logger $logger;
  49.     }
  50.     /**
  51.      * @RouteScope(scopes={"api"})
  52.      * @Route(
  53.      *     "/api/_action/stripe-payment/register-webhook",
  54.      *     name="api.action.stripe-payment.register-webhook",
  55.      *     methods={"PUT"}
  56.      * )
  57.      */
  58.     public function registerWebhook(Request $requestContext $context): JsonResponse
  59.     {
  60.         $requestBody json_decode($request->getContent(), true);
  61.         try {
  62.             $result $this->stripeWebhookRegistrationService->registerWebhook(
  63.                 $context,
  64.                 $requestBody['salesChannelId'] ?? null,
  65.             );
  66.             return new JsonResponse(['result' => $result]);
  67.         } catch (StripeExceptionInterface $e) {
  68.             return new JsonResponse(['result' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
  69.         }
  70.     }
  71.     /**
  72.      * @RouteScope(scopes={"storefront"})
  73.      * @Route(
  74.      *     "/stripe-payment/webhook/execute",
  75.      *     name="frontend.stripe-payment.webhook.execute",
  76.      *     methods={"POST"},
  77.      *     defaults={"csrf_protected"=false}
  78.      * )
  79.      */
  80.     public function executeWebhook(Request $requestContext $context): Response
  81.     {
  82.         $webhookSignature $request->headers->get('stripe-signature');
  83.         if (!$webhookSignature) {
  84.             return new Response('Missing stripe-signature header'Response::HTTP_BAD_REQUEST);
  85.         }
  86.         $webhookPayload $request->getContent();
  87.         if (!$webhookPayload) {
  88.             return new Response('Missing webhook payload'Response::HTTP_BAD_REQUEST);
  89.         }
  90.         $salesChannelId $context->getSource()->getSalesChannelId();
  91.         $stripeApi $this->stripeApiFactory->createStripeApiForSalesChannel($context$salesChannelId);
  92.         try {
  93.             $event $stripeApi->createWebhookEvent($webhookPayload$webhookSignature);
  94.         } catch (StripeExceptionInterface $e) {
  95.             $this->logger->error(
  96.                 'Received an invalid Stripe webhook request and could not process the event because of the '
  97.                 'following error: ' $e->getMessage(),
  98.                 [
  99.                     'webhookPayload' => $webhookPayload,
  100.                     'webhookSignature' => $webhookSignature,
  101.                     'exceptionStackTrace' => $e->getTraceAsString(),
  102.                     'exception' => $e,
  103.                 ],
  104.             );
  105.             return new Response('Invalid stripe event'Response::HTTP_BAD_REQUEST);
  106.         }
  107.         try {
  108.             $this->stripeWebhookEventDispatcher->dispatch($event$context);
  109.         } catch (OrderTransactionLockingException WebhookException $e) {
  110.             $this->logger->error(
  111.                 $e->getMessage(),
  112.                 [
  113.                     'event' => $event,
  114.                     'exception' => $e,
  115.                 ],
  116.             );
  117.             // Return HTTP status 200 because Stripe expects Webhook delivery to always return 2XX
  118.             // https://stripe.com/docs/webhooks/build#return-a-2xx-status-code-quickly
  119.             return new Response($e->getMessage(), Response::HTTP_OK);
  120.         }
  121.         return new Response(''Response::HTTP_OK);
  122.     }
  123. }