Skip to content

Commit

Permalink
Change resolved banks on pbl payments (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
lchrusciel authored Oct 31, 2024
2 parents b4969a9 + e5866db commit 5347811
Show file tree
Hide file tree
Showing 24 changed files with 707 additions and 29 deletions.
2 changes: 1 addition & 1 deletion config/services/context_provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

$services->set(BankListContextProvider::class)
->args([
service('commerce_weavers_sylius_tpay.tpay.provider.tpay_api_bank_list'),
service('commerce_weavers_sylius_tpay.tpay.provider.validated_tpay_api_bank_list'),
])
->tag('sylius.ui.template_event.context_provider')
;
Expand Down
4 changes: 1 addition & 3 deletions config/services/form.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use CommerceWeavers\SyliusTpayPlugin\EventListener\AddCreditCardToAccountMenuEventListener;
use CommerceWeavers\SyliusTpayPlugin\Form\DataTransformer\CardTypeDataTransformer;
use CommerceWeavers\SyliusTpayPlugin\Form\DataTransformer\VisaMobilePhoneDataTransformer;
use CommerceWeavers\SyliusTpayPlugin\Form\EventListener\AddSavedCreditCardsListener;
use CommerceWeavers\SyliusTpayPlugin\Form\EventListener\DecryptGatewayConfigListener;
use CommerceWeavers\SyliusTpayPlugin\Form\EventListener\EncryptGatewayConfigListener;
Expand All @@ -18,7 +16,7 @@
use CommerceWeavers\SyliusTpayPlugin\Form\Type\TpayPaymentDetailsType;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\TpayGatewayFactory;

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

$services->set(CompleteTypeExtension::class)
Expand Down
21 changes: 16 additions & 5 deletions config/services/tpay.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateRedirectBasedPaymentPayloadFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateVisaMobilePaymentPayloadFactory;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Factory\CreateVisaMobilePaymentPayloadFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProvider;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProviderInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\AvailableTpayChannelListProvider;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\AvailableTpayChannelListProviderInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\ValidTpayChannelListProvider;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver\CachedTpayTransactionChannelResolver;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver\TpayTransactionChannelResolver;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Security\Notification\Factory\BasicPaymentFactory;
Expand Down Expand Up @@ -149,18 +150,28 @@
->alias(SignatureVerifierInterface::class, 'commerce_weavers_sylius_tpay.tpay.security.notification.verifier.signature')
;

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

$services->set('commerce_weavers_sylius_tpay.tpay.provider.validated_tpay_api_bank_list', ValidTpayChannelListProvider::class)
->args([
service('commerce_weavers_sylius_tpay.tpay.provider.available_tpay_api_bank_list'),
service('sylius.repository.payment_method'),
service('sylius.context.channel'),
service('payum.dynamic_gateways.cypher')
])
->alias(AvailableTpayChannelListProviderInterface::class, 'commerce_weavers_sylius_tpay.tpay.provider.validated_tpay_api_bank_list')
;

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

$services->set('commerce_weavers_sylius_tpay.tpay.resolver.cached_tpay_transaction_channel_resolver', CachedTpayTransactionChannelResolver::class)
Expand Down
8 changes: 8 additions & 0 deletions config/services/validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use CommerceWeavers\SyliusTpayPlugin\Validator\Constraint\EncodedGooglePayTokenValidator;
use CommerceWeavers\SyliusTpayPlugin\Validator\Constraint\ForAuthorizedUserOnlyValidator;
use CommerceWeavers\SyliusTpayPlugin\Validator\Constraint\ValidTpayChannelValidator;

return static function(ContainerConfigurator $container): void {
$services = $container->services();
Expand All @@ -20,4 +21,11 @@
])
->tag('validator.constraint_validator')
;

$services->set('commerce_weavers_sylius_tpay.validator.constraint.valid_tpay_channel', ValidTpayChannelValidator::class)
->args([
service('commerce_weavers_sylius_tpay.tpay.provider.validated_tpay_api_bank_list'),
])
->tag('validator.constraint_validator')
;
};
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ parameters:
- '#Comparison operation "<=" between int<1, max> and \(array\|float\|int\) results in an error\.#'
- '#Parameter \#1 \$request \(CommerceWeavers\\SyliusTpayPlugin\\Payum\\Request\\Api\\InitializeApplePayPayment\) of method CommerceWeavers\\SyliusTpayPlugin\\Payum\\Action\\Api\\InitializeApplePayPaymentAction::doExecute\(\) should be contravariant with parameter \$request \(Payum\\Core\\Request\\Generic\) of method CommerceWeavers\\SyliusTpayPlugin\\Payum\\Action\\Api\\BasePaymentAwareAction::doExecute\(\)#'
- '#Parameter \#1 \$request \(CommerceWeavers\\SyliusTpayPlugin\\Payum\\Request\\Api\\Notify\) of method CommerceWeavers\\SyliusTpayPlugin\\Payum\\Action\\Api\\NotifyAction::doExecute\(\) should be contravariant with parameter \$request \(Payum\\Core\\Request\\Generic\) of method CommerceWeavers\\SyliusTpayPlugin\\Payum\\Action\\Api\\BasePaymentAwareAction::doExecute\(\)#'
- '#Parameter \#2 \$callback of function array_filter expects \(callable\(array\|bool\|object\|string\): bool\)\|null, Closure\(array\): bool given#'
6 changes: 3 additions & 3 deletions src/ContextProvider/BankListContextProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

