Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for paying by redirection directly to a chosen bank #42

Merged
merged 8 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions assets/shop/entrypoint.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
import './js/card_encoder';
import './img/hourglass.gif';
import './scss/style.scss';
import './js/_pay_by_link';
14 changes: 14 additions & 0 deletions assets/shop/js/_pay_by_link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
document.addEventListener("DOMContentLoaded", function() {
const tiles = document.querySelectorAll('.bank-tile');
const hiddenInput = document.getElementById('sylius_checkout_complete_tpay_pay_by_link_channel_id');

tiles.forEach(tile => {
tile.addEventListener('click', function () {
tiles.forEach(tileElement => tileElement.classList.remove('selected'));

tile.classList.add('selected');

hiddenInput.value = tile.getAttribute('data-bank-id');
});
});
});
25 changes: 25 additions & 0 deletions assets/shop/scss/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.bank-tile {
display: inline-block;
padding: 10px;
margin: 10px;
border: 1px solid #ccc;
cursor: pointer;
width: 100px;
text-align: center;
}

.bank-tile img {
max-width: 100%;
height: auto;
}

.bank-tile.selected {
border-color: blue;
background-color: #f0f8ff;
}

.bank-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
}
3 changes: 2 additions & 1 deletion config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return function(ContainerConfigurator $container): void {
return static function(ContainerConfigurator $container): void {
$container->import('config/**/*.php');

$parameters = $container->parameters();

$parameters->set('commerce_weavers_tpay.certificate.cache_ttl_in_seconds', 300);
$parameters->set('commerce_weavers_tpay.tpay_transaction_channels.cache_ttl_in_seconds', 300);
$parameters->set('commerce_weavers_tpay.waiting_for_payment.refresh_interval', 5);
};
16 changes: 16 additions & 0 deletions config/config/sylius_fixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,22 @@
],
'enabled' => true,
],
'pbl' => [
'code' => 'tpay_pbl',
'name' => 'Pay by Link (Tpay)',
'gatewayFactory' => 'tpay',
'gatewayName' => 'tpay',
'gatewayConfig' => [
'client_id' => '%env(string:TPAY_CLIENT_ID)%',
'client_secret' => '%env(string:TPAY_CLIENT_SECRET)%',
'type' => 'pay-by-link',
'production_mode' => false,
],
'channels' => [
'FASHION_WEB',
],
'enabled' => true,
],
],
],
]);
Expand Down
11 changes: 11 additions & 0 deletions config/config/sylius_template_events.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
'template' => '@CommerceWeaversSyliusTpayPlugin/shop/cart/complete/_card.html.twig',
'priority' => 5,
],
'pay-by-link' => [
'template' => '@CommerceWeaversSyliusTpayPlugin/shop/cart/complete/_payByLink.html.twig',
'priority' => 5,
]
],
],
'sylius.shop.layout.javascripts' => [
Expand All @@ -26,6 +30,13 @@
],
],
],
'sylius.shop.layout.stylesheets' => [
'blocks' => [
'commerce_weavers_tpay_styles' => [
'template' => '@CommerceWeaversSyliusTpayPlugin/shop/styles.html.twig',
],
],
],
],
]);
};
18 changes: 18 additions & 0 deletions config/services/context_provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use CommerceWeavers\SyliusTpayPlugin\ContextProvider\BankListContextProvider;

return static function(ContainerConfigurator $container): void {
$services = $container->services();

$services->set(BankListContextProvider::class)
->args([
service('commerce_weavers_tpay.tpay.provider.tpay_api_bank_list'),
])
->tag('sylius.ui.template_event.context_provider')
;
};
15 changes: 14 additions & 1 deletion config/services/payum/action.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\CreateBlikLevelZeroTransactionAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\CreateCardTransactionAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\CreatePayByLinkTransactionAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\CreateRedirectBasedTransactionAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\CreateTransactionAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\GetTpayTransactionsChannelsAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\NotifyAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api\PayWithCardAction;
use CommerceWeavers\SyliusTpayPlugin\Payum\Action\CaptureAction;
Expand Down Expand Up @@ -74,6 +75,18 @@
->tag('payum.action', ['factory' => TpayGatewayFactory::NAME, 'alias' => 'cw.tpay.refund'])
;

$services->set(GetTpayTransactionsChannelsAction::class)
->tag('payum.action', ['factory' => TpayGatewayFactory::NAME, 'alias' => 'cw.tpay.get_transactions_channels'])
;

