Skip to content
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
24 changes: 24 additions & 0 deletions src/Entity/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Payment
'url_pending' => '',
'chargeUnregulatedCardFees' => null,
'enableApplePayGooglePay' => null,
'threeDSPreference' => null,
'prepareOnly' => true,
'embedded' => false,
'allowedMethods' => [],
Expand Down Expand Up @@ -669,6 +670,29 @@ public function setEnableApplePayGooglePay($enableApplePayGooglePay): self
return $this;
}

/**
* Vrací preferenci 3D Secure ověření karetních plateb.
* @return null|string
*/
public function getThreeDSPreference(): ?string
{
return $this->params['threeDSPreference'] ?? null;
}

/**
* Preference 3D Secure ověření karetních plateb. Povolené hodnoty jsou 'AUTO' nebo 'FAST'.
* Pokud parametr není zaslán, použije se nastavení Dynamické řízení 3DS v Klientském portálu.
*
* @param string $threeDSPreference
* @return Payment
*/
public function setThreeDSPreference(string $threeDSPreference): self
{
$this->setParam('threeDSPreference', $threeDSPreference);

return $this;
}

/**
* @param string $attributeName
* @return bool|int|string
Expand Down
6 changes: 6 additions & 0 deletions src/Entity/Request/PaymentCreateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public function toArray(): array
unset($output['enableApplePayGooglePay']);
}

if($this->payment->getThreeDSPreference() !== null) {
$output['threeDSPreference'] = $this->payment->getThreeDSPreference();
} else {
unset($output['threeDSPreference']);
}

$output['embedded'] = $this->payment->isEmbedded() ? 'true' : 'false';

return $output;
Expand Down
138 changes: 138 additions & 0 deletions tests/Integration/ComgateBuilderCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php

declare(strict_types=1);

namespace Tests\Integration;

use Codeception\Attribute\Group;
use Comgate\SDK\Client;
use Comgate\SDK\ClientTerminal;
use Comgate\SDK\Comgate;
use Comgate\SDK\Config;
use Comgate\SDK\Http\ITransport;
use Comgate\SDK\Logging\StdoutLogger;
use Tests\Support\IntegrationTester;

class ComgateBuilderCest
{
#[Group('builder')]
public function createClientTest(IntegrationTester $I): void
{
$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->createClient();

$I->assertInstanceOf(Client::class, $client);
}

#[Group('builder')]
public function createTerminalClientTest(IntegrationTester $I): void
{
$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->createTerminalClient();

$I->assertInstanceOf(ClientTerminal::class, $client);
}

#[Group('builder')]
public function customUrlIsAppliedTest(IntegrationTester $I): void
{
$customUrl = 'https://custom.example.com/v1/';

$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->setUrl($customUrl)
->createClient();

$I->assertInstanceOf(Client::class, $client);
$I->assertEquals($customUrl, $client->getTransport()->getConfig()->getUrl());
}

#[Group('builder')]
public function defaultUrlIsProductionTest(IntegrationTester $I): void
{
$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->createClient();

$config = $client->getTransport()->getConfig();
$I->assertInstanceOf(ITransport::class, $client->getTransport());
$I->assertStringStartsWith('https://', $config->getUrl());
}

#[Group('builder')]
public function merchantAndSecretAreStoredInConfigTest(IntegrationTester $I): void
{
$merchant = 'test-merchant-123';
$secret = 'test-secret-abc';

$client = Comgate::defaults()
->setMerchant($merchant)
->setSecret($secret)
->createClient();

$config = $client->getTransport()->getConfig();
$I->assertEquals($merchant, $config->getMerchant());
$I->assertEquals($secret, $config->getSecret());
}

#[Group('builder')]
public function builderWithLoggerCreatesClientTest(IntegrationTester $I): void
{
$logger = new StdoutLogger();

$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->setLogger($logger)
->createClient();

$I->assertInstanceOf(Client::class, $client);
}

#[Group('builder')]
public function setUrlWithoutTrailingSlashAddsOneTest(IntegrationTester $I): void
{
$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->setUrl('https://example.com/v1')
->createClient();

$I->assertStringEndsWith('/', $client->getTransport()->getConfig()->getUrl());
}

#[Group('builder')]
public function setUrlWithMultipleTrailingSlashesCollapsesToOneTest(IntegrationTester $I): void
{
$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->setUrl('https://example.com/v1///')
->createClient();

$url = $client->getTransport()->getConfig()->getUrl();

$I->assertStringEndsWith('/', $url);
$I->assertStringEndsNotWith('//', $url);
}

#[Group('builder')]
public function setUrlAlreadyWithTrailingSlashIsUnchangedTest(IntegrationTester $I): void
{
$url = 'https://example.com/v1/';

$client = Comgate::defaults()
->setMerchant($_ENV['API_MERCHANT'])
->setSecret($_ENV['API_SECRET'])
->setUrl($url)
->createClient();

$I->assertEquals($url, $client->getTransport()->getConfig()->getUrl());
}
}
111 changes: 111 additions & 0 deletions tests/Integration/Entity/PaymentNotificationCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

declare(strict_types=1);

namespace Tests\Integration\Entity;

use Codeception\Attribute\Group;
use Comgate\SDK\Entity\Money;
use Comgate\SDK\Entity\PaymentNotification;
use Tests\Support\IntegrationTester;

class PaymentNotificationCest
{
#[Group('notification')]
public function createFromCompletePayloadTest(IntegrationTester $I): void
{
$data = [
'merchant' => '123456',
'test' => 'true',
'price' => '10000',
'curr' => 'CZK',
'label' => 'Test product',
'refId' => 'order-42',
'email' => 'customer@example.com',
'transId' => 'AB12-CD34-EF56',
'status' => 'PAID',
'fee' => '0.50',
'vs' => '9876543210',
'method' => 'CARD_ALL',
'secret' => 'my-secret',
];

$notification = PaymentNotification::createFrom($data);

$I->assertInstanceOf(PaymentNotification::class, $notification);
$I->assertEquals('123456', $notification->getMerchant());
$I->assertTrue($notification->isTest());
$I->assertInstanceOf(Money::class, $notification->getPrice());
$I->assertEquals(10000, $notification->getPrice()->get());
$I->assertEquals('CZK', $notification->getCurrency());
$I->assertEquals('Test product', $notification->getLabel());
$I->assertEquals('order-42', $notification->getReferenceId());
$I->assertEquals('customer@example.com', $notification->getEmail());
$I->assertEquals('AB12-CD34-EF56', $notification->getTransactionId());
$I->assertEquals('PAID', $notification->getStatus());
$I->assertEquals('0.50', $notification->getFee());
$I->assertEquals('9876543210', $notification->getVs());
$I->assertEquals('CARD_ALL', $notification->getMethod());
$I->assertEquals('my-secret', $notification->getSecret());
}

#[Group('notification')]
public function createFromMissingFieldsTest(IntegrationTester $I): void
{
$notification = PaymentNotification::createFrom([]);

$I->assertInstanceOf(PaymentNotification::class, $notification);
$I->assertNull($notification->getMerchant());
$I->assertNull($notification->getTransactionId());
$I->assertNull($notification->getStatus());
$I->assertNull($notification->getPrice());
$I->assertNull($notification->getCurrency());
$I->assertNull($notification->getEmail());
$I->assertNull($notification->getLabel());
$I->assertNull($notification->getReferenceId());
$I->assertNull($notification->getFee());
$I->assertNull($notification->getVs());
$I->assertNull($notification->getMethod());
$I->assertNull($notification->getSecret());
}

#[Group('notification')]
public function isTestBooleanConversionTest(IntegrationTester $I): void
{
$notificationTrue = PaymentNotification::createFrom(['test' => 'true']);
$I->assertTrue($notificationTrue->isTest());

$notificationFalse = PaymentNotification::createFrom(['test' => 'false']);
$I->assertFalse($notificationFalse->isTest());

$notificationOne = PaymentNotification::createFrom(['test' => '1']);
$I->assertTrue($notificationOne->isTest());

$notificationZero = PaymentNotification::createFrom(['test' => '0']);
$I->assertFalse($notificationZero->isTest());
}

#[Group('notification')]
public function createFactoryReturnsEmptyObjectTest(IntegrationTester $I): void
{
$notification = PaymentNotification::create();

$I->assertInstanceOf(PaymentNotification::class, $notification);
$I->assertNull($notification->getTransactionId());
$I->assertNull($notification->getMerchant());
}

#[Group('notification')]
public function settersWorkCorrectlyTest(IntegrationTester $I): void
{
$notification = PaymentNotification::createFrom(['vs' => '111', 'method' => 'BANK_ALL']);

$notification->setVs('999');
$notification->setMethod('CARD_ALL');
$notification->setSecret('new-secret');

$I->assertEquals('999', $notification->getVs());
$I->assertEquals('CARD_ALL', $notification->getMethod());
$I->assertEquals('new-secret', $notification->getSecret());
}
}
96 changes: 96 additions & 0 deletions tests/Integration/Entity/Request/TerminalRequestsCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

declare(strict_types=1);

namespace Tests\Integration\Entity\Request;

use Codeception\Attribute\DataProvider;
use Codeception\Attribute\Group;
use Codeception\Example;
use Comgate\SDK\Entity\Codes\CurrencyCode;
use Comgate\SDK\Entity\Money;
use Comgate\SDK\Entity\Request\TerminalPaymentCreateRequest;
use Comgate\SDK\Entity\Request\TerminalRefundCreateRequest;
use Comgate\SDK\Entity\TerminalPayment;
use Comgate\SDK\Entity\TerminalRefund;
use Tests\Support\IntegrationTester;

class TerminalRequestsCest
{
#[Group('terminal-request')]
#[DataProvider('getTerminalPaymentScenarios')]
public function testTerminalPaymentCreateRequestParams(IntegrationTester $I, Example $example): void
{
$request = new TerminalPaymentCreateRequest($example['payment']);
$I->assertEquals($example['result'], $request->toArray());
}

protected function getTerminalPaymentScenarios(): array
{
return [
'minimal payment — only required fields' => [
'payment' => (new TerminalPayment())
->setPrice(Money::ofInt(100))
->setCurr(CurrencyCode::CZK),
'result' => [
'price' => 10000,
'curr' => CurrencyCode::CZK,
],
],
'payment with refId' => [
'payment' => (new TerminalPayment())
->setPrice(Money::ofInt(50))
->setCurr(CurrencyCode::EUR)
->setRefId('order-9999'),
'result' => [
'price' => 5000,
'curr' => CurrencyCode::EUR,
'refId' => 'order-9999',
],
],
'price in cents' => [
'payment' => (new TerminalPayment())
->setPrice(Money::ofCents(150))
->setCurr(CurrencyCode::CZK),
'result' => [
'price' => 150,
'curr' => CurrencyCode::CZK,
],
],
];
}

#[Group('terminal-request')]
#[DataProvider('getTerminalRefundScenarios')]
public function testTerminalRefundCreateRequestParams(IntegrationTester $I, Example $example): void
{
$request = new TerminalRefundCreateRequest($example['refund']);
$I->assertEquals($example['result'], $request->toArray());
}

protected function getTerminalRefundScenarios(): array
{
return [
'minimal refund — only required fields' => [
'refund' => (new TerminalRefund())
->setPrice(Money::ofInt(50))
->setCurr(CurrencyCode::CZK),
'result' => [
'price' => 5000,
'curr' => CurrencyCode::CZK,
],
],
'refund with refId' => [
'refund' => (new TerminalRefund())
->setPrice(Money::ofInt(25))
->setCurr(CurrencyCode::EUR)
->setRefId('refund-order-42'),
'result' => [
'price' => 2500,
'curr' => CurrencyCode::EUR,
'refId' => 'refund-order-42',
],
],
];
}
}
Loading
Loading