Skip to content

Commit

Permalink
Resolve Tpay transaction channels into an array if an error occurred (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lchrusciel authored Nov 8, 2024
2 parents b046a6a + c88edef commit 23b6c80
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 9 deletions.
6 changes: 6 additions & 0 deletions config/services/payum/factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\CreateTransactionFactory;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\CreateTransactionFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\GetTpayTransactionsChannelsFactory;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\GetTpayTransactionsChannelsFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\InitializeApplePayPaymentFactory;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\InitializeApplePayPaymentFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\NotifyDataFactory;
Expand Down Expand Up @@ -35,6 +37,10 @@
->alias(CreateTransactionFactoryInterface::class, 'commerce_weavers_sylius_tpay.payum.factory.create_transaction')
;

$services->set('commerce_weavers_sylius_tpay.payum.factory.get_tpay_transactions_channels', GetTpayTransactionsChannelsFactory::class)
->alias(GetTpayTransactionsChannelsFactoryInterface::class, 'commerce_weavers_sylius_tpay.payum.factory.get_tpay_transactions_channels')
;

$services->set('commerce_weavers_sylius_tpay.payum.factory.initialize_apple_pay_payment', InitializeApplePayPaymentFactory::class)
->alias(InitializeApplePayPaymentFactoryInterface::class, 'commerce_weavers_sylius_tpay.payum.factory.initialize_apple_pay_payment')
;
Expand Down
3 changes: 3 additions & 0 deletions config/services/tpay.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@
$services->set('commerce_weavers_sylius_tpay.tpay.resolver.tpay_transaction_channel_resolver', TpayTransactionChannelResolver::class)
->args([
service('payum'),
service('commerce_weavers_sylius_tpay.payum.factory.get_tpay_transactions_channels'),
service('logger')->nullOnInvalid(),
])
->tag('monolog.logger', ['channel' => 'sylius_tpay'])
->alias(AvailableTpayChannelListProviderInterface::class, 'commerce_weavers_sylius_tpay.tpay.resolver.tpay_transaction_channel_resolver')
;

Expand Down
16 changes: 16 additions & 0 deletions src/Payum/Factory/GetTpayTransactionsChannelsFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Payum\Factory;

use CommerceWeavers\SyliusTpayPlugin\Payum\Request\Api\GetTpayTransactionsChannels;
use Payum\Core\Model\ArrayObject;

final class GetTpayTransactionsChannelsFactory implements GetTpayTransactionsChannelsFactoryInterface
{
public function createNewEmpty(): GetTpayTransactionsChannels
{
return new GetTpayTransactionsChannels(new ArrayObject());
}
}
12 changes: 12 additions & 0 deletions src/Payum/Factory/GetTpayTransactionsChannelsFactoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace CommerceWeavers\SyliusTpayPlugin\Payum\Factory;

use CommerceWeavers\SyliusTpayPlugin\Payum\Request\Api\GetTpayTransactionsChannels;

interface GetTpayTransactionsChannelsFactoryInterface
{
public function createNewEmpty(): GetTpayTransactionsChannels;
}
7 changes: 1 addition & 6 deletions src/Tpay/Resolver/CachedTpayTransactionChannelResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Webmozart\Assert\Assert;

final class CachedTpayTransactionChannelResolver implements TpayTransactionChannelResolverInterface
{
Expand All @@ -21,14 +20,10 @@ public function __construct(

public function resolve(): array
{
$result = $this->cache->get(self::COMMERCE_WEAVERS_SYLIUS_TPAY_TRANSACTION_CHANNELS, function (ItemInterface $item): array {
return (array) $this->cache->get(self::COMMERCE_WEAVERS_SYLIUS_TPAY_TRANSACTION_CHANNELS, function (ItemInterface $item): array {
$item->expiresAfter($this->cacheTtlInSeconds);

return $this->decorated->resolve();
});

Assert::isArray($result);

return $result;
}
}
35 changes: 32 additions & 3 deletions src/Tpay/Resolver/TpayTransactionChannelResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,57 @@

namespace CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver;

use CommerceWeavers\SyliusTpayPlugin\Payum\Exception\UnableToGetBankListException;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\GetTpayTransactionsChannelsFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Request\Api\GetTpayTransactionsChannels;
use Payum\Core\Model\ArrayObject;
use Payum\Core\Payum;
use Psr\Log\LoggerInterface;
use Tpay\OpenApi\Utilities\TpayException;

final class TpayTransactionChannelResolver implements TpayTransactionChannelResolverInterface
{
public function __construct(
private readonly Payum $payum,
private readonly ?GetTpayTransactionsChannelsFactoryInterface $getTpayTransactionsChannelsFactory = null,
private readonly ?LoggerInterface $logger = null,
) {
if (null === $this->getTpayTransactionsChannelsFactory) {
trigger_deprecation(
'commerce-weavers/sylius-tpay-plugin',
'1.0',
'Not passing a $getTpayTransactionsChannelsFactory to %s constructor is deprecated and will be removed in SyliusTpayPlugin 2.0.',
self::class,
);
}
}

public function resolve(): array
{
$gateway = $this->payum->getGateway('tpay');

$gateway->execute($value = new GetTpayTransactionsChannels(new ArrayObject()), true);
$value = $this->getTpayTransactionsChannelsFactory?->createNewEmpty()
?? new GetTpayTransactionsChannels(new ArrayObject());

try {
$gateway->execute($value, true);
} catch (TpayException $e) {
$this->logger?->critical('Unable to get banks list. TpayException thrown.', ['exceptionMessage' => $e->getMessage()]);

return [];
}

$result = $value->getResult();

if (!isset($result['result']) || 'success' !== $result['result']) {
throw new UnableToGetBankListException('Unable to get banks list. Response: ' . json_encode($result));
$this->logger?->critical('Unable to get banks list. The result is not success.', ['responseBody' => json_encode($result)]);

return [];
}

if (!isset($result['channels'])) {
$this->logger?->critical('Unable to get banks list. The channels key is missing.', ['responseBody' => json_encode($result)]);

return [];
}

$indexedResult = [];
Expand Down
5 changes: 5 additions & 0 deletions tests/Application/config/packages/dev/monolog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ monolog:
firephp:
type: firephp
level: info
sylius_tpay:
type: stream
path: "%kernel.logs_dir%/sylius_tpay_%kernel.environment%.log"
level: debug
channels: [sylius_tpay]
144 changes: 144 additions & 0 deletions tests/Unit/Tpay/Resolver/TpayTransactionChannelResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php

declare(strict_types=1);


namespace Tests\CommerceWeavers\SyliusTpayPlugin\Unit\Tpay\Resolver;

use ArrayObject;
use CommerceWeavers\SyliusTpayPlugin\Payum\Factory\GetTpayTransactionsChannelsFactoryInterface;
use CommerceWeavers\SyliusTpayPlugin\Payum\Request\Api\GetTpayTransactionsChannels;
use CommerceWeavers\SyliusTpayPlugin\Tpay\Resolver\TpayTransactionChannelResolver;
use Payum\Core\GatewayInterface;
use Payum\Core\Payum;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Log\LoggerInterface;
use Tpay\OpenApi\Utilities\TpayException;
use Webmozart\Assert\Assert;

final class TpayTransactionChannelResolverTest extends TestCase
{
use ProphecyTrait;

private Payum|ObjectProphecy $payum;

private GetTpayTransactionsChannelsFactoryInterface|ObjectProphecy $getTpayTransactionsChannelsFactory;

private LoggerInterface|ObjectProphecy $logger;

protected function setUp(): void
{
$this->payum = $this->prophesize(Payum::class);
$this->getTpayTransactionsChannelsFactory = $this->prophesize(GetTpayTransactionsChannelsFactoryInterface::class);
$this->logger = $this->prophesize(LoggerInterface::class);
}

public function test_it_resolves_tpay_transaction_channels(): void
{
$gateway = $this->prophesize(GatewayInterface::class);
$value = $this->prophesize(GetTpayTransactionsChannels::class);
$this->payum->getGateway('tpay')->willReturn($gateway);
$this->getTpayTransactionsChannelsFactory->createNewEmpty()->willReturn($value);
$gateway->execute($value, true)->shouldBeCalled();
$value->getResult()->willReturn([
'result' => 'success',
'channels' => [
['id' => 1, 'name' => 'Bank 1'],
['id' => 2, 'name' => 'Bank 2'],
],
]);

$result = $this->createTestSubject()->resolve();

$this->assertEquals([
1 => ['id' => 1, 'name' => 'Bank 1'],
2 => ['id' => 2, 'name' => 'Bank 2'],
], $result);
}

public function test_it_resolves_an_empty_array_when_tpay_exception_is_thrown(): void
{
$gateway = $this->prophesize(GatewayInterface::class);
$value = $this->prophesize(GetTpayTransactionsChannels::class);
$this->payum->getGateway('tpay')->willReturn($gateway);
$this->getTpayTransactionsChannelsFactory->createNewEmpty()->willReturn($value);
$gateway
->execute($value, true)
->willThrow(new TpayException('Booo! I am a TpayException!'))
;
$this->logger
->critical('Unable to get banks list. TpayException thrown.', Argument::withKey('exceptionMessage'))
->shouldBeCalled()
;

$result = $this->createTestSubject()->resolve();

$this->assertEquals([], $result);
}

public function test_it_resolves_an_empty_array_when_the_result_is_not_success(): void
{
$gateway = $this->prophesize(GatewayInterface::class);
$value = $this->prophesize(GetTpayTransactionsChannels::class);
$this->payum->getGateway('tpay')->willReturn($gateway);
$value->getResult()->willReturn(['result' => 'failure']);
$this->getTpayTransactionsChannelsFactory->createNewEmpty()->willReturn($value);
$gateway->execute($value, true)->shouldBeCalled();

$this->logger
->critical('Unable to get banks list. The result is not success.', ['responseBody' => '{"result":"failure"}'])
->shouldBeCalled()
;

$result = $this->createTestSubject()->resolve();

$this->assertEquals([], $result);
}

public function test_it_resolves_an_empty_array_when_the_channels_key_is_missing(): void
{
$gateway = $this->prophesize(GatewayInterface::class);
$value = $this->prophesize(GetTpayTransactionsChannels::class);
$this->payum->getGateway('tpay')->willReturn($gateway);
$value->getResult()->willReturn(['result' => 'success']);
$this->getTpayTransactionsChannelsFactory->createNewEmpty()->willReturn($value);
$gateway->execute($value, true)->shouldBeCalled();

$this->logger
->critical('Unable to get banks list. The channels key is missing.', ['responseBody' => '{"result":"success"}'])
->shouldBeCalled()
;

$result = $this->createTestSubject()->resolve();

$this->assertEquals([], $result);
}

public function test_it_does_not_log_errors_if_logger_is_null(): void
{
$gateway = $this->prophesize(GatewayInterface::class);
$value = $this->prophesize(GetTpayTransactionsChannels::class);
$this->payum->getGateway('tpay')->willReturn($gateway);
$value->getResult()->willReturn(['result' => 'failure']);
$this->getTpayTransactionsChannelsFactory->createNewEmpty()->willReturn($value);
$gateway->execute($value, true)->shouldBeCalled();

$this->logger->critical(Argument::cetera())->shouldNotBeCalled();

$result = $this->createTestSubject(false)->resolve();

$this->assertEquals([], $result);
}

private function createTestSubject(bool $withLogger = true): TpayTransactionChannelResolver
{
return new TpayTransactionChannelResolver(
$this->payum->reveal(),
$this->getTpayTransactionsChannelsFactory->reveal(),
$withLogger ? $this->logger->reveal() : null,
);
}
}

0 comments on commit 23b6c80

Please sign in to comment.