custom/plugins/RpayPayments/src/Components/InstallmentCalculator/Subscriber/BuildPaymentSubscriber.php line 53

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * Copyright (c) Ratepay GmbH
  5.  *
  6.  * For the full copyright and license information, please view the LICENSE
  7.  * file that was distributed with this source code.
  8.  */
  9. namespace Ratepay\RpayPayments\Components\InstallmentCalculator\Subscriber;
  10. use Exception;
  11. use InvalidArgumentException;
  12. use RatePAY\Model\Request\SubModel\Content\Payment;
  13. use RatePAY\Model\Request\SubModel\Content\Payment\InstallmentDetails;
  14. use RatePAY\Model\Request\SubModel\Content\ShoppingBasket;
  15. use Ratepay\RpayPayments\Components\InstallmentCalculator\Exception\DebitNotAllowedOnInstallment;
  16. use Ratepay\RpayPayments\Components\InstallmentCalculator\Model\InstallmentCalculatorContext;
  17. use Ratepay\RpayPayments\Components\InstallmentCalculator\Service\InstallmentService;
  18. use Ratepay\RpayPayments\Components\InstallmentCalculator\Util\PlanHasher;
  19. use Ratepay\RpayPayments\Components\RatepayApi\Dto\AddCreditData;
  20. use Ratepay\RpayPayments\Components\RatepayApi\Dto\OrderOperationData;
  21. use Ratepay\RpayPayments\Components\RatepayApi\Dto\PaymentRequestData;
  22. use Ratepay\RpayPayments\Components\RatepayApi\Event\BuildEvent;
  23. use Ratepay\RpayPayments\Components\RatepayApi\Factory\PaymentFactory;
  24. use Ratepay\RpayPayments\Components\RatepayApi\Factory\ShoppingBasketFactory;
  25. use Ratepay\RpayPayments\Util\MethodHelper;
  26. use Ratepay\RpayPayments\Util\PaymentFirstday;
  27. use RuntimeException;
  28. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  29. use Shopware\Core\Framework\Validation\DataBag\DataBag;
  30. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  31. class BuildPaymentSubscriber implements EventSubscriberInterface
  32. {
  33.     private InstallmentService $installmentService;
  34.     public function __construct(InstallmentService $installmentService)
  35.     {
  36.         $this->installmentService $installmentService;
  37.     }
  38.     public static function getSubscribedEvents(): array
  39.     {
  40.         return [
  41.             PaymentFactory::class => 'buildPayment',
  42.             ShoppingBasketFactory::class => 'buildShoppingBasket',
  43.         ];
  44.     }
  45.     public function buildPayment(BuildEvent $event): void
  46.     {
  47.         /** @var PaymentRequestData $requestData */
  48.         $requestData $event->getRequestData();
  49.         if (MethodHelper::isInstallmentMethod($requestData->getTransaction()->getPaymentMethod()->getHandlerIdentifier())) {
  50.             /** @var Payment $paymentObject */
  51.             $paymentObject $event->getBuildData();
  52.             /** @var DataBag $requestedInstallment */
  53.             $requestedInstallment $requestData->getRequestDataBag()->get('ratepay')->get('installment');
  54.             $calcContext = new InstallmentCalculatorContext(
  55.                 $requestData->getSalesChannelContext(),
  56.                 $requestedInstallment->get('type'),
  57.                 $requestedInstallment->get('value')
  58.             );
  59.             $calcContext->setTotalAmount($paymentObject->getAmount());
  60.             $calcContext->setOrder($requestData->getOrder());
  61.             $calcContext->setPaymentMethod($requestData->getTransaction()->getPaymentMethod());
  62.             $plan $this->installmentService->getInstallmentPlanData($calcContext);
  63.             if (PlanHasher::isPlanEqualWithHash($requestedInstallment->get('hash'), $plan)) {
  64.                 throw new Exception('the hash value of the calculated plan does not match the given hash');
  65.             }
  66.             $paymentType $requestedInstallment->get('paymentType');
  67.             switch ($paymentType) {
  68.                 case 'DIRECT-DEBIT':
  69.                     $paymentFirstDay PaymentFirstday::DIRECT_DEBIT;
  70.                     break;
  71.                 case 'BANK-TRANSFER':
  72.                     $paymentFirstDay PaymentFirstday::BANK_TRANSFER;
  73.                     break;
  74.                 default:
  75.                     throw new InvalidArgumentException('invalid paymentType');
  76.             }
  77.             $paymentObject
  78.                 ->setAmount($plan['totalAmount'])
  79.                 ->setInstallmentDetails(
  80.                     (new InstallmentDetails())
  81.                         ->setInstallmentNumber($plan['numberOfRatesFull'])
  82.                         ->setInstallmentAmount($plan['rate'])
  83.                         ->setLastInstallmentAmount($plan['lastRate'])
  84.                         ->setInterestRate($plan['interestRate'])
  85.                         /* @phpstan-ignore-next-line */
  86.                         ->setPaymentFirstday($paymentFirstDay)
  87.                 )
  88.                 ->setDebitPayType($paymentType);
  89.         }
  90.     }
  91.     public function buildShoppingBasket(BuildEvent $event): BuildEvent
  92.     {
  93.         /** @var OrderOperationData $requestData */
  94.         $requestData $event->getRequestData();
  95.         if (!$requestData instanceof AddCreditData) {
  96.             return $event;
  97.         }
  98.         $paymentMethod $requestData->getTransaction()->getPaymentMethod();
  99.         if (!$paymentMethod instanceof PaymentMethodEntity) {
  100.             throw new RuntimeException('Payment method is not loaded on transaction entity within the request-data');
  101.         }
  102.         /** @var ShoppingBasket $basket */
  103.         $basket $event->getBuildData();
  104.         if (MethodHelper::isInstallmentMethod($paymentMethod->getHandlerIdentifier())) {
  105.             $items $basket->getItems()->admittedFields['Item']['value'];
  106.             /** @var ShoppingBasket\Items\Item $item */
  107.             foreach ($items as $item) {
  108.                 if ($item->getUnitPriceGross() > 0) {
  109.                     throw new DebitNotAllowedOnInstallment();
  110.                 }
  111.             }
  112.         }
  113.         return $event;
  114.     }
  115. }