src/EventSubscriber/TicketPaymentEventSubscriber.php line 44

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\DependencyInjection\Framework\EntityManagerDI;
  4. use App\DependencyInjection\Framework\EnvironmentDI;
  5. use App\DependencyInjection\Framework\EventDispatcherDI;
  6. use App\DependencyInjection\Framework\LoggerDI;
  7. use App\DependencyInjection\Framework\MessageBusDI;
  8. use App\DependencyInjection\Repository\Game\GameTicketRepositoryDI;
  9. use App\DependencyInjection\Service\Data\Game\GameTicketServiceDI;
  10. use App\DependencyInjection\Service\Data\Logs\LogsServiceDI;
  11. use App\Entity\Loto\GameTicket;
  12. use App\Enum\Game\TicketStatus;
  13. use App\Enum\Payment\PaymentStatus;
  14. use App\Enum\Payment\TransactionType;
  15. use App\Event\Game\TicketEvent;
  16. use App\Event\PaymentEvent;
  17. use App\Message\Loto\LotoTicketFileCreateMessage;
  18. use App\Message\Notification\TicketEmailMessage;
  19. use App\Message\Payment\RefundTicketPaymentMessage;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. use Symfony\Component\Messenger\Stamp\DelayStamp;
  22. class TicketPaymentEventSubscriber implements EventSubscriberInterface
  23. {
  24.     use GameTicketRepositoryDI;
  25.     use MessageBusDI;
  26.     use LoggerDI;
  27.     use LogsServiceDI;
  28.     use EntityManagerDI;
  29.     use GameTicketServiceDI;
  30.     use MessageBusDI;
  31.     use EnvironmentDI;
  32.     use EventDispatcherDI;
  33.     public static function getSubscribedEvents(): array
  34.     {
  35.         return [
  36.             PaymentEvent::NAME => 'onPaymentUpdated',
  37.         ];
  38.     }
  39.     public function onPaymentUpdated(PaymentEvent $event): void
  40.     {
  41.         $this->logger->info('Payment updated', [
  42.             'event' => $event,
  43.         ]);
  44.         if (!$ticket $this->gameTicketRepository->find($event->objectId)) {
  45.             return;
  46.         }
  47.         $this->logsService->addRequestLogToObject($ticket);
  48.         if ($event->transaction->getTicket() !== $ticket) {
  49.             $this->logger->error('Different transactions', [
  50.                 'ticket'            => $ticket->getId(),
  51.                 'ticketTransaction' => $ticket->getPurchaseTransaction(),
  52.                 'eventTransaction'  => $event->transaction,
  53.             ]);
  54.             $this->logsService->addLog(__METHOD____LINE__'Different transactions', [
  55.                 'ticket'            => $ticket->getId(),
  56.                 'ticketTransaction' => $ticket->getPurchaseTransaction(),
  57.                 'eventTransaction'  => $event->transaction,
  58.             ]);
  59.             return;
  60.         }
  61.         if (in_array($ticket->getPaymentStatus(), [PaymentStatus::SuccessPaymentStatus::Refunded])) {
  62.             $this->logger->info('Ticket already paid', [
  63.                 'ticket' => $ticket->getId(),
  64.             ]);
  65.             $this->logsService->addLog(__METHOD____LINE__'Ticket already paid', [
  66.                 'ticket' => $ticket->getId(),
  67.             ]);
  68.             return;
  69.         }
  70.         if ($event->status === PaymentStatus::Success) {
  71.             $ticketPaymentStatus = match ($event->transaction->getType()) {
  72.                 TransactionType::Purchase => PaymentStatus::Success,
  73.                 TransactionType::Refund   => PaymentStatus::Refunded
  74.             };
  75.         } else {
  76.             $ticketPaymentStatus $event->status;
  77.         }
  78.         $ticket->setPaymentStatus($ticketPaymentStatus);
  79.         match ($ticketPaymentStatus) {
  80.             PaymentStatus::Success => $this->onTicketPaymentSuccess($ticket),
  81.             PaymentStatus::Canceled,
  82.             PaymentStatus::Failed  => $this->onTicketPaymentFailed($ticket),
  83.             default                => null,
  84.         };
  85.         $this->entityManager->flush();
  86.         $this->logsService->addLog(__METHOD____LINE__'Ticket payment status updated');
  87.     }
  88.     private function onTicketPaymentSuccess(GameTicket $ticket): void
  89.     {
  90.         $now \DateTimeService::now();
  91.         $ticket->setPlayDate($now);
  92.         $salesEndDate $ticket->getGamePeriod()->getSalesEndDate();
  93.         $exportTime   $ticket->getGamePeriod()->getExportTime();
  94.         $confirmationCutoff = (clone $salesEndDate)->setTime(
  95.             (int) $exportTime->format('H'),
  96.             (int) $exportTime->format('i'),
  97.             (int) $exportTime->format('s'),
  98.         );
  99.         // cancel the ticket if payment is confirmed after the (sales) period is closed
  100.         if (!$ticket->getGamePeriod()->isActive() || $now $confirmationCutoff) {
  101.             $this->logger->warning('Ticket ID {id} is for an inactive game period ({game_period}). Marking as canceled.', [
  102.                 'id' => $ticket->getId(),
  103.                 'game_period' => $ticket->getGamePeriod()->getPeriodCode(),
  104.             ]);
  105.             $ticket->setStatus(TicketStatus::Canceled);
  106.             $this->entityManager->flush();
  107.             $this->eventDispatcher->dispatch(new TicketEvent($ticket), TicketEvent::CANCELED);
  108.         } else {
  109.             $this->logger->info('Ticket ID {id} is in an active game period ({game_period}). Continuing processing.', [
  110.                 'id' => $ticket->getId(),
  111.                 'game_period' => $ticket->getGamePeriod()->getPeriodCode(),
  112.             ]);
  113.             $ticket->getTicketDefinition()?->getInfo()?->updateInfo();
  114.             $this->entityManager->flush();
  115.             if (!$ticket->getFile()) {
  116.                 $this->logger->info('Dispatching file generation message for ticket ID {id}', [
  117.                     'id' => $ticket->getId(),
  118.                 ]);
  119.                 $this->messageBus->dispatch(new LotoTicketFileCreateMessage($ticket));
  120.             }
  121.             $this->logger->info('Creating ticket purchase entry for ticket ID {id}', [
  122.                 'id' => $ticket->getId(),
  123.             ]);
  124.             $this->gameTicketService->createTicketPurchaseEntry($ticket);
  125.         }
  126.     }
  127.     private function onTicketPaymentFailed(GameTicket $ticket)
  128.     {
  129.         // there is no flow defined for failed payments
  130.     }
  131. }