namespace CommerceWeavers\SyliusTpayPlugin\ContextProvider;

use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProviderInterface;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\ValidTpayChannelListProviderInterface;
use Sylius\Bundle\UiBundle\ContextProvider\ContextProviderInterface;
use Sylius\Bundle\UiBundle\Registry\TemplateBlock;
use Sylius\Component\Core\Model\OrderInterface;

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

Expand All @@ -27,7 +27,7 @@ public function provide(array $templateContext, TemplateBlock $templateBlock): a
}
}

$templateContext['banks'] = $this->bankListProvider->provide();
$templateContext['banks'] = $this->validTpayChannelListProvider->provide();

return $templateContext;
}
Expand Down
5 changes: 5 additions & 0 deletions src/Form/Type/TpayPaymentDetailsType.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use CommerceWeavers\SyliusTpayPlugin\Repository\CreditCardRepositoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Validator\Constraint\EncodedGooglePayToken;
use CommerceWeavers\SyliusTpayPlugin\Validator\Constraint\ValidTpayChannel;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
Expand Down Expand Up @@ -87,6 +88,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
HiddenType::class,
[
'property_path' => '[tpay_channel_id]',
'validation_groups' => ['sylius_checkout_complete'],
'constraints' => [
new ValidTpayChannel(groups: ['sylius_checkout_complete']),
],
],
)
->add(
Expand Down
30 changes: 30 additions & 0 deletions src/Repository/FindByChannelWithGatewayConfigTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Sylius\Component\Channel\Model\ChannelInterface;

/**
* @mixin EntityRepository
*/
trait FindByChannelWithGatewayConfigTrait
{
public function findByChannelAndGatewayConfigNameWithGatewayConfig(ChannelInterface $channel, string $gatewayConfigName): array
{
return $this->createQueryBuilder('o')
->addSelect('gatewayConfig')
->innerJoin('o.gatewayConfig', 'gatewayConfig', Join::WITH, 'gatewayConfig.gatewayName = :gatewayName')
->where('o.enabled = :enabled')
->andWhere(':channel MEMBER OF o.channels')
->setParameter('enabled', true)
->setParameter('channel', $channel)
->setParameter('gatewayName', $gatewayConfigName)
->getQuery()
->getResult()
;
}
}
13 changes: 13 additions & 0 deletions src/Repository/FindByChannelWithGatewayConfigTraitInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Repository;

use Sylius\Component\Channel\Model\ChannelInterface;
use Sylius\Component\Core\Repository\PaymentMethodRepositoryInterface as BasePaymentMethodRepositoryInterface;

interface FindByChannelWithGatewayConfigTraitInterface extends BasePaymentMethodRepositoryInterface
{
public function findByChannelWithGatewayConfig(ChannelInterface $channel): array;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver\TpayTransactionChannelResolverInterface;

final class TpayApiBankListProvider implements TpayApiBankListProviderInterface
final class AvailableTpayChannelListProvider implements AvailableTpayChannelListProviderInterface
{
public function __construct(
private readonly TpayTransactionChannelResolverInterface $channelResolver,
Expand All @@ -30,11 +30,7 @@ public function provide(): array
* }
*/
return array_filter($result, static function (array $channel) {
return
($channel['instantRedirection'] ?? false) === true &&
($channel['onlinePayment'] ?? false) === true &&
($channel['available'] ?? false) === true
;
return ($channel['available'] ?? false) === true;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace CommerceWeavers\SyliusTpayPlugin\Tpay\Provider;

interface TpayApiBankListProviderInterface
interface AvailableTpayChannelListProviderInterface
{
/** @return array{
* id: string,
Expand Down
83 changes: 83 additions & 0 deletions src/Tpay/Provider/ValidTpayChannelListProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Tpay\Provider;

use App\Repository\PaymentMethodRepositoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Exception\UnableToGetBankListException;
use CommerceWeavers\SyliusTpayPlugin\Tpay\PayGroup;
use CommerceWeavers\SyliusTpayPlugin\Tpay\PaymentType;
use Payum\Core\Security\CryptedInterface;
use Payum\Core\Security\CypherInterface;
use Sylius\Bundle\PayumBundle\Model\GatewayConfigInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Webmozart\Assert\Assert;

final class ValidTpayChannelListProvider implements ValidTpayChannelListProviderInterface
{
public function __construct(
private readonly AvailableTpayChannelListProviderInterface $availableTpayApiBankListProvider,
private readonly PaymentMethodRepositoryInterface $paymentMethodRepository,
private readonly ChannelContextInterface $channelContext,
private readonly CypherInterface $cypher,
) {
}

public function provide(): array
{
$availableChannels = $this->availableTpayApiBankListProvider->provide();

/** @var PaymentMethodInterface[] $paymentMethods */
$paymentMethods = $this->paymentMethodRepository->findByChannelAndGatewayConfigNameWithGatewayConfig(
$this->channelContext->getChannel(),
'tpay',
);

Assert::notEmpty($paymentMethods, 'There is no payment method of Tpay type available');

$paymentMethodsToRemoveByGroupId = [];
$hasPblPaymentAvailable = false;
foreach ($paymentMethods as $paymentMethod) {
/** @var (GatewayConfigInterface&CryptedInterface)|null $tpayGatewayConfig */
$tpayGatewayConfig = $paymentMethod->getGatewayConfig();

if (null === $tpayGatewayConfig) {
continue;
}

$tpayGatewayConfig->decrypt($this->cypher);
$config = $tpayGatewayConfig->getConfig();

if (!array_key_exists('type', $config)) {
continue;
}

if ($hasPblPaymentAvailable === false && $config['type'] === PaymentType::PAY_BY_LINK) {
$hasPblPaymentAvailable = true;
}

match ($config['type']) {
PaymentType::VISA_MOBILE => $paymentMethodsToRemoveByGroupId[] = PayGroup::VISA_MOBILE,
PaymentType::APPLE_PAY => $paymentMethodsToRemoveByGroupId[] = PayGroup::APPLE_PAY,
PaymentType::GOOGLE_PAY => $paymentMethodsToRemoveByGroupId[] = PayGroup::GOOGLE_PAY,
PaymentType::BLIK => $paymentMethodsToRemoveByGroupId[] = PayGroup::BLIK,
PaymentType::CARD => $paymentMethodsToRemoveByGroupId[] = PayGroup::CARD,
default => null,
};
}

if (!$hasPblPaymentAvailable) {
throw new UnableToGetBankListException(
'Bank list cannot be retrieved if there is no payment method with PayByLink type configured',
);
}

return array_filter($availableChannels, static function (array $channel) use ($paymentMethodsToRemoveByGroupId): bool {
$groupId = (int) $channel['groups'][0]['id'];

return !in_array($groupId, $paymentMethodsToRemoveByGroupId, true);
});
}
}
10 changes: 10 additions & 0 deletions src/Tpay/Provider/ValidTpayChannelListProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Tpay\Provider;

interface ValidTpayChannelListProviderInterface
{
public function provide(): array;
}
19 changes: 19 additions & 0 deletions src/Validator/Constraint/ValidTpayChannel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Validator\Constraint;

use Symfony\Component\Validator\Constraint;

final class ValidTpayChannel extends Constraint
{
public string $message = 'commerce_weavers_sylius_tpay.shop.pay.tpay_channel.not_valid';

public const NOT_VALID_CHANNEL_ERROR = '632f97f3-c302-409b-a321-ec078194302d';

public function getTargets(): string
{
return self::PROPERTY_CONSTRAINT;
}
}
40 changes: 40 additions & 0 deletions src/Validator/Constraint/ValidTpayChannelValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Validator\Constraint;

use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\ValidTpayChannelListProviderInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Webmozart\Assert\Assert;

final class ValidTpayChannelValidator extends ConstraintValidator
{
public function __construct(
private readonly ValidTpayChannelListProviderInterface $validatedTpayApiBankListProvider,
) {
}

public function validate(mixed $value, Constraint $constraint): void
{
if (null === $value) {
return;
}

Assert::string($value);

Assert::isInstanceOf($constraint, ValidTpayChannel::class);

$validChannels = $this->validatedTpayApiBankListProvider->provide();

if (array_key_exists($value, $validChannels)) {
return;
}

$this->context->buildViolation($constraint->message)
->setCode($constraint::NOT_VALID_CHANNEL_ERROR)
->addViolation()
;
}
}
6 changes: 6 additions & 0 deletions tests/Application/config/packages/_sylius.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ sylius_order:
order:
classes:
model: App\Entity\Order

sylius_payment:
resources:
payment_method:
classes:
repository: App\Repository\PaymentMethodRepository
13 changes: 13 additions & 0 deletions tests/Application/src/Repository/PaymentMethodRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace App\Repository;

use CommerceWeavers\SyliusTpayPlugin\Repository\FindByChannelWithGatewayConfigTrait;
use Sylius\Bundle\CoreBundle\Doctrine\ORM\PaymentMethodRepository as BasePaymentMethodRepository;

final class PaymentMethodRepository extends BasePaymentMethodRepository implements PaymentMethodRepositoryInterface
{
use FindByChannelWithGatewayConfigTrait;
}
Loading

0 comments on commit 5347811

Please sign in to comment.