Skip to content

Commit

Permalink
Merge pull request #23 from solverat/feature/22
Browse files Browse the repository at this point in the history
Allow Capture Suppression
  • Loading branch information
solverat authored Mar 6, 2023
2 parents d206c45 + 4c3b46f commit d827746
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 41 deletions.
4 changes: 2 additions & 2 deletions Action/CaptureAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private function handlePaymentPageInterface(Capture $request): void
$this->gateway->execute(new AssertPaymentPage($model));

$this->gateway->execute($status = new GetHumanStatus($model));
if ($status->isAuthorized()) {
if ($this->api->doInstantCapturing() && $status->isAuthorized()) {
$this->gateway->execute(new CaptureTransaction($model));
}
}
Expand Down Expand Up @@ -128,7 +128,7 @@ private function handleTransactionInterface(Capture $request): void
$this->gateway->execute(new AuthorizeTransaction($model));

$this->gateway->execute($status = new GetHumanStatus($model));
if ($status->isAuthorized()) {
if ($this->api->doInstantCapturing() && $status->isAuthorized()) {
$this->gateway->execute(new CaptureTransaction($model));
}
}
Expand Down
21 changes: 19 additions & 2 deletions Action/CaptureReferencedAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace Karser\PayumSaferpay\Action;

use Karser\PayumSaferpay\Api;
use Karser\PayumSaferpay\Request\Api\AuthorizeReferencedTransaction;
use Karser\PayumSaferpay\Request\Api\CaptureTransaction;
use Karser\PayumSaferpay\Request\CaptureReferenced;
use Payum\Core\Action\ActionInterface;
use Payum\Core\ApiAwareInterface;
use Payum\Core\ApiAwareTrait;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
Expand All @@ -14,10 +17,21 @@
use Payum\Core\Request\Convert;
use Payum\Core\Request\GetHumanStatus;

class CaptureReferencedAction implements ActionInterface, GatewayAwareInterface
class CaptureReferencedAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface
{
use ApiAwareTrait;
use GatewayAwareTrait;

/**
* @var Api
*/
protected $api;

public function __construct()
{
$this->apiClass = Api::class;
}

/**
* @param mixed $request
*
Expand All @@ -41,7 +55,10 @@ public function execute($request): void

try {
$this->gateway->execute(new AuthorizeReferencedTransaction($details));
$this->gateway->execute(new CaptureTransaction($details));
if ($this->api->doInstantCapturing()) {
$this->gateway->execute(new CaptureTransaction($details));
}

} finally {
$payment->setDetails($details);
}
Expand Down
19 changes: 17 additions & 2 deletions Action/NotifyAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace Karser\PayumSaferpay\Action;

use Karser\PayumSaferpay\Api;
use Karser\PayumSaferpay\Request\Api\AssertPaymentPage;
use Karser\PayumSaferpay\Request\Api\CaptureTransaction;
use Payum\Core\Action\ActionInterface;
use Payum\Core\ApiAwareInterface;
use Payum\Core\ApiAwareTrait;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
Expand All @@ -13,10 +16,21 @@
use Payum\Core\Request\GetHumanStatus;
use Payum\Core\Request\Notify;

class NotifyAction implements ActionInterface, GatewayAwareInterface
class NotifyAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface
{
use ApiAwareTrait;
use GatewayAwareTrait;

/**
* @var Api
*/
protected $api;

public function __construct()
{
$this->apiClass = Api::class;
}

/**
* @param Notify $request
*/
Expand All @@ -29,9 +43,10 @@ public function execute($request): void
$this->gateway->execute(new AssertPaymentPage($model));
$this->gateway->execute($status = new GetHumanStatus($model));

if ($status->isPending() || $status->isAuthorized()) {
if ($this->api->doInstantCapturing() && ($status->isPending() || $status->isAuthorized())) {
$this->gateway->execute(new CaptureTransaction($model));
}

throw new HttpResponse('', 204);
}

Expand Down
5 changes: 5 additions & 0 deletions Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ public function getApiEndpoint(): string
return $this->options['sandbox'] ? 'https://test.saferpay.com/api' : 'https://www.saferpay.com/api';
}

