Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPP: Add order meta upon the AuthenticationRequired state #7540

Merged
merged 5 commits into from
Oct 25, 2023
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
5 changes: 5 additions & 0 deletions changelog/rpp-authentication-state-meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: Storing the metadata, that was forgotten in 7471


1 change: 1 addition & 0 deletions src/Internal/Payment/State/InitialState.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}

Expand Down
28 changes: 28 additions & 0 deletions src/Internal/Service/OrderService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
'',
$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
*
Expand Down
16 changes: 15 additions & 1 deletion tests/unit/src/Internal/Payment/State/InitialStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -175,22 +176,35 @@ 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 );

// 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( WC_Helper_Intention::create_intention( [ 'status' => Intent_Status::REQUIRES_ACTION ] ) );
->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 );
$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, $mock_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 );
}
Expand Down
47 changes: 47 additions & 0 deletions tests/unit/src/Internal/Service/OrderServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 ],
Expand Down
Loading