<?php
namespace App\EventSubscriber\PaymentGateway;
use App\DTO\MMPZ\PaymentMethod\PaymentGatewayAuthorizationDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\PaypalCurrencyDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\PaypalProductDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanBillingCyclesDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanFrequencyDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanPaymentPreferenceDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PayPalPlanPricingSchemeDTO;
use App\Entity\Logs\EventLog;
use App\Entity\Package\Package;
use App\Enums\Constants;
use App\Enums\PackageType;
use App\Enums\TransactionPlatform;
use App\Event\LogEvent;
use App\Event\PaymentGateway\PaymentGatewayCreatedEvent;
use App\Event\PaymentGateway\PaymentGatewayEditedEvent;
use App\Repository\Package\PackageRepository;
use App\Service\AuthenticationService;
use App\Service\PaymentMethod\Paypal\PaypalService;
use App\Service\PaymentMethod\Stripe\StripeService;
use App\Service\ProfileService;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class PaymentGatewaySubscriber implements EventSubscriberInterface
{
/** @var PackageRepository */
private $packageRepository;
/** @var PaypalService */
private $paypalService;
/** @var StripeService */
private $stripeService;
/** @var ProfileService */
private $profileService;
/** @var EventDispatcherInterface */
private $eventDispatcher;
/**
* @var AuthenticationService
*/
private $authenticationService;
public function __construct(
AuthenticationService $authenticationService,
EventDispatcherInterface $eventDispatcher,
PackageRepository $packageRepository,
PaypalService $paypalService,
StripeService $stripeService,
ProfileService $profileService
)
{
$this->authenticationService = $authenticationService;
$this->eventDispatcher = $eventDispatcher;
$this->packageRepository = $packageRepository;
$this->stripeService = $stripeService;
$this->paypalService = $paypalService;
$this->profileService = $profileService;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return[
PaymentGatewayCreatedEvent::class => "onPaymentGatewayCreatedEvent",
PaymentGatewayEditedEvent::class => "onPaymentGatewayEditedEvent",
];
}
/**
* @param PaymentGatewayCreatedEvent $paymentGatewayCreatedEvent
* @return void
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Stripe\Exception\ApiErrorException
*/
public function onPaymentGatewayCreatedEvent(PaymentGatewayCreatedEvent $paymentGatewayCreatedEvent): void
{
$profile = $paymentGatewayCreatedEvent->getProfile();
$paymentGateway = $paymentGatewayCreatedEvent->getPaymentGateway();
$type = EventLog::TYPE_PAYMENT_GATEWAY_CREATED;
if($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER_ADMINISTRATOR){
$credentials = $this->profileService->getParentPaymentGateways($profile);
}else if($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER
|| $profile->getProfileType()->getName() === Constants::PROFILE_TYPE_SONGWRITER){
$publisherAdministrator = $this->profileService->findPublisherAdministratorForProfile($profile);
$credentials = $this->profileService->getParentPaymentGateways($publisherAdministrator);
}
/** @var Package $package */
foreach ($this->packageRepository->findBy(['profile' => $profile]) as $package){
if($paymentGateway->getPaymentType()->getName() === TransactionPlatform::PAYPAL &&
is_null($package->getPaypalProductId())
){
$type .= TransactionPlatform::PAYPAL;
/** @var PaymentGatewayAuthorizationDTO $paymentGatewayAuthorizationDTO */
$paymentGatewayAuthorizationDTO = $this->paypalService->authPaypal($credentials[TransactionPlatform::PAYPAL]);
$paypalProductDTO = (new PaypalProductDTO())
->setName($package->getName())
->setDescription($package->getDescription())
->setCategory("OTHER")
->setType("SERVICE");
$paypalProductDTO = $this->paypalService->createProduct(
$paypalProductDTO,
$paymentGatewayAuthorizationDTO
);
if($package->getType() === PackageType::SUBSCRIPTION){
$paypalPlanDTO = $this->paypalCreatePlanProcess(
$package,
$paypalProductDTO,
$paymentGatewayAuthorizationDTO
);
$package->setPaypalPlanId($paypalPlanDTO->getId());
$this->paypalService->activePlan($paypalPlanDTO, $paymentGatewayAuthorizationDTO);
}else{
$package->setPaypalPlanId("");
}
$package->setPaypalProductId($paypalProductDTO->getId());
}else if($paymentGateway->getPaymentType()->getName() === TransactionPlatform::STRIPE &&
is_null($package->getStripeProductId())
){
$type .= TransactionPlatform::STRIPE;
/** @var PaymentGatewayAuthorizationDTO $paymentGatewayAuthorizationDTO */
$paymentGatewayAuthorizationDTO = $this->stripeService->authStripe($credentials[TransactionPlatform::STRIPE]);
$stripeProduct = $this->stripeService->createProduct($package, $paymentGatewayAuthorizationDTO);
$stripePrice = $this->stripeService->createPrice($package, $stripeProduct, $paymentGatewayAuthorizationDTO);
if($package->getType() === PackageType::SUBSCRIPTION){
$package->setStripePlanId($stripePrice->id);
}else{
$package->setStripePlanId("");
}
$package->setStripeProductId($stripeProduct->id);
}
$this->packageRepository->flush($package);
}
$this->eventDispatcher->dispatch(new LogEvent($paymentGateway, $this->authenticationService->getUser(), $type));
}
public function onPaymentGatewayEditedEvent(PaymentGatewayEditedEvent $paymentGatewayEditedEvent)
{
$profile = $paymentGatewayEditedEvent->getProfile();
$paymentGateway = $paymentGatewayEditedEvent->getPaymentGateway();
$type = EventLog::TYPE_PAYMENT_GATEWAY_EDITED;
if($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER_ADMINISTRATOR){
$credentials = $this->profileService->getParentPaymentGateways($profile);
}else if($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER
|| $profile->getProfileType()->getName() === Constants::PROFILE_TYPE_SONGWRITER){
$publisherAdministrator = $this->profileService->findPublisherAdministratorForProfile($profile);
$credentials = $this->profileService->getParentPaymentGateways($publisherAdministrator);
}
/** @var Package $package */
foreach ($this->packageRepository->findBy(['profile' => $profile]) as $package){
if($paymentGateway->getPaymentType()->getName() === TransactionPlatform::PAYPAL){
$type .= TransactionPlatform::PAYPAL;
/** @var PaymentGatewayAuthorizationDTO $paymentGatewayAuthorizationDTO */
$paymentGatewayAuthorizationDTO = $this->paypalService->authPaypal($credentials[TransactionPlatform::PAYPAL]);
$paypalProductDTO = (new PaypalProductDTO())
->setName($package->getName())
->setDescription($package->getDescription())
->setCategory("OTHER")
->setType("SERVICE");
$paypalProductDTO = $this->paypalService->createProduct(
$paypalProductDTO,
$paymentGatewayAuthorizationDTO
);
if($package->getType() === PackageType::SUBSCRIPTION){
$paypalPlanDTO = $this->paypalCreatePlanProcess(
$package,
$paypalProductDTO,
$paymentGatewayAuthorizationDTO
);
$package->setPaypalPlanId($paypalPlanDTO->getId());
$this->paypalService->activePlan($paypalPlanDTO, $paymentGatewayAuthorizationDTO);
}else{
$package->setPaypalPlanId("");
}
$package->setPaypalProductId($paypalProductDTO->getId());
}else if($paymentGateway->getPaymentType()->getName() === TransactionPlatform::STRIPE){
$type .= TransactionPlatform::STRIPE;
/** @var PaymentGatewayAuthorizationDTO $paymentGatewayAuthorizationDTO */
$paymentGatewayAuthorizationDTO = $this->stripeService->authStripe($credentials[TransactionPlatform::STRIPE]);
$stripeProduct = $this->stripeService->createProduct($package, $paymentGatewayAuthorizationDTO);
$stripePrice = $this->stripeService->createPrice($package, $stripeProduct, $paymentGatewayAuthorizationDTO);
if($package->getType() === PackageType::SUBSCRIPTION){
$package->setStripePlanId($stripePrice->id);
}else{
$package->setStripePlanId("");
}
$package->setStripeProductId($stripeProduct->id);
}
$this->packageRepository->flush($package);
}
$this->eventDispatcher->dispatch(new LogEvent($paymentGateway, $this->authenticationService->getUser(), $type));
}
/**
* @param Package $package
* @param PaypalProductDTO $paypalProductDTO
* @param PaymentGatewayAuthorizationDTO $paymentGatewayAuthorizationDTO
* @return array|object
*/
private function paypalCreatePlanProcess(
Package $package,
PaypalProductDTO $paypalProductDTO,
PaymentGatewayAuthorizationDTO $paymentGatewayAuthorizationDTO
)
{
$totalAmount = (float)$package->getPrice() - ((float)$package->getPrice() * (float)$package->getDiscount());
$frequencyUnit = "YEAR";
$totalCycle = 0;
if($package->isMonthly()){
$frequencyUnit = "MONTH";
}
$frequency = (new PaypalPlanFrequencyDTO())
->setIntervalUnit($frequencyUnit);
$fixedPrice = (new PaypalCurrencyDTO())
->setValue($totalAmount)
->setCurrencyCode("GBP");
$pricingScheme = (new PayPalPlanPricingSchemeDTO())
->setFixedPrice($fixedPrice);
$billingCycles = (new PaypalPlanBillingCyclesDTO())
->setTenureType("REGULAR")
->setSequence(1)
->setFrequency($frequency)
->setTotalCycles($totalCycle)
->setPricingScheme($pricingScheme);
$setupFee = (new PaypalCurrencyDTO())
->setValue(0)//TODO: this would change
->setCurrencyCode("GBP");
$paymentPreferences = (new PaypalPlanPaymentPreferenceDTO())
->setAutoBillOutstanding(true)
->setSetupFeeFailureAction("CANCEL")
->setPaymentFailureThreshold(1)
->setSetupFee($setupFee);
$paypalPlanDTO = (new PaypalPlanDTO())
->setProductId($paypalProductDTO->getId())
->setName($package->getName())
->setBillingCycles([$billingCycles])
->setPaymentPreferences($paymentPreferences);
return $this->paypalService->createPlan(
$paypalPlanDTO,
$paymentGatewayAuthorizationDTO
);
}
}