Skip to content

Commit

Permalink
BB-17479: PayPal Express Integration 3.1 LTS
Browse files Browse the repository at this point in the history
Co-Authored-By: Dmitriev Alexandr <admitriev@oroinc.com>
Co-Authored-By: Ignat Shcheglovskyi <ignat@oroinc.com>
Co-Authored-By: Eugene Chetverikov <ychetverikov@oroinc.com>
Co-Authored-By: vetal-e <vyeromenko@oroinc.com>
Co-Authored-By: Vitaliy Berdylo <vberdylo@oroinc.com>
  • Loading branch information
6 people committed Oct 25, 2019
0 parents commit 587c1c9
Show file tree
Hide file tree
Showing 138 changed files with 12,186 additions and 0 deletions.
25 changes: 25 additions & 0 deletions DependencyInjection/OroPayPalExpressExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Oro\Bundle\PayPalExpressBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

/**
* Loads DI configuration files of the bundle.
*/
class OroPayPalExpressExtension extends Extension
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$loader->load('integration.yml');
$loader->load('method.yml');
}
}
215 changes: 215 additions & 0 deletions Entity/PayPalExpressSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
<?php

namespace Oro\Bundle\PayPalExpressBundle\Entity;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Oro\Bundle\IntegrationBundle\Entity\Transport;
use Oro\Bundle\LocaleBundle\Entity\LocalizedFallbackValue;
use Symfony\Component\HttpFoundation\ParameterBag;

/**
* Represents entity for PayPal Express payment method integration settings.
*
* @ORM\Entity(repositoryClass="Oro\Bundle\PayPalExpressBundle\Entity\Repository\PayPalExpressSettingsRepository")
*/
class PayPalExpressSettings extends Transport
{
const CLIENT_ID_SETTING_KEY = 'client_id';
const CLIENT_SECRET_SETTING_KEY = 'client_secret';
const SANDBOX_MOD_SETTING_KEY = 'test_mod';
const LABELS_SETTING_KEY = 'labels';
const SHORT_LABELS_SETTING_KEY = 'short_labels';
const PAYMENT_ACTION_KEY = 'payment_action';

/**
* @var ParameterBag
*/
protected $settings;

/**
* @var string
*
* @ORM\Column(name="pp_express_client_id", type="string", length=255, nullable=false)
*/
protected $clientId;

/**
* @var string
*
* @ORM\Column(name="pp_express_client_secret", type="string", length=255, nullable=false)
*/
protected $clientSecret;

/**
* @var boolean
*
* @ORM\Column(name="pp_express_sandbox_mode", type="boolean", options={"default"=false})
*/
protected $sandboxMode = false;


/**
* @var Collection|LocalizedFallbackValue[]
*
* @ORM\ManyToMany(
* targetEntity="Oro\Bundle\LocaleBundle\Entity\LocalizedFallbackValue",
* cascade={"ALL"},
* orphanRemoval=true
* )
* @ORM\JoinTable(
* name="oro_pp_express_label",
* joinColumns={
* @ORM\JoinColumn(name="transport_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="localized_value_id", referencedColumnName="id", onDelete="CASCADE", unique=true)
* }
* )
*/
protected $labels;

/**
* @var Collection|LocalizedFallbackValue[]
*
* @ORM\ManyToMany(
* targetEntity="Oro\Bundle\LocaleBundle\Entity\LocalizedFallbackValue",
* cascade={"ALL"},
* orphanRemoval=true
* )
* @ORM\JoinTable(
* name="oro_pp_express_short_label",
* joinColumns={
* @ORM\JoinColumn(name="transport_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="localized_value_id", referencedColumnName="id", onDelete="CASCADE", unique=true)
* }
* )
*/
protected $shortLabels;

/**
* @var string
*
* @ORM\Column(name="pp_express_payment_action", type="string", length=255, nullable=false)
*/
protected $paymentAction;

/**
* @return string
*/
public function getClientId()
{
return $this->clientId;
}

/**
* @param string $clientId
*/
public function setClientId($clientId)
{
$this->clientId = $clientId;
}

/**
* @return string
*/
public function getClientSecret()
{
return $this->clientSecret;
}

/**
* @param string $clientSecret
*/
public function setClientSecret($clientSecret)
{
$this->clientSecret = $clientSecret;
}

/**
* @return bool
*/
public function isSandboxMode()
{
return $this->sandboxMode;
}

/**
* @param bool $sandboxMode
*/
public function setSandboxMode($sandboxMode)
{
$this->sandboxMode = $sandboxMode;
}

/**
* @return Collection|LocalizedFallbackValue[]
*/
public function getLabels()
{
return $this->labels;
}

/**
* @param Collection|LocalizedFallbackValue[] $labels
*/
public function setLabels($labels)
{
$this->labels = $labels;
}

/**
* @return Collection|LocalizedFallbackValue[]
*/
public function getShortLabels()
{
return $this->shortLabels;
}

/**
* @param Collection|LocalizedFallbackValue[] $shortLabels
*/
public function setShortLabels($shortLabels)
{
$this->shortLabels = $shortLabels;
}

/**
* @return string
*/
public function getPaymentAction()
{
return $this->paymentAction;
}

/**
* @param string $paymentAction
*/
public function setPaymentAction($paymentAction)
{
$this->paymentAction = $paymentAction;
}

/**
* @return ParameterBag
*/
public function getSettingsBag()
{
if (null === $this->settings) {
$this->settings = new ParameterBag(
[
self::CLIENT_ID_SETTING_KEY => $this->getClientId(),
self::CLIENT_SECRET_SETTING_KEY => $this->getClientSecret(),
self::SANDBOX_MOD_SETTING_KEY => $this->isSandboxMode(),
self::LABELS_SETTING_KEY => $this->getLabels(),
self::SHORT_LABELS_SETTING_KEY => $this->getShortLabels(),
self::PAYMENT_ACTION_KEY => $this->getPaymentAction(),
]
);
}

return $this->settings;
}
}
28 changes: 28 additions & 0 deletions Entity/Repository/PayPalExpressSettingsRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Oro\Bundle\PayPalExpressBundle\Entity\Repository;

