Skip to content

Commit

Permalink
Merge pull request #219 from PAYONE-GmbH/feature/PAYONE-143-Przelewy24
Browse files Browse the repository at this point in the history
[PAYONE-143] Add payment method Przelewy24
  • Loading branch information
janteuber authored Nov 15, 2022
2 parents 151d2c4 + 4d75c81 commit 846d589
Show file tree
Hide file tree
Showing 26 changed files with 1,135 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/Configuration/ConfigurationPrefixes.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface ConfigurationPrefixes
public const CONFIGURATION_PREFIX_KLARNA_INVOICE = 'klarnaInvoice';
public const CONFIGURATION_PREFIX_KLARNA_DIRECT_DEBIT = 'klarnaDirectDebit';
public const CONFIGURATION_PREFIX_KLARNA_INSTALLMENT = 'klarnaInstallment';
public const CONFIGURATION_PREFIX_PRZELEWY24 = 'przelewy24';

public const CONFIGURATION_PREFIXES = [
Handler\PayoneApplePayPaymentHandler::class => self::CONFIGURATION_PREFIX_APPLE_PAY,
Expand All @@ -56,5 +57,6 @@ interface ConfigurationPrefixes
Handler\PayoneKlarnaInvoicePaymentHandler::class => self::CONFIGURATION_PREFIX_KLARNA_INVOICE,
Handler\PayoneKlarnaDirectDebitPaymentHandler::class => self::CONFIGURATION_PREFIX_KLARNA_DIRECT_DEBIT,
Handler\PayoneKlarnaInstallmentPaymentHandler::class => self::CONFIGURATION_PREFIX_KLARNA_INSTALLMENT,
Handler\PayonePrzelewy24PaymentHandler::class => self::CONFIGURATION_PREFIX_PRZELEWY24,
];
}
16 changes: 16 additions & 0 deletions src/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,22 @@ private function getPaymentParameters(string $paymentClass): array
'no[1]' => 1,
];

case Handler\PayonePrzelewy24PaymentHandler::class:
return [
'request' => 'preauthorization',
'clearingtype' => 'sb',
'onlinebanktransfertype' => 'P24',
'bankcountry' => 'PL',
'amount' => 100,
'currency' => 'EUR',
'reference' => sprintf('%s%d', self::REFERENCE_PREFIX_TEST, random_int(1000000000000, 9999999999999)),
'lastname' => 'Test',
'country' => 'PL',
'successurl' => 'https://www.payone.com',
'errorurl' => 'https://www.payone.com',
'backurl' => 'https://www.payone.com',
];

default:
$this->logger->error(sprintf('There is no test data defined for payment class %s', $paymentClass));

Expand Down
13 changes: 13 additions & 0 deletions src/DependencyInjection/handler/payment_handler.xml
Original file line number Diff line number Diff line change
Expand Up @@ -294,5 +294,18 @@
<tag name="shopware.payment.method.async"/>
</service>

<service id="PayonePayment\PaymentHandler\PayonePrzelewy24PaymentHandler">
<argument type="service" id="PayonePayment\Components\ConfigReader\ConfigReader" />
<argument type="service" id="order_line_item.repository" />
<argument type="service" id="PayonePayment\Payone\Client\PayoneClient" />
<argument type="service" id="translator" />
<argument type="service" id="PayonePayment\Components\DataHandler\Transaction\TransactionDataHandler" />
<argument type="service" id="PayonePayment\Components\PaymentStateHandler\PaymentStateHandler" />
<argument type="service" id="request_stack" />
<argument type="service" id="PayonePayment\Payone\RequestParameter\RequestParameterFactory" />

<tag name="shopware.payment.method.async" />
</service>

</services>
</container>
4 changes: 4 additions & 0 deletions src/DependencyInjection/listeners.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,9 @@
<service id="PayonePayment\EventListener\CheckoutConfirmKlarnaRestrictPaymentEventListener">
<tag name="kernel.event_subscriber"/>
</service>