$services->set(CreatePayByLinkTransactionAction::class)
->args([
service('commerce_weavers_tpay.tpay.factory.create_pay_by_link_payment_payload'),
service('commerce_weavers_tpay.payum.factory.token.notify'),
])
->tag('payum.action', ['factory' => TpayGatewayFactory::NAME, 'alias' => 'cw.tpay.create_pay_by_link_transaction'])
;

$services->set(ResolveNextRouteAction::class)
->tag('payum.action', ['factory' => TpayGatewayFactory::NAME, 'alias' => 'cw.tpay.resolve_next_route'])
;
Expand Down
38 changes: 37 additions & 1 deletion config/services/tpay.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateBlikLevelZeroPaymentPayloadFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateCardPaymentPayloadFactory;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateCardPaymentPayloadFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreatePayByLinkPayloadFactory;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreatePayByLinkPayloadFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateRedirectBasedPaymentPayloadFactory;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateRedirectBasedPaymentPayloadFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver\CachedTpayTransactionChannelResolver;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver\TpayTransactionChannelResolver;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Factory\BasicPaymentFactory;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Factory\X509Factory;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Factory\X509FactoryInterface;
Expand All @@ -23,8 +27,10 @@
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Verifier\ChecksumVerifierInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Verifier\SignatureVerifier;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Verifier\SignatureVerifierInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProvider;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProviderInterface;

return function(ContainerConfigurator $container): void {
return static function(ContainerConfigurator $container): void {
$services = $container->services();

$services->set('commerce_weavers_tpay.tpay.factory.create_blik_level_zero_payment_payload', CreateBlikLevelZeroPaymentPayloadFactory::class)
Expand All @@ -50,6 +56,13 @@
->alias(CreateRedirectBasedPaymentPayloadFactoryInterface::class, 'commerce_weavers_tpay.factory.create_redirect_based_payment_payload')
;

$services->set('commerce_weavers_tpay.tpay.factory.create_pay_by_link_payment_payload', CreatePayByLinkPayloadFactory::class)
->args([
service('commerce_weavers_tpay.tpay.factory.create_redirect_based_payment_payload'),
])
->alias(CreatePayByLinkPayloadFactoryInterface::class, 'commerce_weavers_tpay.factory.create_pay_by_link_payment_payload')
;

$services->set('commerce_weavers_tpay.tpay.security.notification.factory.basic_payment', BasicPaymentFactory::class)
->alias(BasicPaymentFactory::class, 'commerce_weavers_tpay.security.notification.factory.basic_payment')
;
Expand Down Expand Up @@ -96,4 +109,27 @@
])
->alias(SignatureVerifierInterface::class, 'commerce_weavers_tpay.security.notification.verifier.signature')
;

$services->set('commerce_weavers_tpay.tpay.provider.tpay_api_bank_list', TpayApiBankListProvider::class)
->args([
service('commerce_weavers_tpay.tpay.resolver.tpay_transaction_channel_resolver'),
])
->alias(TpayApiBankListProviderInterface::class, 'commerce_weavers_tpay.provider.tpay_api_bank_list')
;

$services->set('commerce_weavers_tpay.tpay.resolver.tpay_transaction_channel_resolver', TpayTransactionChannelResolver::class)
->args([
service('payum'),
])
->alias(TpayApiBankListProviderInterface::class, 'commerce_weavers_tpay.resolver.tpay_transaction_channel_resolver')
;

$services->set('commerce_weavers_tpay.tpay.resolver.cached_tpay_transaction_channel_resolver', CachedTpayTransactionChannelResolver::class)
->decorate('commerce_weavers_tpay.tpay.resolver.tpay_transaction_channel_resolver')
->args([
service('.inner'),
service('cache.app'),
param('commerce_weavers_tpay.tpay_transaction_channels.cache_ttl_in_seconds'),
])
;
};
7 changes: 6 additions & 1 deletion config/services/twig.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@

$services->set(TpayExtension::class)->tag('twig.extension');

$services->set(TpayRuntime::class)->args([service('payum.dynamic_gateways.cypher')])->tag('twig.runtime');
$services->set(TpayRuntime::class)
->args([
service('payum.dynamic_gateways.cypher'),
])
->tag('twig.runtime')
;
};
31 changes: 31 additions & 0 deletions src/ContextProvider/BankListContextProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\ContextProvider;

use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProviderInterface;
use Sylius\Bundle\UiBundle\ContextProvider\ContextProviderInterface;
use Sylius\Bundle\UiBundle\Registry\TemplateBlock;

