From fdc1420c88ce70d74973fb74c2a87bce66daae35 Mon Sep 17 00:00:00 2001 From: Francis Hilaire Date: Tue, 2 Jan 2024 11:03:19 +0100 Subject: [PATCH 1/4] Fix already canceled --- src/Action/CancelAction.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Action/CancelAction.php b/src/Action/CancelAction.php index 8931fa6..d8d6a10 100644 --- a/src/Action/CancelAction.php +++ b/src/Action/CancelAction.php @@ -26,6 +26,10 @@ public function execute($request): void return; } + if (PaymentIntent::STATUS_CANCELED === $paymentIntent->status) { + return; + } + $cancelRequest = new CancelPaymentIntent($paymentIntent->id); $this->gateway->execute($cancelRequest); From e8f336cabfbc14406908c7bf71be49c1ac82bbbc Mon Sep 17 00:00:00 2001 From: Francis Hilaire Date: Tue, 11 Jun 2024 20:08:01 +0200 Subject: [PATCH 2/4] Generic Cancel is only about PaymentIntent --- src/Action/CancelAction.php | 12 ++++++------ tests/Action/CancelActionTest.php | 28 +++++++++------------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/Action/CancelAction.php b/src/Action/CancelAction.php index d8d6a10..00e10ad 100644 --- a/src/Action/CancelAction.php +++ b/src/Action/CancelAction.php @@ -26,10 +26,6 @@ public function execute($request): void return; } - if (PaymentIntent::STATUS_CANCELED === $paymentIntent->status) { - return; - } - $cancelRequest = new CancelPaymentIntent($paymentIntent->id); $this->gateway->execute($cancelRequest); @@ -60,7 +56,11 @@ public function supports($request): bool return false; } - // if capture_method=manual it means the payment intent was created from a checkout session with authorization - return $model->offsetExists('capture_method') && $model->offsetGet('capture_method') === 'manual'; + if (!$model->offsetExists('object') || $model->offsetGet('object') !== PaymentIntent::OBJECT_NAME) { + return false; + } + + // if capture_method=manual it means the payment intent was created with authorization + return $model->offsetExists('capture_method') && $model->offsetGet('capture_method') === PaymentIntent::CAPTURE_METHOD_MANUAL; } } diff --git a/tests/Action/CancelActionTest.php b/tests/Action/CancelActionTest.php index ff5b0d4..d36dc3c 100644 --- a/tests/Action/CancelActionTest.php +++ b/tests/Action/CancelActionTest.php @@ -40,35 +40,25 @@ public function testShouldSupportOnlyCancelWithAnArrayAccessModelWithCaptureMeth { $action = new CancelAction(); - $this->assertTrue($action->supports(new Cancel(['capture_method' => 'manual']))); - $this->assertFalse($action->supports(new Cancel(['capture_method' => 'automatic']))); + $this->assertTrue($action->supports(new Cancel(['object' => PaymentIntent::OBJECT_NAME, 'capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL]))); + $this->assertFalse($action->supports(new Cancel(['object' => PaymentIntent::OBJECT_NAME, 'capture_method' => PaymentIntent::CAPTURE_METHOD_AUTOMATIC]))); $this->assertFalse($action->supports(new Cancel([]))); $this->assertFalse($action->supports(new Cancel(null))); - $this->assertFalse($action->supports(new Authorize(['capture_method' => 'manual']))); + $this->assertFalse($action->supports(new Authorize(['capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL]))); } public function testShouldDoNothingWhenRequiredModelInfoAreNotAvailable(): void { $action = new CancelAction(); - $model = ['capture_method' => 'manual']; + $model = ['capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL]; $request = new Cancel($model); $supports = $action->supports($request); - $this->assertTrue($supports); - $action->execute($request); + $this->assertFalse($supports); $model = [ 'object' => PaymentIntent::OBJECT_NAME, - 'capture_method' => 'manual', - ]; - $request = new Cancel($model); - $supports = $action->supports($request); - $this->assertTrue($supports); - $action->execute($request); - - $model = [ - 'object' => SetupIntent::OBJECT_NAME, - 'capture_method' => 'manual', + 'capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL, ]; $request = new Cancel($model); $supports = $action->supports($request); @@ -78,7 +68,7 @@ public function testShouldDoNothingWhenRequiredModelInfoAreNotAvailable(): void $model = [ 'object' => PaymentIntent::OBJECT_NAME, 'id' => '', - 'capture_method' => 'manual', + 'capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL, ]; $request = new Cancel($model); $supports = $action->supports($request); @@ -93,7 +83,7 @@ public function testShouldThrowAnExceptionWhenNoTokenIsProvided(): void $model = [ 'object' => PaymentIntent::OBJECT_NAME, 'id' => 'pi_0000', - 'capture_method' => 'manual', + 'capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL, ]; $request = new Cancel($model); @@ -110,7 +100,7 @@ public function testShouldCancelThePaymentIntent(): void $model = [ 'object' => PaymentIntent::OBJECT_NAME, 'id' => 'pi_0000', - 'capture_method' => 'manual', + 'capture_method' => PaymentIntent::CAPTURE_METHOD_MANUAL, ]; $token = new Token(); From 224ad1c61e3e88461e1a458cf6f1d4b1f6b5a51a Mon Sep 17 00:00:00 2001 From: Francis Hilaire Date: Tue, 11 Jun 2024 20:09:58 +0200 Subject: [PATCH 3/4] Use legacy payment intent cancelation --- src/Action/StripeCheckoutSession/CancelAction.php | 1 - src/Action/StripeCheckoutSession/LegacyCancelAction.php | 2 +- src/StripeCheckoutSessionGatewayFactory.php | 4 +++- tests/StripeGatewayFactoryTest.php | 4 +++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Action/StripeCheckoutSession/CancelAction.php b/src/Action/StripeCheckoutSession/CancelAction.php index dbee5b1..bc2a686 100644 --- a/src/Action/StripeCheckoutSession/CancelAction.php +++ b/src/Action/StripeCheckoutSession/CancelAction.php @@ -6,7 +6,6 @@ use ArrayAccess; use FluxSE\PayumStripe\Request\Api\Resource\ExpireSession; -use FluxSE\PayumStripe\Request\Api\Resource\RetrieveSession; use Payum\Core\Action\ActionInterface; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; diff --git a/src/Action/StripeCheckoutSession/LegacyCancelAction.php b/src/Action/StripeCheckoutSession/LegacyCancelAction.php index 0fa8b84..fe4b36f 100644 --- a/src/Action/StripeCheckoutSession/LegacyCancelAction.php +++ b/src/Action/StripeCheckoutSession/LegacyCancelAction.php @@ -68,6 +68,6 @@ public function supports($request): bool } // if capture_method=automatic it means the payment intent was created from a checkout session without authorization - return $model->offsetExists('capture_method') && $model->offsetGet('capture_method') === 'automatic'; + return $model->offsetExists('capture_method') && $model->offsetGet('capture_method') === PaymentIntent::CAPTURE_METHOD_AUTOMATIC; } } diff --git a/src/StripeCheckoutSessionGatewayFactory.php b/src/StripeCheckoutSessionGatewayFactory.php index acf7bb4..771a7f0 100644 --- a/src/StripeCheckoutSessionGatewayFactory.php +++ b/src/StripeCheckoutSessionGatewayFactory.php @@ -12,6 +12,7 @@ use FluxSE\PayumStripe\Action\StripeCheckoutSession\CancelAction; use FluxSE\PayumStripe\Action\StripeCheckoutSession\CaptureAction; use FluxSE\PayumStripe\Action\StripeCheckoutSession\ConvertPaymentAction; +use FluxSE\PayumStripe\Action\StripeCheckoutSession\LegacyCancelAction; use FluxSE\PayumStripe\Api\KeysAwareInterface; use FluxSE\PayumStripe\Api\StripeCheckoutSessionApi; use FluxSE\PayumStripe\Api\StripeCheckoutSessionApiInterface; @@ -39,7 +40,8 @@ protected function populateConfig(ArrayObject $config): void 'payum.action.authorize' => new AuthorizeAction(), 'payum.action.convert_payment' => new ConvertPaymentAction(), 'payum.action.redirect_to_checkout' => new RedirectToCheckoutAction(), - 'payum.action.cancel.payment_intent.automatic' => new CancelAction(), + 'payum.action.cancel.payment_intent.automatic' => new LegacyCancelAction(), + 'payum.action.cancel.checkout_session' => new CancelAction(), // Extensions 'payum.extension.after_capture_cancel_payment_intent' => new CancelUrlCancelPaymentIntentExtension(), diff --git a/tests/StripeGatewayFactoryTest.php b/tests/StripeGatewayFactoryTest.php index 1b07b13..bcea920 100644 --- a/tests/StripeGatewayFactoryTest.php +++ b/tests/StripeGatewayFactoryTest.php @@ -221,7 +221,9 @@ public function testConfigurationForCheckoutSession(): void $this->assertArrayHasKey('payum.action.redirect_to_checkout', $actualActions); $this->assertEquals(new StripeCheckoutSession\Api\RedirectToCheckoutAction(), $actualActions['payum.action.redirect_to_checkout']); $this->assertArrayHasKey('payum.action.cancel.payment_intent.automatic', $actualActions); - $this->assertEquals(new StripeCheckoutSession\CancelAction(), $actualActions['payum.action.cancel.payment_intent.automatic']); + $this->assertEquals(new StripeCheckoutSession\LegacyCancelAction(), $actualActions['payum.action.cancel.payment_intent.automatic']); + $this->assertArrayHasKey('payum.action.cancel.checkout_session', $actualActions); + $this->assertEquals(new StripeCheckoutSession\CancelAction(), $actualActions['payum.action.cancel.checkout_session']); $api = $config['payum.api'](ArrayObject::ensureArrayObject($config)); $this->assertInstanceOf(StripeCheckoutSessionApi::class, $api); From d135928bff38947da0a1682669398af38f31731d Mon Sep 17 00:00:00 2001 From: Francis Hilaire Date: Tue, 11 Jun 2024 20:10:23 +0200 Subject: [PATCH 4/4] Use the constant available inside PaymentIntent class --- .../Api/WebhookEvent/AuthorizedPaymentIntentCanceledAction.php | 3 ++- .../AuthorizedPaymentIntentManuallyCanceledAction.php | 3 ++- .../WebhookEvent/AuthorizedPaymentIntentSucceededAction.php | 3 ++- src/Action/Api/WebhookEvent/PaymentIntentCanceledAction.php | 3 ++- .../WebhookEvent/PaymentIntentCanceledFromAuthorizeAction.php | 3 ++- src/Action/Api/WebhookEvent/PaymentIntentSucceededAction.php | 3 ++- .../WebhookEvent/PaymentIntentSucceededFromAuthorizeAction.php | 3 ++- src/Action/StripeCheckoutSession/AuthorizeAction.php | 3 ++- src/Action/StripeJs/AuthorizeAction.php | 3 ++- 9 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentCanceledAction.php b/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentCanceledAction.php index fa36db5..9cfca25 100644 --- a/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentCanceledAction.php +++ b/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentCanceledAction.php @@ -6,6 +6,7 @@ use FluxSE\PayumStripe\Token\TokenHashKeysInterface; use Stripe\Event; +use Stripe\PaymentIntent; final class AuthorizedPaymentIntentCanceledAction extends AbstractPaymentIntentAction { @@ -18,7 +19,7 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'manual'; + return PaymentIntent::CAPTURE_METHOD_MANUAL; } public function getTokenHashMetadataKeyName(): string diff --git a/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentManuallyCanceledAction.php b/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentManuallyCanceledAction.php index 448998e..ad3dd43 100644 --- a/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentManuallyCanceledAction.php +++ b/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentManuallyCanceledAction.php @@ -6,6 +6,7 @@ use FluxSE\PayumStripe\Token\TokenHashKeysInterface; use Stripe\Event; +use Stripe\PaymentIntent; final class AuthorizedPaymentIntentManuallyCanceledAction extends AbstractPaymentIntentAction { @@ -18,7 +19,7 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'manual'; + return PaymentIntent::CAPTURE_METHOD_MANUAL; } public function getTokenHashMetadataKeyName(): string diff --git a/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentSucceededAction.php b/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentSucceededAction.php index 4e4a767..67b0f2d 100644 --- a/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentSucceededAction.php +++ b/src/Action/Api/WebhookEvent/AuthorizedPaymentIntentSucceededAction.php @@ -6,6 +6,7 @@ use FluxSE\PayumStripe\Token\TokenHashKeysInterface; use Stripe\Event; +use Stripe\PaymentIntent; final class AuthorizedPaymentIntentSucceededAction extends AbstractPaymentIntentAction { @@ -18,7 +19,7 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'manual'; + return PaymentIntent::CAPTURE_METHOD_MANUAL; } public function getTokenHashMetadataKeyName(): string diff --git a/src/Action/Api/WebhookEvent/PaymentIntentCanceledAction.php b/src/Action/Api/WebhookEvent/PaymentIntentCanceledAction.php index 89664ba..6c2c6f3 100644 --- a/src/Action/Api/WebhookEvent/PaymentIntentCanceledAction.php +++ b/src/Action/Api/WebhookEvent/PaymentIntentCanceledAction.php @@ -5,6 +5,7 @@ namespace FluxSE\PayumStripe\Action\Api\WebhookEvent; use Stripe\Event; +use Stripe\PaymentIntent; final class PaymentIntentCanceledAction extends AbstractPaymentIntentAction { @@ -17,6 +18,6 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'automatic'; + return PaymentIntent::CAPTURE_METHOD_AUTOMATIC; } } diff --git a/src/Action/Api/WebhookEvent/PaymentIntentCanceledFromAuthorizeAction.php b/src/Action/Api/WebhookEvent/PaymentIntentCanceledFromAuthorizeAction.php index 00c0f30..94eec8d 100644 --- a/src/Action/Api/WebhookEvent/PaymentIntentCanceledFromAuthorizeAction.php +++ b/src/Action/Api/WebhookEvent/PaymentIntentCanceledFromAuthorizeAction.php @@ -5,6 +5,7 @@ namespace FluxSE\PayumStripe\Action\Api\WebhookEvent; use Stripe\Event; +use Stripe\PaymentIntent; final class PaymentIntentCanceledFromAuthorizeAction extends AbstractPaymentIntentAction { @@ -17,6 +18,6 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'manual'; + return PaymentIntent::CAPTURE_METHOD_MANUAL; } } diff --git a/src/Action/Api/WebhookEvent/PaymentIntentSucceededAction.php b/src/Action/Api/WebhookEvent/PaymentIntentSucceededAction.php index a2f7f69..c91af85 100644 --- a/src/Action/Api/WebhookEvent/PaymentIntentSucceededAction.php +++ b/src/Action/Api/WebhookEvent/PaymentIntentSucceededAction.php @@ -5,6 +5,7 @@ namespace FluxSE\PayumStripe\Action\Api\WebhookEvent; use Stripe\Event; +use Stripe\PaymentIntent; final class PaymentIntentSucceededAction extends AbstractPaymentIntentAction { @@ -17,6 +18,6 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'automatic'; + return PaymentIntent::CAPTURE_METHOD_AUTOMATIC; } } diff --git a/src/Action/Api/WebhookEvent/PaymentIntentSucceededFromAuthorizeAction.php b/src/Action/Api/WebhookEvent/PaymentIntentSucceededFromAuthorizeAction.php index c313a3d..cf1172e 100644 --- a/src/Action/Api/WebhookEvent/PaymentIntentSucceededFromAuthorizeAction.php +++ b/src/Action/Api/WebhookEvent/PaymentIntentSucceededFromAuthorizeAction.php @@ -5,6 +5,7 @@ namespace FluxSE\PayumStripe\Action\Api\WebhookEvent; use Stripe\Event; +use Stripe\PaymentIntent; final class PaymentIntentSucceededFromAuthorizeAction extends AbstractPaymentIntentAction { @@ -17,6 +18,6 @@ protected function getSupportedEventTypes(): array protected function getSupportedCaptureMethod(): string { - return 'manual'; + return PaymentIntent::CAPTURE_METHOD_MANUAL; } } diff --git a/src/Action/StripeCheckoutSession/AuthorizeAction.php b/src/Action/StripeCheckoutSession/AuthorizeAction.php index b9deee5..5357e35 100644 --- a/src/Action/StripeCheckoutSession/AuthorizeAction.php +++ b/src/Action/StripeCheckoutSession/AuthorizeAction.php @@ -10,6 +10,7 @@ use Payum\Core\Request\Authorize; use Payum\Core\Request\Generic; use Payum\Core\Security\TokenInterface; +use Stripe\PaymentIntent; /** * For more information about Stripe Authorize payments :. @@ -34,7 +35,7 @@ public function embedOnModeData(ArrayObject $model, TokenInterface $token, strin /** @var array $embeddedModeData */ $embeddedModeData = $model->offsetGet($modeDataKey); - $embeddedModeData['capture_method'] = 'manual'; + $embeddedModeData['capture_method'] = PaymentIntent::CAPTURE_METHOD_MANUAL; $model->offsetSet($modeDataKey, $embeddedModeData); } diff --git a/src/Action/StripeJs/AuthorizeAction.php b/src/Action/StripeJs/AuthorizeAction.php index 35482db..1ae2cf6 100644 --- a/src/Action/StripeJs/AuthorizeAction.php +++ b/src/Action/StripeJs/AuthorizeAction.php @@ -9,6 +9,7 @@ use Payum\Core\Request\Authorize; use Payum\Core\Request\Generic; use Payum\Core\Security\TokenInterface; +use Stripe\PaymentIntent; /** * For more information about Stripe Authorize payments :. @@ -19,7 +20,7 @@ final class AuthorizeAction extends CaptureAction { public function embedNotifyTokenHash(ArrayObject $model, Generic $request): TokenInterface { - $model->offsetSet('capture_method', 'manual'); + $model->offsetSet('capture_method', PaymentIntent::CAPTURE_METHOD_MANUAL); return parent::embedNotifyTokenHash($model, $request); }