<service id="PayonePayment\EventListener\CheckoutConfirmPrzelewy24EventListener">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
13 changes: 13 additions & 0 deletions src/DependencyInjection/requestParameter/builder.xml
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,19 @@
<tag name="payone_request_builder"/>
</service>

<!-- Przelewy24 -->
<service id="PayonePayment\Payone\RequestParameter\Builder\Przelewy24\AuthorizeRequestParameterBuilder"
parent="PayonePayment\Payone\RequestParameter\Builder\AbstractRequestParameterBuilder">

<tag name="payone_request_builder"/>
</service>

<service id="PayonePayment\Payone\RequestParameter\Builder\Przelewy24\PreAuthorizeRequestParameterBuilder"
parent="PayonePayment\Payone\RequestParameter\Builder\AbstractRequestParameterBuilder">

<tag name="payone_request_builder"/>
</service>

<!-- Capture -->
<service id="PayonePayment\Payone\RequestParameter\Builder\Capture\CaptureRequestParameterBuilder"
parent="PayonePayment\Payone\RequestParameter\Builder\AbstractRequestParameterBuilder">
Expand Down
77 changes: 77 additions & 0 deletions src/EventListener/CheckoutConfirmPrzelewy24EventListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace PayonePayment\EventListener;

use PayonePayment\PaymentHandler\PayonePrzelewy24PaymentHandler;
use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderAddress\OrderAddressEntity;
use Shopware\Core\Checkout\Payment\PaymentMethodCollection;
use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Shopware\Storefront\Page\Account\PaymentMethod\AccountPaymentMethodPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\PageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CheckoutConfirmPrzelewy24EventListener implements EventSubscriberInterface
{
private const ALLOWED_COUNTRIES = ['PL'];
private const ALLOWED_CURRENCIES = ['PLN'];

public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => 'hidePaymentMethod',
AccountPaymentMethodPageLoadedEvent::class => 'hidePaymentMethod',
AccountEditOrderPageLoadedEvent::class => 'hidePaymentMethod',
];
}

/**
* @param AccountEditOrderPageLoadedEvent|AccountPaymentMethodPageLoadedEvent|CheckoutConfirmPageLoadedEvent $event
*/
public function hidePaymentMethod(PageLoadedEvent $event): void
{
$context = $event->getSalesChannelContext();
$customer = $context->getCustomer();
$page = $event->getPage();

$billingAddress = $customer ? $customer->getActiveBillingAddress() : null;

if ($this->isCurrencyAllowed($context->getCurrency()->getIsoCode())
&& (!$billingAddress || $this->isAddressAllowed($billingAddress))
) {
return;
}

$paymentMethods = $this->removePaymentMethods($page->getPaymentMethods(), [PayonePrzelewy24PaymentHandler::class]);

$event->getPage()->setPaymentMethods($paymentMethods);
}

/**
* @param CustomerAddressEntity|OrderAddressEntity $address
*/
private function isAddressAllowed($address): bool
{
$country = $address->getCountry();

return $country && \in_array($country->getIso(), self::ALLOWED_COUNTRIES, true);
}

private function isCurrencyAllowed(string $currencyCode): bool
{
return \in_array($currencyCode, self::ALLOWED_CURRENCIES, true);
}

