From 9be8dd795ec1b7f094a5a002204562bf2e0a7324 Mon Sep 17 00:00:00 2001 From: Radoslav Georgiev Date: Tue, 24 Oct 2023 11:22:39 +0300 Subject: [PATCH 1/5] Adding the initial test --- src/Internal/Payment/State/InitialState.php | 1 + src/Internal/Service/OrderService.php | 28 +++++++++++ .../src/Internal/Service/OrderServiceTest.php | 47 +++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/src/Internal/Payment/State/InitialState.php b/src/Internal/Payment/State/InitialState.php index 7e3311d6819..87b59eec817 100644 --- a/src/Internal/Payment/State/InitialState.php +++ b/src/Internal/Payment/State/InitialState.php @@ -106,6 +106,7 @@ public function start_processing( PaymentRequest $request ) { // Intent requires authorization (3DS check). if ( Intent_Status::REQUIRES_ACTION === $intent->get_status() ) { + $this->order_service->update_order_from_intent_that_requires_action( $context->get_order_id(), $intent, $context ); return $this->create_state( AuthenticationRequiredState::class ); } diff --git a/src/Internal/Service/OrderService.php b/src/Internal/Service/OrderService.php index ca7b3ee9083..032090efcb3 100644 --- a/src/Internal/Service/OrderService.php +++ b/src/Internal/Service/OrderService.php @@ -213,6 +213,34 @@ public function update_order_from_successful_intent( } } + /** + * Updates the order with the necessary details whenever an intent requires action. + * + * @param int $order_id ID of the order. + * @param WC_Payments_API_Abstract_Intention $intent Remote object. To be abstracted soon. + * @param PaymentContext $context Context for the payment. + * @throws Order_Not_Found_Exception + */ + public function update_order_from_intent_that_requires_action( + int $order_id, + WC_Payments_API_Abstract_Intention $intent, + PaymentContext $context + ) { + $order = $this->get_order( $order_id ); + + $this->legacy_service->attach_intent_info_to_order( + $order, + $intent->get_id(), + $intent->get_status(), + $context->get_payment_method()->get_id(), + $context->get_customer_id(), + null, + $context->get_currency() + ); + + $this->legacy_service->update_order_status_from_intent( $order, $intent ); + } + /** * Given the charge data, checks if there was an exchange and adds it to the given order as metadata * diff --git a/tests/unit/src/Internal/Service/OrderServiceTest.php b/tests/unit/src/Internal/Service/OrderServiceTest.php index 362cb725fa9..168de422bf8 100644 --- a/tests/unit/src/Internal/Service/OrderServiceTest.php +++ b/tests/unit/src/Internal/Service/OrderServiceTest.php @@ -385,6 +385,53 @@ public function test_update_order_from_successful_intent( $intent ) { $this->sut->update_order_from_successful_intent( $this->order_id, $intent, $mock_context ); } + /** + * Test for the `update_order_from_intent_that_requires_action` method. + */ + public function test_update_order_from_intent_that_requires_action() { + $intent_id = 'pi_XYZ'; + $intent_status = 'success'; + $customer_id = 'cus_XYZ'; + $currency = 'usd'; + $payment_method_id = 'pm_XYZ'; + + // Prepare the context, and all needed getters. + $mock_context = $this->createMock( PaymentContext::class ); + $mock_context->expects( $this->once() )->method( 'get_payment_method' )->willReturn( new NewPaymentMethod( $payment_method_id ) ); + $mock_context->expects( $this->once() )->method( 'get_customer_id' )->willReturn( $customer_id ); + $mock_context->expects( $this->once() )->method( 'get_currency' )->willReturn( $currency ); + + // Create a mock order that will be used, and return it. + $mock_order = $this->createMock( WC_Order::class ); + $this->sut->expects( $this->once() ) + ->method( 'get_order' ) + ->with( $this->order_id ) + ->willReturn( $mock_order ); + + // Prepare the intent, and all expected getters. + $mock_intent = $this->createMock( WC_Payments_API_Payment_Intention::class ); + $mock_intent->expects( $this->once() )->method( 'get_id' )->willReturn( $intent_id ); + $mock_intent->expects( $this->once() )->method( 'get_status' )->willReturn( $intent_status ); + + $this->mock_legacy_service->expects( $this->once() ) + ->method( 'attach_intent_info_to_order' ) + ->with( + $mock_order, + $intent_id, + $intent_status, + $payment_method_id, + $customer_id, + null, + $currency + ); + + $this->mock_legacy_service->expects( $this->once() ) + ->method( 'update_order_status_from_intent' ) + ->with( $mock_order, $mock_intent ); + + $this->sut->update_order_from_intent_that_requires_action( $this->order_id, $mock_intent, $mock_context ); + } + public function provider_attach_exchange_info_to_order() { return [ 'Different store and account currencies' => [ 'USD', 'USD', 'EUR', null, null ], From a616e8a8c594f517051624c5e49dbde535ff4b27 Mon Sep 17 00:00:00 2001 From: Radoslav Georgiev Date: Tue, 24 Oct 2023 11:37:32 +0300 Subject: [PATCH 2/5] Fixing the existing test --- .../src/Internal/Payment/State/InitialStateTest.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/unit/src/Internal/Payment/State/InitialStateTest.php b/tests/unit/src/Internal/Payment/State/InitialStateTest.php index 74687a167e6..b804a887552 100644 --- a/tests/unit/src/Internal/Payment/State/InitialStateTest.php +++ b/tests/unit/src/Internal/Payment/State/InitialStateTest.php @@ -175,22 +175,33 @@ public function test_start_processing_will_transition_to_error_state_when_api_ex } public function test_processing_will_transition_to_auth_required_state() { + $order_id = 123; $mock_request = $this->createMock( PaymentRequest::class ); $mock_auth_state = $this->createMock( AuthenticationRequiredState::class ); + $intent = WC_Helper_Intention::create_intention( [ 'status' => Intent_Status::REQUIRES_ACTION ] ); $this->mock_payment_request_service->expects( $this->once() ) ->method( 'create_intent' ) ->with( $this->mock_context ) - ->willReturn( WC_Helper_Intention::create_intention( [ 'status' => Intent_Status::REQUIRES_ACTION ] ) ); + ->willReturn( $intent ); // Let's mock these services in order to prevent real execution of them. $this->mocked_sut->expects( $this->once() )->method( 'populate_context_from_request' )->with( $mock_request ); $this->mocked_sut->expects( $this->once() )->method( 'populate_context_from_order' ); + // Before the transition, the order service should update the order. + $this->mock_context->expects( $this->once() ) + ->method( 'get_order_id' ) + ->willReturn( $order_id ); + $this->mock_order_service->expects( $this->once() ) + ->method( 'update_order_from_intent_that_requires_action' ) + ->with( $order_id, $intent, $this->mock_context ); + $this->mock_state_factory->expects( $this->once() ) ->method( 'create_state' ) ->with( AuthenticationRequiredState::class, $this->mock_context ) ->willReturn( $mock_auth_state ); + $result = $this->mocked_sut->start_processing( $mock_request ); $this->assertSame( $mock_auth_state, $result ); } From 5fad8238a0939e32dfbbaaa3b63cb5f56f7c17d6 Mon Sep 17 00:00:00 2001 From: Radoslav Georgiev Date: Tue, 24 Oct 2023 11:40:25 +0300 Subject: [PATCH 3/5] Using a mock intent --- .../unit/src/Internal/Payment/State/InitialStateTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/unit/src/Internal/Payment/State/InitialStateTest.php b/tests/unit/src/Internal/Payment/State/InitialStateTest.php index b804a887552..f0df9ce0833 100644 --- a/tests/unit/src/Internal/Payment/State/InitialStateTest.php +++ b/tests/unit/src/Internal/Payment/State/InitialStateTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit_Utils; use WC_Order; +use WC_Payments_API_Payment_Intention; use WC_Payments_Customer_Service; use WCPay\Core\Exceptions\Server\Request\Invalid_Request_Parameter_Exception; use WCPay\Internal\Payment\State\InitialState; @@ -179,11 +180,13 @@ public function test_processing_will_transition_to_auth_required_state() { $mock_request = $this->createMock( PaymentRequest::class ); $mock_auth_state = $this->createMock( AuthenticationRequiredState::class ); - $intent = WC_Helper_Intention::create_intention( [ 'status' => Intent_Status::REQUIRES_ACTION ] ); + // Create an intent, and make sure it will be returned by the service. + $mock_intent = $this->createMock( WC_Payments_API_Payment_Intention::class ); + $mock_intent->expects( $this->once() )->method( 'get_status' )->willReturn( Intent_Status::REQUIRES_ACTION ); $this->mock_payment_request_service->expects( $this->once() ) ->method( 'create_intent' ) ->with( $this->mock_context ) - ->willReturn( $intent ); + ->willReturn( $mock_intent ); // Let's mock these services in order to prevent real execution of them. $this->mocked_sut->expects( $this->once() )->method( 'populate_context_from_request' )->with( $mock_request ); @@ -195,7 +198,7 @@ public function test_processing_will_transition_to_auth_required_state() { ->willReturn( $order_id ); $this->mock_order_service->expects( $this->once() ) ->method( 'update_order_from_intent_that_requires_action' ) - ->with( $order_id, $intent, $this->mock_context ); + ->with( $order_id, $mock_intent, $this->mock_context ); $this->mock_state_factory->expects( $this->once() ) ->method( 'create_state' ) From bdaa588e6899fe5c37e19bbde5f1b86534d83a7f Mon Sep 17 00:00:00 2001 From: Radoslav Georgiev Date: Wed, 25 Oct 2023 18:14:46 +0300 Subject: [PATCH 4/5] Fixing the psalm error --- src/Internal/Service/OrderService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Internal/Service/OrderService.php b/src/Internal/Service/OrderService.php index 032090efcb3..457cd9a0176 100644 --- a/src/Internal/Service/OrderService.php +++ b/src/Internal/Service/OrderService.php @@ -234,7 +234,7 @@ public function update_order_from_intent_that_requires_action( $intent->get_status(), $context->get_payment_method()->get_id(), $context->get_customer_id(), - null, + '', $context->get_currency() ); From 50b3902247993dd762c42d69c4848d342eb0b3af Mon Sep 17 00:00:00 2001 From: Radoslav Georgiev Date: Wed, 25 Oct 2023 18:15:39 +0300 Subject: [PATCH 5/5] Changelog entry --- changelog/rpp-authentication-state-meta | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/rpp-authentication-state-meta diff --git a/changelog/rpp-authentication-state-meta b/changelog/rpp-authentication-state-meta new file mode 100644 index 00000000000..b35cdfbeb63 --- /dev/null +++ b/changelog/rpp-authentication-state-meta @@ -0,0 +1,5 @@ +Significance: patch +Type: dev +Comment: Storing the metadata, that was forgotten in 7471 + +