diff --git a/Action/CaptureAction.php b/Action/CaptureAction.php index 86429d9..3e0bafe 100644 --- a/Action/CaptureAction.php +++ b/Action/CaptureAction.php @@ -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)); } } @@ -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)); } } diff --git a/Action/CaptureReferencedAction.php b/Action/CaptureReferencedAction.php index 0c2f5ab..48ee8fa 100644 --- a/Action/CaptureReferencedAction.php +++ b/Action/CaptureReferencedAction.php @@ -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; @@ -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 * @@ -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); } diff --git a/Action/NotifyAction.php b/Action/NotifyAction.php index da43455..a562de8 100644 --- a/Action/NotifyAction.php +++ b/Action/NotifyAction.php @@ -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; @@ -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 */ @@ -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); } diff --git a/Api.php b/Api.php index 7a86cbd..4fdeef6 100644 --- a/Api.php +++ b/Api.php @@ -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'])) { diff --git a/SaferpayGatewayFactory.php b/SaferpayGatewayFactory.php index babca62..3758295 100644 --- a/SaferpayGatewayFactory.php +++ b/SaferpayGatewayFactory.php @@ -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']; diff --git a/Tests/Functional/AbstractSaferpayTest.php b/Tests/Functional/AbstractSaferpayTest.php index 027f5f7..e9958e9 100644 --- a/Tests/Functional/AbstractSaferpayTest.php +++ b/Tests/Functional/AbstractSaferpayTest.php @@ -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; @@ -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(); @@ -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 */ diff --git a/Tests/Functional/TransactionTest.php b/Tests/Functional/TransactionTest.php index 2ba4da2..481c3f5 100644 --- a/Tests/Functional/TransactionTest.php +++ b/Tests/Functional/TransactionTest.php @@ -2,7 +2,6 @@ namespace Karser\PayumSaferpay\Tests\Functional; -use Payum\Core\Reply\HttpRedirect; use Payum\Core\Request\GetHumanStatus; class TransactionTest extends AbstractSaferpayTest @@ -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); } } diff --git a/Tests/Functional/TransactionWithoutInstantCapturingTest.php b/Tests/Functional/TransactionWithoutInstantCapturingTest.php new file mode 100644 index 0000000..715f20d --- /dev/null +++ b/Tests/Functional/TransactionWithoutInstantCapturingTest.php @@ -0,0 +1,40 @@ + 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); + } +} diff --git a/Tests/Unit/ApiTest.php b/Tests/Unit/ApiTest.php index 467eb7e..7bcb83a 100644 --- a/Tests/Unit/ApiTest.php +++ b/Tests/Unit/ApiTest.php @@ -27,6 +27,7 @@ public function setUp(): void 'customerId' => 'test', 'terminalId' => 'test', 'sandbox' => true, + 'instantCapturing' => true, ); } @@ -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 */