private function removePaymentMethods(PaymentMethodCollection $paymentMethods, array $paymentHandler): PaymentMethodCollection
{
return $paymentMethods->filter(
static function (PaymentMethodEntity $paymentMethod) use ($paymentHandler) {
return !\in_array($paymentMethod->getHandlerIdentifier(), $paymentHandler, true);
}
);
}
}
3 changes: 3 additions & 0 deletions src/Installer/PaymentMethodInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use PayonePayment\PaymentMethod\PayonePaypal;
use PayonePayment\PaymentMethod\PayonePaypalExpress;
use PayonePayment\PaymentMethod\PayonePrepayment;
use PayonePayment\PaymentMethod\PayonePrzelewy24;
use PayonePayment\PaymentMethod\PayoneRatepayDebit;
use PayonePayment\PaymentMethod\PayoneRatepayInstallment;
use PayonePayment\PaymentMethod\PayoneRatepayInvoicing;
Expand Down Expand Up @@ -68,6 +69,7 @@ class PaymentMethodInstaller implements InstallerInterface
PayoneKlarnaInvoice::class => 'c4cd059611cc4d049187d8d955ec1f91',
PayoneKlarnaDirectDebit::class => '31af2cbeda5242bfbfe4531e203f8a42',
PayoneKlarnaInstallment::class => 'a18ffddd4baf4948b8c9f9d3d8abd2d4',
PayonePrzelewy24::class => '6068e01cef8b4c9698956c6cca648d50',
];

public const HANDLER_IDENTIFIER_ROOT_NAMESPACE = 'PayonePayment';
Expand Down Expand Up @@ -96,6 +98,7 @@ class PaymentMethodInstaller implements InstallerInterface
PayoneKlarnaInvoice::class,
PayoneKlarnaDirectDebit::class,
PayoneKlarnaInstallment::class,
PayonePrzelewy24::class,
];