final class BankListContextProvider implements ContextProviderInterface
{
public function __construct(
private readonly TpayApiBankListProviderInterface $bankListProvider,
) {
}

public function provide(array $templateContext, TemplateBlock $templateBlock): array
{
$templateContext['banks'] = $this->bankListProvider->provide();

return $templateContext;
}

public function supports(TemplateBlock $templateBlock): bool
{
return 'sylius.shop.checkout.complete.summary' === $templateBlock->getEventName() &&
'pay_by_link' === $templateBlock->getName()
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class RemoveUnnecessaryPaymentDetailsFieldsListener
{
public function __invoke(FormEvent $event): void
{
/** @var array{card?: string, blik_token?: string} $data */
/** @var array{card?: string, blik_token?: string, pay_by_link_channel_id?: string} $data */
$data = $event->getData() ?? [];
$form = $event->getForm();

Expand All @@ -21,5 +21,9 @@ public function __invoke(FormEvent $event): void
if (!isset($data['blik_token'])) {
$form->remove('blik_token');
}

if (!isset($data['pay_by_link_channel_id'])) {
$form->remove('pay_by_link_channel_id');
}
}
}
1 change: 1 addition & 0 deletions src/Form/Type/TpayGatewayConfigurationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'commerce_weavers_sylius_tpay.admin.gateway_configuration.type.redirect' => 'redirect',
'commerce_weavers_sylius_tpay.admin.gateway_configuration.type.card' => 'card',
'commerce_weavers_sylius_tpay.admin.gateway_configuration.type.blik' => 'blik',
'commerce_weavers_sylius_tpay.admin.gateway_configuration.type.pay_by_link' => 'pay-by-link',
],
],
)
Expand Down
10 changes: 9 additions & 1 deletion src/Form/Type/TpayPaymentDetailsType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace CommerceWeavers\SyliusTpayPlugin\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
Expand All @@ -13,7 +14,7 @@
final class TpayPaymentDetailsType extends AbstractType
{
public function __construct(
private object $removeUnnecessaryPaymentDetailsFieldsListener,
private readonly object $removeUnnecessaryPaymentDetailsFieldsListener,
) {
}

Expand Down Expand Up @@ -42,6 +43,13 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
],
],
)
->add(
'pay_by_link_channel_id',
HiddenType::class,
[
'property_path' => '[pay_by_link_channel_id]',
],
)
;

$builder->addEventListener(
Expand Down
73 changes: 73 additions & 0 deletions src/Payum/Action/Api/CreatePayByLinkTransactionAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Payum\Action\Api;

use CommerceWeavers\SyliusTpayPlugin\Model\PaymentDetails;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\Token\NotifyTokenFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Request\Api\CreateTransaction;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreatePayByLinkPayloadFactoryInterface;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Reply\HttpRedirect;
use Sylius\Component\Core\Model\PaymentInterface;
use Webmozart\Assert\Assert;

final class CreatePayByLinkTransactionAction extends AbstractCreateTransactionAction implements GatewayAwareInterface
{
use GatewayAwareTrait;

public function __construct(
private readonly CreatePayByLinkPayloadFactoryInterface $createPayByLinkPayloadFactory,
private readonly NotifyTokenFactoryInterface $notifyTokenFactory,
) {
parent::__construct();
}

/**
* @param CreateTransaction $request
*/
public function execute($request): void
{
/** @var PaymentInterface $model */
$model = $request->getModel();
$gatewayName = $request->getToken()?->getGatewayName() ?? $this->getGatewayNameFrom($model);

$localeCode = $this->getLocaleCodeFrom($model);
$notifyToken = $this->notifyTokenFactory->create($model, $gatewayName, $localeCode);

$response = $this->api->transactions()->createTransaction(
$this->createPayByLinkPayloadFactory->createFrom($model, $notifyToken->getTargetUrl(), $localeCode),
);

$paymentDetails = PaymentDetails::fromArray($model->getDetails());

$paymentDetails->setTransactionId($response['transactionId']);
$paymentDetails->setStatus($response['status']);
$paymentDetails->setPaymentUrl($response['transactionPaymentUrl']);

$model->setDetails($paymentDetails->toArray());

Assert::notNull($paymentUrl = $paymentDetails->getPaymentUrl());

throw new HttpRedirect($paymentUrl);
}

public function supports($request): bool
{
if (!$request instanceof CreateTransaction) {
return false;
}

$model = $request->getModel();

if (!$model instanceof PaymentInterface) {
return false;
}

$details = $model->getDetails();

return isset($details['tpay']['pay_by_link_channel_id']);
}
}
Loading
Loading