use Doctrine\ORM\EntityRepository;
use Oro\Bundle\PayPalExpressBundle\Entity\PayPalExpressSettings;
use Oro\Bundle\PayPalExpressBundle\Integration\PayPalExpressChannelType;

/**
* Extends base repository and adds additional methods to get {@see PayPalExpressSettings} entity.
*/
class PayPalExpressSettingsRepository extends EntityRepository
{
/**
* @return PayPalExpressSettings[]
*/
public function getEnabledIntegrationsSettings()
{
return $this->createQueryBuilder('settings')
->innerJoin('settings.channel', 'channel')
->andWhere('channel.enabled = true')
->andWhere('channel.type = :type')
->orderBy('settings.id')
->setParameter('type', PayPalExpressChannelType::TYPE)
->getQuery()
->getResult();
}
}
96 changes: 96 additions & 0 deletions EventListener/PayPalExpressRedirectListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Oro\Bundle\PayPalExpressBundle\EventListener;

use Oro\Bundle\PaymentBundle\Event\AbstractCallbackEvent;
use Oro\Bundle\PaymentBundle\Method\Provider\PaymentMethodProviderInterface;
use Oro\Bundle\PayPalExpressBundle\Method\PaymentAction\CompleteVirtualAction;
use Oro\Bundle\PayPalExpressBundle\Method\PaymentTransaction\PaymentTransactionResponseData;
use Psr\Log\LoggerAwareTrait;

/**
* Handles a payment callback event triggered when PayPal redirects a user after an attempt to make a payment.
* If payment was created successfully in PayPal, then a {@see CompleteVirtualAction} action will be executed.
* Otherwise, a payment transaction marked as failed.
*/
class PayPalExpressRedirectListener
{
use LoggerAwareTrait;

/**
* @var PaymentMethodProviderInterface
*/
protected $paymentMethodProvider;

/**
* @param PaymentMethodProviderInterface $paymentMethodProvider
*/
public function __construct(PaymentMethodProviderInterface $paymentMethodProvider)
{
$this->paymentMethodProvider = $paymentMethodProvider;
}

/**
* @param AbstractCallbackEvent $event
*/
public function onError(AbstractCallbackEvent $event)
{
$paymentTransaction = $event->getPaymentTransaction();

if (!$paymentTransaction) {
return;
}

if (false === $this->paymentMethodProvider->hasPaymentMethod($paymentTransaction->getPaymentMethod())) {
return;
}

$paymentTransaction
->setSuccessful(false)
->setActive(false);
}

/**
* @param AbstractCallbackEvent $event
*/
public function onReturn(AbstractCallbackEvent $event)
{
$paymentTransaction = $event->getPaymentTransaction();

if (!$paymentTransaction) {
return;
}

$paymentMethodId = $paymentTransaction->getPaymentMethod();

if (false === $this->paymentMethodProvider->hasPaymentMethod($paymentMethodId)) {
return;
}

$eventData = $event->getData();

if (!$paymentTransaction || !isset($eventData['paymentId'], $eventData['PayerID'], $eventData['token']) ||
$eventData['paymentId'] !== $paymentTransaction->getReference()
) {
return;
}

$response = $paymentTransaction->getResponse();
$response[PaymentTransactionResponseData::PAYMENT_ID_FIELD_KEY] = $eventData['paymentId'];
$response[PaymentTransactionResponseData::PAYER_ID_FIELD_KEY] = $eventData['PayerID'];

$paymentTransaction->setResponse($response);

try {
$paymentMethod = $this->paymentMethodProvider->getPaymentMethod($paymentMethodId);
$paymentMethod->execute(CompleteVirtualAction::NAME, $paymentTransaction);

$event->markSuccessful();
} catch (\InvalidArgumentException $e) {
if ($this->logger) {
// do not expose sensitive data in context
$this->logger->error($e->getMessage(), []);
}
}
}
}
17 changes: 17 additions & 0 deletions Exception/ErrorContextAwareExceptionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Oro\Bundle\PayPalExpressBundle\Exception;

/**
* Represents an interface of exception with an error context. Data in the context has no predefined structure.
* This data is intended to be exposed as is when exception is logged.
*/
interface ErrorContextAwareExceptionInterface extends ExceptionInterface
{
/**
* Returns error context used for logging.
*
* @return array
*/
public function getErrorContext();
}
Loading

0 comments on commit 587c1c9

Please sign in to comment.