public const AFTER_ORDER_PAYMENT_METHODS = [
Expand Down
146 changes: 146 additions & 0 deletions src/PaymentHandler/PayonePrzelewy24PaymentHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php

declare(strict_types=1);

namespace PayonePayment\PaymentHandler;

use PayonePayment\Components\ConfigReader\ConfigReaderInterface;
use PayonePayment\Components\DataHandler\Transaction\TransactionDataHandlerInterface;
use PayonePayment\Components\PaymentStateHandler\PaymentStateHandlerInterface;
use PayonePayment\Payone\Client\Exception\PayoneRequestException;
use PayonePayment\Payone\Client\PayoneClientInterface;
use PayonePayment\Payone\RequestParameter\RequestParameterFactory;
use PayonePayment\Payone\RequestParameter\Struct\PaymentTransactionStruct;
use PayonePayment\Struct\PaymentTransaction;
use Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct;
use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\AsynchronousPaymentHandlerInterface;
use Shopware\Core\Checkout\Payment\Exception\AsyncPaymentProcessException;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\Translation\TranslatorInterface;

class PayonePrzelewy24PaymentHandler extends AbstractPayonePaymentHandler implements AsynchronousPaymentHandlerInterface
{
private PayoneClientInterface $client;

private TranslatorInterface $translator;

private TransactionDataHandlerInterface $dataHandler;

private PaymentStateHandlerInterface $stateHandler;

private RequestParameterFactory $requestParameterFactory;

public function __construct(
ConfigReaderInterface $configReader,
EntityRepositoryInterface $lineItemRepository,
PayoneClientInterface $client,
TranslatorInterface $translator,
TransactionDataHandlerInterface $dataHandler,
PaymentStateHandlerInterface $stateHandler,
RequestStack $requestStack,
RequestParameterFactory $requestParameterFactory
) {
parent::__construct($configReader, $lineItemRepository, $requestStack);

$this->client = $client;
$this->translator = $translator;
$this->dataHandler = $dataHandler;
$this->stateHandler = $stateHandler;
$this->requestParameterFactory = $requestParameterFactory;
}

/**
* {@inheritdoc}
*/
public function pay(AsyncPaymentTransactionStruct $transaction, RequestDataBag $dataBag, SalesChannelContext $salesChannelContext): RedirectResponse
{
$requestData = $this->fetchRequestData();

// Get configured authorization method
$authorizationMethod = $this->getAuthorizationMethod(
$transaction->getOrder()->getSalesChannelId(),
'przelewy24AuthorizationMethod',
'authorization'
);

$paymentTransaction = PaymentTransaction::fromAsyncPaymentTransactionStruct($transaction, $transaction->getOrder());

$request = $this->requestParameterFactory->getRequestParameter(
new PaymentTransactionStruct(
$paymentTransaction,
$requestData,
$salesChannelContext,
__CLASS__,
$authorizationMethod
)
);

try {
$response = $this->client->request($request);
} catch (PayoneRequestException $exception) {
throw new AsyncPaymentProcessException(
$transaction->getOrderTransaction()->getId(),
$exception->getResponse()['error']['CustomerMessage']
);
} catch (\Throwable $exception) {
throw new AsyncPaymentProcessException(
$transaction->getOrderTransaction()->getId(),
$this->translator->trans('PayonePayment.errorMessages.genericError')
);
}

if (empty($response['status']) && $response['status'] !== 'REDIRECT') {
throw new AsyncPaymentProcessException(
$transaction->getOrderTransaction()->getId(),
$this->translator->trans('PayonePayment.errorMessages.genericError')
);
}

$data = $this->preparePayoneOrderTransactionData($request, $response, [
'transactionState' => $response['status'],
'allowCapture' => false,
'allowRefund' => false,
]);

$this->dataHandler->saveTransactionData($paymentTransaction, $salesChannelContext->getContext(), $data);

return new RedirectResponse($response['redirecturl']);
}

/**
* {@inheritdoc}
*/
public function finalize(AsyncPaymentTransactionStruct $transaction, Request $request, SalesChannelContext $salesChannelContext): void
{
$this->stateHandler->handleStateResponse($transaction, (string) $request->query->get('state'));
}

/**
* {@inheritdoc}
*/
public static function isCapturable(array $transactionData, array $payoneTransActionData): bool
{
if (static::isNeverCapturable($payoneTransActionData)) {
return false;
}

return static::isTransactionAppointedAndCompleted($transactionData) || static::matchesIsCapturableDefaults($transactionData);
}

/**
* {@inheritdoc}
*/
public static function isRefundable(array $transactionData): bool
{
if (static::isNeverRefundable($transactionData)) {
return false;
}

return static::matchesIsRefundableDefaults($transactionData);
}
}
6 changes: 3 additions & 3 deletions src/PaymentMethod/PayoneBancontact.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class PayoneBancontact extends AbstractPaymentMethod

protected string $id = self::UUID;

protected string $name = 'Payone Bancontact';
protected string $name = 'PAYONE Bancontact';

protected string $description = 'Pay fast and secure with your Bancontact card';

Expand All @@ -23,11 +23,11 @@ class PayoneBancontact extends AbstractPaymentMethod

protected array $translations = [
'de-DE' => [
'name' => 'Payone Bancontact',
'name' => 'PAYONE Bancontact',
'description' => 'Schnell und einfach bezahlen mit der Bancontact-Karte',
],
'en-GB' => [
'name' => 'Payone Bancontact',
'name' => 'PAYONE Bancontact',
'description' => 'Pay fast and secure with your Bancontact card',
],
];
Expand Down
36 changes: 36 additions & 0 deletions src/PaymentMethod/PayonePrzelewy24.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace PayonePayment\PaymentMethod;

use PayonePayment\Installer\PaymentMethodInstaller;
use PayonePayment\PaymentHandler\PayonePrzelewy24PaymentHandler;

class PayonePrzelewy24 extends AbstractPaymentMethod
{
public const UUID = PaymentMethodInstaller::PAYMENT_METHOD_IDS[self::class];

protected string $id = self::UUID;

protected string $name = 'PAYONE Przelewy24';

protected string $description = 'Pay save and secured with P24';

protected string $paymentHandler = PayonePrzelewy24PaymentHandler::class;

protected ?string $template = null;

protected array $translations = [
'de-DE' => [
'name' => 'PAYONE Przelewy24',
'description' => 'Zahle sicher und geschützt mit P24',
],
'en-GB' => [
'name' => 'PAYONE Przelewy24',
'description' => 'Pay save and secured with P24',
],
];

protected int $position = 160;
}
Loading

0 comments on commit 846d589

Please sign in to comment.