<?php
namespace App\EventSubscribers\Main;
use App\Entity\Main\BillingRefundV2Callback;
use App\Entity\Main\CallbackLog;
use App\Events\Main\Callbacks\ChargebackCallbackReceivedEvent;
use App\Events\Main\Callbacks\PaypalCallbackReceivedEvent;
use App\Events\Main\Callbacks\RebillManagerCallbackReceivedEvent;
use App\Events\Main\Callbacks\RefundCallbackReceivedEvent;
use App\Events\Main\Callbacks\ThreeDSCallbackReceivedEvent;
use App\Events\Main\Callbacks\TransactionCallbackReceivedEvent;
use App\Exceptions\Main\Callbacks\IgnoredByThisCallbackException;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* Class CallbacksSubscriber
* @package App\EventSubscribers\Main
*/
class CallbacksSubscriber implements EventSubscriberInterface
{
const
CALLBACK_CHARGEBACK = 'callback.chargeback',
CALLBACK_TRANSACTION = 'callback.transaction',
CALLBACK_REBILLMANAGER = 'callback.rebillmanager',
CALLBACK_3DS = 'callback.threeds',
CALLBACK_REFUND = 'callback.refund',
CALLBACK_PAYPAL = 'callback.paypal'
;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var ValidatorInterface
*/
private $validator;
private $errors;
/**
* CoachingUserSubscriber constructor.
* @param EntityManagerInterface $entityManager
*/
public function __construct(EntityManagerInterface $entityManager, ValidatorInterface $validator)
{
$this->entityManager = $entityManager;
$this->validator = $validator;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return array(
self::CALLBACK_CHARGEBACK => "callbackChargeback",
self::CALLBACK_TRANSACTION => "callbackTransaction",
self::CALLBACK_REBILLMANAGER => "callbackRebillManager",
self::CALLBACK_3DS => "callbackThreeDS",
self::CALLBACK_REFUND => "callbackRefund",
self::CALLBACK_PAYPAL => "callbackPaypal"
);
}
/**
* @param ChargebackCallbackReceivedEvent $event
* @throws \Exception
*/
public function callbackChargeback(ChargebackCallbackReceivedEvent $event)
{
// We ignore some actions but we still log them.
$ignoredActions = ["", "transaction"];
$isValid = $this->validate($event->getCallback());
$this->createLog($event->getRequest(), CallbackLog::TYPE_CHARGEBACK, $isValid, $event->getCallback());
if (in_array($event->getCallback()->getAction(), $ignoredActions)) {
throw new IgnoredByThisCallbackException();
}
if (!$isValid) {
$this->throwError($event->getRequest());
}
}
/**
* @param TransactionCallbackReceivedEvent $event
* @throws \Exception
*/
public function callbackTransaction(TransactionCallbackReceivedEvent $event)
{
// TODO update that if we have a transaction callback.
$this->createLog($event->getRequest(), CallbackLog::TYPE_TRANSACTION, true);
}
/**
* @param RebillManagerCallbackReceivedEvent $event
* @throws \Exception
*/
public function callbackRebillManager(RebillManagerCallbackReceivedEvent $event)
{
$isValid = $this->validate($event->getCallback());
$this->createLog($event->getRequest(), CallbackLog::TYPE_REBILL_MANAGER, $isValid, $event->getCallback());
// return a 500 error like it was.
if (!$isValid) {
$this->throwError($event->getRequest());
}
}
/**
* @param ThreeDSCallbackReceivedEvent $event
* @throws \Exception
*/
public function callbackThreeDS(ThreeDSCallbackReceivedEvent $event)
{
$this->createLog($event->getRequest(), CallbackLog::TYPE_3DS, true);
}
/**
* @param PaypalCallbackReceivedEvent $event
* @throws \Exception
*/
public function callbackPaypal(PaypalCallbackReceivedEvent $event)
{
$this->createLog($event->getRequest(), CallbackLog::TYPE_PAYPAL, true, null, $event->getPutData());
}
/**
* @param RefundCallbackReceivedEvent $event
* @throws \Exception
*/
public function callbackRefund(RefundCallbackReceivedEvent $event)
{
$callBack = $event->getCallBack();
$request = $event->getRequest();
$isValid = $this->validate($callBack);
$this->createLog($request, CallbackLog::TYPE_REFUND, $isValid, $callBack);
// return a 500 error like it was.
if (!$isValid) {
$this->throwError($request);
}
}
/**
* @param Request $request
* @param $logType
* @param $isValid
* @param null $object
* @throws \Exception
*/
protected function createLog(Request $request, $logType, $isValid, $object = null, $putData = null)
{
$log = new CallbackLog();
$log->setContent("POST data : " . json_encode($request->request->all()) . " \n GET data : " . json_encode($request->query->all()));
if (null != $putData) {
$log->setContent($log->getContent() . " Put data : " . print_r($putData, true));
}
$log->setDate(new \DateTime());
$log->setOriginIp($request->getClientIp());
$log->setType($logType);
$log->setPassedValidation($isValid);
if (null != $object) {
$log->setObjectData(print_r($object, true));
}
$this->entityManager->persist($log);
$this->entityManager->flush();
}
/**
* @param $objectToValidate
* @return bool
*/
protected function validate($objectToValidate)
{
$this->errors = $this->validator->validate($objectToValidate);
if (count($this->errors)) {
return false;
}
return true;
}
/**
* @param Request $request
*/
protected function throwError(Request $request)
{
throw new HttpException(
Response::HTTP_INTERNAL_SERVER_ERROR,
'Errors found in: ' . (string) $this->errors . ' - Request : ' . print_r($request->request->all(), true)
);
}
}