public function doInstantCapturing(): bool
{
return $this->options['instantCapturing'] === true;
}

public function getCaptureStrategy(): string
{
if (isset($this->options['interface']) && is_string($this->options['interface'])) {
Expand Down
1 change: 1 addition & 0 deletions SaferpayGatewayFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ protected function populateConfig(ArrayObject $config): void
if (false == $config['payum.api']) {
$config['payum.default_options'] = [
'sandbox' => true,
'instantCapturing' => true,
];
$config->defaults($config['payum.default_options']);
$config['payum.required_options'] = ['username', 'password', 'customerId', 'terminalId'];
Expand Down
52 changes: 44 additions & 8 deletions Tests/Functional/AbstractSaferpayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,7 @@ public function setUp(): void
->addGatewayFactory('saferpay', static function(array $config, GatewayFactoryInterface $coreGatewayFactory) {
return new SaferpayGatewayFactory($config, $coreGatewayFactory);
})
->addGateway(self::GATEWAY_NAME, [
'factory' => 'saferpay',
'username' => 'API_401860_80003225',
'password' => 'C-y*bv8346Ze5-T8',
'customerId' => '401860',
'terminalId' => '17795278',
'sandbox' => true,
]);
->addGateway(self::GATEWAY_NAME, $this->getGatewayConfig());
$payum = $builder->getPayum();

$this->payum = $payum;
Expand All @@ -88,6 +81,19 @@ public function setUp(): void
$this->client = $client;
}

protected function getGatewayConfig(): array
{
return [
'factory' => 'saferpay',
'username' => 'API_401860_80003225',
'password' => 'C-y*bv8346Ze5-T8',
'customerId' => '401860',
'terminalId' => '17795278',
'sandbox' => true,
'instantCapturing' => true
];
}

protected function submitForm(string $buttonSel, array $fieldValues = [], string $method = 'POST', array $serverParameters = []): Crawler
{
$crawler = $this->client->getCrawler();
Expand Down Expand Up @@ -241,6 +247,36 @@ protected function getThroughCheckout(string $url, array $formData, string $acti
return $this->client->getCrawler()->filter('a.btn-next')->first()->attr('href');
}

protected function createPaymentWithStatus($formData, $formBehavior, string $expectedStatus): void
{
$payment = $this->createPayment();

$token = $this->payum->getTokenFactory()->createCaptureToken(self::GATEWAY_NAME, $payment, 'done.php');
$this->payum->getHttpRequestVerifier()->invalidate($token); //no need to store token

# INIT transaction
/** @var HttpRedirect $reply */
$reply = $this->capture($token, $payment);
$this->assertStatus(GetHumanStatus::STATUS_PENDING, $payment);

#assert redirected
self::assertInstanceOf(HttpRedirect::class, $reply);
$iframeUrl = $reply->getUrl();
self::assertNotNull($iframeUrl);
self::assertStringStartsWith('https://test.saferpay.com/', $iframeUrl);

# submit form
$iframeRedirect = $this->getThroughCheckout($iframeUrl, $formData, $formBehavior);
self::assertNotNull($iframeRedirect);
self::assertStringStartsWith(self::HOST, $iframeRedirect);
self::assertStringContainsString('payum_token='.$token->getHash(), $iframeRedirect);
parse_str(parse_url($iframeRedirect, PHP_URL_QUERY) ?: '', $_GET);

# AUTHORIZE AND CAPTURE
$this->capture($token, $payment);
$this->assertStatus($expectedStatus, $payment);
}

protected function createCardAlias(array $details): CardAliasInterface
{
/** @var CardAlias $alias */
Expand Down
28 changes: 1 addition & 27 deletions Tests/Functional/TransactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Karser\PayumSaferpay\Tests\Functional;

use Payum\Core\Reply\HttpRedirect;
use Payum\Core\Request\GetHumanStatus;

class TransactionTest extends AbstractSaferpayTest
Expand Down Expand Up @@ -44,31 +43,6 @@ public function paymentStatusProvider(): array
*/
public function paymentStatus($formData, $formBehavior, string $expectedStatus): void
{
$payment = $this->createPayment();

$token = $this->payum->getTokenFactory()->createCaptureToken(self::GATEWAY_NAME, $payment, 'done.php');
$this->payum->getHttpRequestVerifier()->invalidate($token); //no need to store token

# INIT transaction
/** @var HttpRedirect $reply */
$reply = $this->capture($token, $payment);
$this->assertStatus(GetHumanStatus::STATUS_PENDING, $payment);

#assert redirected
self::assertInstanceOf(HttpRedirect::class, $reply);
$iframeUrl = $reply->getUrl();
self::assertNotNull($iframeUrl);
self::assertStringStartsWith('https://test.saferpay.com/', $iframeUrl);

# submit form
$iframeRedirect = $this->getThroughCheckout($iframeUrl, $formData, $formBehavior);
self::assertNotNull($iframeRedirect);
self::assertStringStartsWith(self::HOST, $iframeRedirect);
self::assertStringContainsString('payum_token='.$token->getHash(), $iframeRedirect);
parse_str(parse_url($iframeRedirect, PHP_URL_QUERY) ?: '', $_GET);

# AUTHORIZE AND CAPTURE
$this->capture($token, $payment);
$this->assertStatus($expectedStatus, $payment);
$this->createPaymentWithStatus($formData, $formBehavior, $expectedStatus);
}
}
40 changes: 40 additions & 0 deletions Tests/Functional/TransactionWithoutInstantCapturingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types=1);

namespace Karser\PayumSaferpay\Tests\Functional;

use Payum\Core\Request\GetHumanStatus;

class TransactionWithoutInstantCapturingTest extends AbstractSaferpayTest
{
protected function getGatewayConfig(): array
{
return array_merge(parent::getGatewayConfig(), [
'instantCapturing' => false
]);
}

public function paymentStatusWithoutInstantCapturingProvider(): array
{
return [
'success' => [
$this->composeFormData(self::CARD_SUCCESS),
$behavior = 'submit',
GetHumanStatus::STATUS_AUTHORIZED,
],
'success 3d' => [
$this->composeFormData(self::CARD_SUCCESS_LS_AUTH_3D),
$behavior = 'submit',
GetHumanStatus::STATUS_AUTHORIZED,
],
];
}

/**
* @test
* @dataProvider paymentStatusWithoutInstantCapturingProvider
*/
public function paymentWithoutInstantCapturingStatus($formData, $formBehavior, string $expectedStatus): void
{
$this->createPaymentWithStatus($formData, $formBehavior, $expectedStatus);
}
}
27 changes: 27 additions & 0 deletions Tests/Unit/ApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function setUp(): void
'customerId' => 'test',
'terminalId' => 'test',
'sandbox' => true,
'instantCapturing' => true,
);
}

Expand Down Expand Up @@ -76,6 +77,32 @@ public function shouldReturnLiveIpnEndpointIfSandboxSetFalseInConstructor(): voi
$this->assertEquals('https://www.saferpay.com/api', $api->getApiEndpoint());
}

/**
* @test
*/
public function shouldReturnInstantCapturingIfSetTrueInConstructor(): void
{
$api = new Api(
array_merge($this->options, ['instantCapturing' => true]),
$this->createHttpClientMock(),
$this->createHttpMessageFactory()
);
$this->assertEquals(true, $api->doInstantCapturing());
}

/**
* @test
*/
public function shouldNotReturnInstantCapturingIfSetFalseInConstructor(): void
{
$api = new Api(
array_merge($this->options, ['instantCapturing' => false]),
$this->createHttpClientMock(),
$this->createHttpMessageFactory()
);
$this->assertEquals(false, $api->doInstantCapturing());
}

/**
* @test
*/
Expand Down

0 comments on commit d827746

Please sign in to comment.