<?php
namespace Boldr\Shop\MolliePaymentMethodBundle\EventSubscriber;
use Boldr\Shop\ShopBundle\Event\{ InvoiceStatusUpdatedEvent, PaymentStatusUpdatedEvent };
use Boldr\Shop\ShopBundle\Entity\Invoice;
use Boldr\Shop\MolliePaymentMethodBundle\Entity\MolliePayment;
use Boldr\Cms\MollieBundle\Event\MolliePaymentUpdatedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Doctrine\ORM\EntityManagerInterface;
use Mollie\Api\MollieApiClient;
class MollieEventSubscriber implements EventSubscriberInterface
{
private EventDispatcherInterface $eventDispatcher;
private EntityManagerInterface $em;
private MollieApiClient $mollieApiClient;
public function __construct(EventDispatcherInterface $eventDispatcher, EntityManagerInterface $em, MollieApiClient $mollieApiClient)
{
$this->eventDispatcher = $eventDispatcher;
$this->em = $em;
$this->mollieApiClient = $mollieApiClient;
}
public static function getSubscribedEvents(): array
{
return [
MolliePaymentUpdatedEvent::class => [
['onMolliePaymentUpdated', 10]
],
InvoiceStatusUpdatedEvent::class => [
['onInvoiceStateUpdated', 0]
],
PaymentStatusUpdatedEvent::class => [
['onPaymentStatusUpdated', 10]
]
];
}
public function onPaymentStatusUpdated(PaymentStatusUpdatedEvent $event)
{
$payment = $event->getPayment();
if ($payment instanceof MolliePayment)
{
if ($event->getNewStatus() === MolliePayment::STATUS_CANCELLED)
{
try
{
$this->mollieApiClient->payments->cancel($payment->getMolliePaymentId());
} catch (\Exception $ex) {
// ignore silently
}
}
}
}
public function onInvoiceStateUpdated(InvoiceStatusUpdatedEvent $event)
{
$invoice = $event->getInvoice();
$orders = $invoice->getOrders();
if (count($orders) > 1)
{
return;
}
if (isset($orders[0]))
{
$order = $orders[0];
if ($order->getNumber() !== null)
{
foreach ($invoice->getPayments() as $payment)
{
if ($payment instanceof MolliePayment)
{
try
{
$molliePayment = $this->mollieApiClient->payments->get($payment->getMolliePaymentId());
$molliePayment->description = 'Bestelling #'. $order->getNumber();
$molliePayment->update();
}
catch (\Exception $ex)
{
// ignore silently
}
}
}
}
}
if ($event->getNewStatus() === Invoice::STATUS_PAID)
{
// Cancel pending mollie payments
foreach ($invoice->getPayments() as $payment)
{
if ($payment instanceof MolliePayment)
{
if ($payment->getStatus() === MolliePayment::STATUS_PENDING)
{
try
{
$this->mollieApiClient->payments->cancel($payment->getMolliePaymentId());
}
catch (\Exception $ex)
{
// ignore silently
}
}
}
}
}
}
public function onMolliePaymentUpdated(MolliePaymentUpdatedEvent $event)
{
$molliePaymentRepository = $this->em->getRepository(MolliePayment::class);
$payment = $event->getPayment();
$molliePayment = $molliePaymentRepository->findOneBy(['molliePaymentId' => $payment->id]);
if ($molliePayment === null || $molliePayment->getStatus() === MolliePayment::STATUS_FAILED)
{
return;
}
if ($molliePayment !== null)
{
$oldStatus = $molliePayment->getStatus();
$newStatus = $payment->isPaid()
? MolliePayment::STATUS_PAID
: ($payment->isFailed() || $payment->isCanceled() || $payment->isExpired() || $payment->getAmountRefunded() > 0
? MolliePayment::STATUS_FAILED
: ($payment->hasChargebacks()
? MolliePayment::STATUS_CHARGEBACK
: MolliePayment::STATUS_PENDING
)
)
;
if ($oldStatus !== $newStatus)
{
$molliePayment->setStatus($newStatus);
$this->em->flush();
$event = new PaymentStatusUpdatedEvent($molliePayment, $oldStatus, $newStatus);
$this->eventDispatcher->dispatch($event);
}
}
}
}