src/Payment/PaymentContext.php line 49

Open in your IDE?
  1. <?php
  2. namespace App\Payment;
  3. use App\Entity\Sale;
  4. use App\Entity\Transaction;
  5. use App\Entity\Vehicle;
  6. use App\Payment\Dto\Payment;
  7. use App\Payment\Exception\AlreadyPaidException;
  8. use App\Repository\SaleRepository;
  9. use App\Repository\TransactionRepository;
  10. use App\Repository\UserRepository;
  11. use App\Repository\VehicleRepository;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Psr\Log\LoggerInterface;
  14. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  15. use Symfony\Component\HttpKernel\Exception\HttpException;
  16. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  17. /**
  18.  * This Class gives informations about current payment context.
  19.  */
  20. class PaymentContext
  21. {
  22.     private const SESSION_PAYMENT_KEY 'payment';
  23.     private $defaultAmount;
  24.     public function __construct(
  25.         private readonly SessionInterface $session,
  26.         private readonly SaleRepository $saleRepository,
  27.         private readonly VehicleRepository $vehicleRepository,
  28.         private readonly UserRepository $userRepository,
  29.         private readonly TransactionRepository $transactionRepository,
  30.         private readonly EntityManagerInterface $entityManager,
  31.         private readonly LoggerInterface $paymentLogger,
  32.         int $paymentDefaultAmount
  33.     ) {
  34.         $this->defaultAmount $paymentDefaultAmount;
  35.     }
  36.     public function forget(): void
  37.     {
  38.         $this->log('forgeting payment');
  39.         $this->session->remove(self::SESSION_PAYMENT_KEY);
  40.     }
  41.     public function getCurrentPayment(): ?Payment
  42.     {
  43.         $payment $this->session->get(self::SESSION_PAYMENT_KEY);
  44.         if (!$payment instanceof Payment) {
  45.             return null;
  46.         }
  47.         return $payment;
  48.     }
  49.     public function getCurrentVehicle(): ?Vehicle
  50.     {
  51.         $payment $this->getCurrentPayment();
  52.         $vehicleId $payment->getVehicleId();
  53.         if (null === $vehicleId) {
  54.             return null;
  55.         }
  56.         $vehicle $this->vehicleRepository->find($vehicleId);
  57.         if (!$vehicle) {
  58.             throw new NotFoundHttpException(sprintf('vehicle with id %d couldn\'t be found'$vehicleId));
  59.         }
  60.         return $vehicle;
  61.     }
  62.     public function getCurrentSale(): ?Sale
  63.     {
  64.         $payment $this->getCurrentPayment();
  65.         if (!$payment) {
  66.             return null;
  67.         }
  68.         $saleId $payment->getSaleId();
  69.         if (null === $saleId) {
  70.             return null;
  71.         }
  72.         $sale $this->saleRepository->find($saleId);
  73.         if (!$sale) {
  74.             throw new NotFoundHttpException(sprintf('sale with id %d couldn\'t be found'$saleId));
  75.         }
  76.         return $sale;
  77.     }
  78.     public function getCurrentUser()
  79.     {
  80.         $payment $this->getCurrentPayment();
  81.         if (!$payment) {
  82.             return null;
  83.         }
  84.         $userId $payment->getUserId();
  85.         if (null === $userId) {
  86.             return null;
  87.         }
  88.         $user $this->userRepository->find($userId);
  89.         if (!$user) {
  90.             throw new NotFoundHttpException(sprintf('sale with id %d couldn\'t be found'$userId));
  91.         }
  92.         return $user;
  93.     }
  94.     /**
  95.      * @throws AlreadyPaidException
  96.      */
  97.     public function checkAndStore(Payment $payment): void
  98.     {
  99.         if (!$payment->getBlockedAmount()) {
  100.             $payment->setBlockedAmount($this->defaultAmount);
  101.         }
  102.         if (!$payment->getFinalAmount()) {
  103.             $payment->setFinalAmount($payment->getBlockedAmount());
  104.         }
  105.         $this->checkIfItDoesNotExistsYet($payment);
  106.         $this->store($payment);
  107.     }
  108.     public function store(Payment $payment): void
  109.     {
  110.         $payment->validate();
  111.         $this->session->remove(self::SESSION_PAYMENT_KEY);
  112.         $this->session->set(self::SESSION_PAYMENT_KEY$payment);
  113.         $this->log('store payment in session');
  114.     }
  115.     public function findOrCreateTransaction(): Transaction
  116.     {
  117.         $payment $this->getCurrentPayment();
  118.         if (!$payment) {
  119.             throw new \Exception('Cannot get transaction because payment is not set');
  120.         }
  121.         $transaction null;
  122.         if ($transactionId $payment->getTransactionId()) {
  123.             $transaction $this->transactionRepository->find($transactionId);
  124.         }
  125.         if ($transaction) {
  126.             if ($transaction->getUser() !== $this->getCurrentUser()) {
  127.                 throw new \Exception('Wrong user for transaction');
  128.             }
  129.             if ($transaction->getSale() !== $this->getCurrentSale()) {
  130.                 throw new \Exception('Wrong sale for transaction');
  131.             }
  132.         } else {
  133.             $transaction = new Transaction();
  134.             $transaction->setUser($this->getCurrentUser());
  135.             $transaction->setSale($this->getCurrentSale());
  136.             $transaction->setAmount($payment->getBlockedAmount() * 100);
  137.             $transaction->setCountry($payment->getCountry());
  138.             $this->entityManager->persist($transaction);
  139.             $this->entityManager->flush();
  140.             $payment->setTransaction($transaction);
  141.             $this->store($payment);
  142.         }
  143.         return $transaction;
  144.     }
  145.     public function log(string $message, ?array $data = [], string $level 'info'): void
  146.     {
  147.         if (!method_exists($this->paymentLogger$level)) {
  148.             throw new \LogicException(sprintf('Unknown log level %s for message «%s»'$level$message));
  149.         }
  150.         if (!$data && $this->getCurrentPayment()) {
  151.             $data get_object_vars($this->getCurrentPayment());
  152.         }
  153.         $this->paymentLogger->$level($message.' '.print_r($datatrue));
  154.     }
  155.     /**
  156.      * @throws AlreadyPaidException
  157.      */
  158.     private function checkIfItDoesNotExistsYet(Payment $payment): void
  159.     {
  160.         $transaction $this->entityManager->getRepository(Transaction::class)
  161.             ->findValidTransactionByUserAndSale(
  162.                 $this->userRepository->find($payment->getUserId()),
  163.                 $this->saleRepository->find($payment->getSaleId())
  164.             );
  165.         if ($transaction) {
  166.             throw new AlreadyPaidException($this$transaction);
  167.         }
  168.     }
  169. }