custom/plugins/FourtwosixThemeExtension/src/Controller/Hub/GetPriceController.php line 243

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace FourtwosixThemeExtension\Controller\Hub;
  3. use Exception;
  4. use FourtwosixThemeExtension\Exception\CountryNotFoundException;
  5. use FourtwosixThemeExtension\Exception\InvalidSalesChannelId;
  6. use FourtwosixThemeExtension\Exception\NullCountryIsoException;
  7. use FourtwosixThemeExtension\Exception\NullCustomerEmailException;
  8. use FourtwosixThemeExtension\Exception\NullZipCodeException;
  9. use FourtwosixThemeExtension\Service\VirtualCartService;
  10. use Shopware\Core\Checkout\Cart\Delivery\Struct\ShippingLocation;
  11. use Shopware\Core\Checkout\Cart\Order\OrderConversionContext;
  12. use Shopware\Core\Checkout\Cart\Order\OrderConverter;
  13. use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity;
  14. use Shopware\Core\Checkout\Customer\CustomerEntity;
  15. use Shopware\Core\Defaults;
  16. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  19. use Shopware\Core\Framework\Uuid\Uuid;
  20. use Shopware\Core\System\Country\CountryEntity;
  21. use Shopware\Core\System\SalesChannel\Context\AbstractBaseContextFactory;
  22. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  23. use Shopware\Core\System\SystemConfig\SystemConfigService;
  24. use Shopware\Storefront\Controller\StorefrontController;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpKernel\Exception\HttpException;
  28. use Symfony\Component\Routing\Annotation\Route;
  29. /**
  30.  * @Route(defaults={"_routeScope"={"storefront"}})
  31.  */
  32. class GetPriceController extends StorefrontController
  33. {
  34.     protected SystemConfigService $systemConfigService;
  35.     protected ?string $webhookSecret null;
  36.     protected VirtualCartService $virtualCart;
  37.     protected AbstractBaseContextFactory $baseContextFactory;
  38.     protected EntityRepositoryInterface $countryRepository;
  39.     protected EntityRepositoryInterface $salesChannelRepository;
  40.     protected array $allowedSalesChannel;
  41.     protected OrderConverter $orderConverter;
  42.     public function __construct(
  43.         SystemConfigService                $systemConfigService,
  44.         VirtualCartService                 $virtualCart,
  45.         AbstractBaseContextFactory         $baseContextFactory,
  46.         EntityRepositoryInterface          $countryRepository,
  47.         EntityRepositoryInterface          $salesChannelRepository,
  48.         OrderConverter                     $orderConverter
  49.     ) {
  50.         $this->systemConfigService $systemConfigService;
  51.         $this->virtualCart $virtualCart;
  52.         $this->baseContextFactory $baseContextFactory;
  53.         $this->countryRepository $countryRepository;
  54.         $this->salesChannelRepository $salesChannelRepository;
  55.         $this->orderConverter $orderConverter;
  56.         $this->allowedSalesChannel $this->systemConfigService->get('FourtwosixThemeExtension.config.allowedSalesChannel');
  57.         $this->webhookSecret $this->systemConfigService->get('FourtwosixThemeExtension.config.shopSecret');
  58.     }
  59.     /**
  60.      * @Route("/calculate-price", name="calculate.hub.price", defaults={"csrf_protected"=false}, methods={"POST"})
  61.      * @throws Exception
  62.      */
  63.     public function calculatePrice(Request $requestSalesChannelContext $context): Response
  64.     {
  65.         $secretMatches $request->get("secret") === $this->webhookSecret;
  66.         if (!$secretMatches) {
  67.             throw new HttpException(500"Wrong secret");
  68.         }
  69.         try {
  70.             $payload json_decode(
  71.                 $request->getContent(),
  72.                 true
  73.             );
  74.             $zipcode $payload["customer"]["zipcode"] ?? null;
  75.             $countryIso $payload["customer"]["country_iso"] ?? null;
  76.             $salesChannelId $payload["customer"]["sales_channel_id"] ?? null;
  77.             $customerEmail $payload["customer"]["email"] ?? null;
  78.             $this->validatePayloadData(
  79.                 $customerEmail,
  80.                 $zipcode,
  81.                 $countryIso,
  82.                 $salesChannelId,
  83.             );
  84.             // Also customer not registered in SW should be able to get discounts calculation and shipping
  85.             $customer $this->virtualCart->getCustomer($customerEmail$context->getContext());
  86.             $criteria = new Criteria();
  87.             $criteria->addFilter(new EqualsFilter("iso"$countryIso));
  88.             $country $this->countryRepository->search($criteria$context->getContext())->first();
  89.             if (is_null($country)) {
  90.                 throw new CountryNotFoundException();
  91.             }
  92.             // Create a fake address where insert data passed via payload to create a new salesChannelContext
  93.             $customerAddress $this->createFakeAddress($zipcode$country);
  94.             $shippingLocation = new ShippingLocation($countrynull$customerAddress);
  95.             $salesChannelContext $this->recreateSalesChannelContext(
  96.                 $context,
  97.                 $salesChannelId,
  98.                 $shippingLocation,
  99.                 $customer,
  100.                 $country
  101.             );
  102.             $this->virtualCart->addLineItemsToCart($salesChannelContext$payload["order_lines"]);
  103.             $conversionContext = (new OrderConversionContext())
  104.                 ->setIncludeCustomer(false)
  105.                 ->setIncludeBillingAddress(false)
  106.                 ->setIncludeDeliveries(true)
  107.                 ->setIncludeTransactions(false)
  108.                 ->setIncludeOrderDate(false);
  109.             $data $this->orderConverter->convertToOrder(
  110.                 $this->virtualCart->getCart($salesChannelContext),
  111.                 $salesChannelContext,
  112.                 $conversionContext
  113.             );
  114.             $this->virtualCart->destroy($salesChannelContext);
  115.             $success true;
  116.             $response $data;
  117.         } catch (Exception $e) {
  118.             $success false;
  119.             $response $e->getMessage();
  120.         }
  121.         return $this->json([
  122.             "success" => $success,
  123.             "response" => $response,
  124.         ], $success 200 500);
  125.     }
  126.     /**
  127.      * @param string|null $customerEmail
  128.      * @param string|null $zipcode
  129.      * @param string|null $countryIso
  130.      * @param string|null $salesChannelId
  131.      * @return void
  132.      * @throws InvalidSalesChannelId
  133.      * @throws NullCountryIsoException
  134.      * @throws NullCustomerEmailException
  135.      * @throws NullZipCodeException
  136.      */
  137.     public function validatePayloadData(
  138.         ?string $customerEmail,
  139.         ?string $zipcode,
  140.         ?string $countryIso,
  141.         ?string $salesChannelId
  142.     ): void {
  143.         if (is_null($customerEmail)) {
  144.             throw new NullCustomerEmailException();
  145.         }
  146.         if (is_null($zipcode)) {
  147.             throw new NullZipCodeException();
  148.         }
  149.         if (is_null($countryIso)) {
  150.             throw new NullCountryIsoException();
  151.         }
  152.         if (is_null($salesChannelId) || !in_array($salesChannelId$this->allowedSalesChannel)) {
  153.             throw new InvalidSalesChannelId();
  154.         }
  155.     }
  156.     /**
  157.      * @param $zipcode
  158.      * @param $country
  159.      * @return CustomerAddressEntity
  160.      */
  161.     public function createFakeAddress($zipcode$country): CustomerAddressEntity
  162.     {
  163.         $customerAddress = new CustomerAddressEntity();
  164.         $customerAddress->setId(Uuid::randomHex());
  165.         $customerAddress->setFirstName('Max');
  166.         $customerAddress->setLastName('Mustermann');
  167.         $customerAddress->setStreet('Musterstraße 1');
  168.         $customerAddress->setCity('Schöppingen');
  169.         $customerAddress->setZipcode($zipcode);
  170.         $customerAddress->setSalutationId(Defaults::SALUTATION);
  171.         $customerAddress->setCountryId($country->getId());
  172.         $customerAddress->setCountry($country);
  173.         return $customerAddress;
  174.     }
  175.     /**
  176.      * @param SalesChannelContext $context
  177.      * @param string              $salesChannelId
  178.      * @param ShippingLocation    $shippingLocation
  179.      * @param CustomerEntity|null $customer
  180.      * @param CountryEntity       $country
  181.      * @return SalesChannelContext
  182.      * @throws Exception
  183.      */
  184.     public function recreateSalesChannelContext(
  185.         SalesChannelContext $context,
  186.         string              $salesChannelId,
  187.         ShippingLocation    $shippingLocation,
  188.         ?CustomerEntity     $customer,
  189.         CountryEntity       $country
  190.     ): SalesChannelContext {
  191.         $base $this->baseContextFactory->create($context->getSalesChannelId(), []);
  192.         // Getting existing saleschannel
  193.         $criteria = new Criteria();
  194.         $criteria->addFilter(new EqualsFilter("id"$salesChannelId));
  195.         $salesChannel $this->salesChannelRepository->search($criteria$context->getContext())->first();
  196.         $salesChannel is_null($salesChannel) ? $base->getSalesChannel() : $salesChannel;
  197.         $shippingMethod $this->virtualCart->getShipping($country$context);
  198.         if(is_null($shippingMethod)){
  199.             throw new Exception("customer_invalid ssasd");
  200.         }
  201.         return new SalesChannelContext(
  202.             $context->getContext(),
  203.             $context->getToken(),
  204.             null,
  205.             $salesChannel,
  206.             $base->getCurrency(),
  207.             $base->getCurrentCustomerGroup(),
  208.             $base->getFallbackCustomerGroup(),
  209.             $context->getTaxRules(),
  210.             $context->getPaymentMethod(),
  211.             $shippingMethod,
  212.             $shippingLocation,
  213.             $customer,
  214.             $base->getItemRounding(),
  215.             $base->getTotalRounding(),
  216.             $context->getRuleIds()
  217.         );
  218.     }
  219. }