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

Add client data to the compatibility service #9714

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
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
42 changes: 38 additions & 4 deletions includes/class-compatibility-service.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use WC_Payments;
use WC_Payments_API_Client;
use WCPay\Exceptions\API_Exception;
use WC_Payments_Session_Service;

defined( 'ABSPATH' ) || exit; // block direct access.

Expand All @@ -26,13 +26,25 @@ class Compatibility_Service {
*/
private $payments_api_client;

/**
* Session service.
*
* @var WC_Payments_Session_Service instance for working with session information
*/
private $session_service;

/**
* Constructor for Compatibility_Service.
*
* @param WC_Payments_API_Client $payments_api_client WooCommerce Payments API client.
* @param WC_Payments_API_Client $payments_api_client WooCommerce Payments API client.
* @param WC_Payments_Session_Service $session_service Session service.
*/
public function __construct( WC_Payments_API_Client $payments_api_client ) {
public function __construct(
WC_Payments_API_Client $payments_api_client,
WC_Payments_Session_Service $session_service
) {
$this->payments_api_client = $payments_api_client;
$this->session_service = $session_service;
}

/**
Expand Down Expand Up @@ -62,7 +74,16 @@ public function update_compatibility_data() {
* @return void
*/
public function update_compatibility_data_hook() {
$this->payments_api_client->update_compatibility_data( $this->get_compatibility_data() );
$compatibility_data = array_merge(
$this->get_compatibility_data(),
[
'sift_session_id' => $this->session_service->get_sift_session_id(),
'ip_address' => \WC_Geolocation::get_ip_address(),
'browser' => self::get_browser_info(),
],
);

$this->payments_api_client->update_compatibility_data( $compatibility_data );
}

/**
Expand All @@ -77,6 +98,19 @@ public function add_compatibility_onboarding_data( $args ): array {
return $args;
}

/**
* Gets the browser info.
*
* @return array
*/
public static function get_browser_info() {
return [
'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? wc_clean( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '',
'accept_language' => isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? wc_clean( wp_unslash( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) : '',
'content_language' => empty( get_user_locale() ) ? 'en-US' : str_replace( '_', '-', get_user_locale() ),
];
}

/**
* Gets the compatibility data.
*
Expand Down
21 changes: 19 additions & 2 deletions includes/class-wc-payments-customer-service.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* @package WooCommerce\Payments
*/

use WCPay\Compatibility_Service;
use WCPay\Database_Cache;
use WCPay\Exceptions\API_Exception;
use WCPay\Logger;
Expand Down Expand Up @@ -152,8 +153,7 @@ public function get_customer_id_by_user_id( $user_id ) {
* @throws API_Exception Error creating customer.
*/
public function create_customer_for_user( ?WP_User $user, array $customer_data = [] ): string {
// Include the session ID for the user.
$customer_data['session_id'] = $this->session_service->get_sift_session_id() ?? null;
$customer_data = $this->append_client_data_to_customer( $customer_data );

// Create a customer on the WCPay server.
$customer_id = $this->payments_api_client->create_customer( $customer_data );
Expand Down Expand Up @@ -204,6 +204,8 @@ public function get_or_create_customer_id_from_order( ?int $user_id, WC_Order $o
* @throws API_Exception Error updating the customer.
*/
public function update_customer_for_user( string $customer_id, ?WP_User $user, array $customer_data ): string {
$customer_data = $this->append_client_data_to_customer( $customer_data );

try {
// Update the customer on the WCPay server.
$this->payments_api_client->update_customer(
Expand Down Expand Up @@ -572,4 +574,19 @@ public function get_prepared_customer_data() {
'address' => $address,
];
}

/**
* Appends client data to the customer array.
*
* @param array $customer_data The customer data.
*
* @return array The customer data with client data appended.
*/
private function append_client_data_to_customer( array $customer_data ) {
$customer_data['session_id'] = $this->session_service->get_sift_session_id() ?? null;
$customer_data['ip_address'] = \WC_Geolocation::get_ip_address();
$customer_data['browser'] = Compatibility_Service::get_browser_info();

return $customer_data;
}
}
4 changes: 2 additions & 2 deletions includes/class-wc-payments.php
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,9 @@ public static function init() {
include_once WCPAY_ABSPATH . 'includes/class-woopay-tracker.php';

self::$order_service = new WC_Payments_Order_Service( self::$api_client );
self::$compatibility_service = new Compatibility_Service( self::$api_client );
self::$action_scheduler_service = new WC_Payments_Action_Scheduler_Service( self::$api_client, self::$order_service, self::$compatibility_service );
self::$session_service = new WC_Payments_Session_Service( self::$api_client );
self::$compatibility_service = new Compatibility_Service( self::$api_client, self::$session_service );
self::$action_scheduler_service = new WC_Payments_Action_Scheduler_Service( self::$api_client, self::$order_service, self::$compatibility_service );
self::$redirect_service = new WC_Payments_Redirect_Service( self::$api_client );
self::$onboarding_service = new WC_Payments_Onboarding_Service( self::$api_client, self::$database_cache, self::$session_service );
self::$account = new WC_Payments_Account( self::$api_client, self::$database_cache, self::$action_scheduler_service, self::$onboarding_service, self::$redirect_service );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public function set_up() {
$order_service = new WC_Payments_Order_Service( $this->mock_api_client );
$customer_service = new WC_Payments_Customer_Service( $this->mock_api_client, $this->mock_wcpay_account, $this->mock_db_cache, $this->mock_session_service, $order_service );
$token_service = new WC_Payments_Token_Service( $this->mock_api_client, $customer_service );
$compatibility_service = new Compatibility_Service( $this->mock_api_client );
$compatibility_service = new Compatibility_Service( $this->mock_api_client, $this->mock_session_service );
$action_scheduler_service = new WC_Payments_Action_Scheduler_Service( $this->mock_api_client, $order_service, $compatibility_service );
$mock_rate_limiter = $this->createMock( Session_Rate_Limiter::class );
$mock_dpps = $this->createMock( Duplicate_Payment_Prevention_Service::class );
Expand Down
47 changes: 44 additions & 3 deletions tests/unit/test-class-compatibility-service.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class Compatibility_Service_Test extends WCPAY_UnitTestCase {
*/
private $mock_api_client;

/**
* Mock WC_Payments_Session_Service.
*
* @var WC_Payments_Session_Service|MockObject
*/
private $mock_session_service;

/**
* Compatibility_Service.
*
Expand Down Expand Up @@ -69,7 +76,8 @@ public function set_up() {
parent::set_up();

$this->mock_api_client = $this->createMock( WC_Payments_API_Client::class );
$this->compatibility_service = new Compatibility_Service( $this->mock_api_client );
$this->mock_session_service = $this->createMock( WC_Payments_Session_Service::class );
$this->compatibility_service = new Compatibility_Service( $this->mock_api_client, $this->mock_session_service );
$this->compatibility_service->init_hooks();

$this->add_stylesheet_filter();
Expand Down Expand Up @@ -167,7 +175,7 @@ public function test_update_compatibility_data_adds_a_single_scheduled_job() {

public function test_update_compatibility_data_hook_active_plugins_false() {
// Arrange: Create the expected value to be passed to update_compatibility_data.
$expected = $this->get_mock_compatibility_data(
$expected = $this->get_mock_compatibility_hook_data(
[
'active_plugins' => [],
]
Expand Down Expand Up @@ -196,7 +204,7 @@ public function test_update_compatibility_data_hook_active_plugins_false() {
*/
public function test_update_compatibility_data_hook_permalinks_not_set( $page_name ) {
// Arrange: Create the expected value to be passed to update_compatibility_data.
$expected = $this->get_mock_compatibility_data(
$expected = $this->get_mock_compatibility_hook_data(
[
'woocommerce_' . $page_name => 'Not set',
]
Expand Down Expand Up @@ -255,6 +263,39 @@ private function get_mock_compatibility_data( array $args = [] ): array {
);
}

/**
* Returns the mock compatibility hook data.
*
* @param array $args If any values need to be overridden, the values can be added here.
*
* @return array
*/
private function get_mock_compatibility_hook_data( array $args = [] ): array {
wp_set_current_user( 1 );
wp_get_current_user()->locale = 'en-US';

$_SERVER['HTTP_USER_AGENT'] = 'Unit Test Agent/0.1.0';
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US';

$this->mock_session_service
->method( 'get_sift_session_id' )
->willReturn( '12345' );

return array_merge(
$this->get_mock_compatibility_data(),
[
'sift_session_id' => '12345',
'ip_address' => '127.0.0.1',
'browser' => [
'user_agent' => 'Unit Test Agent/0.1.0',
'accept_language' => 'en-US',
'content_language' => 'en-US',
],
],
$args,
);
}

/**
* Adds a filter for the theme/stylesheet name.
* Will use the default defined in the test class if no params passed.
Expand Down
90 changes: 47 additions & 43 deletions tests/unit/test-class-wc-payments-customer-service.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,12 @@ public function test_create_customer_for_user() {
$user = new WP_User( 1 );
$user->user_login = 'testUser';

$mock_customer_data = $this->get_mock_customer_data();

$this->mock_session_service
->method( 'get_sift_session_id' )
->willReturn( 'sift_session_id' );
$mock_client_data = $this->get_mock_client_data();
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

$this->mock_api_client->expects( $this->once() )
->method( 'create_customer' )
->with(
array_merge(
$mock_customer_data,
[ 'session_id' => 'sift_session_id' ]
)
)
->with( $mock_customer_data )
->willReturn( 'cus_test12345' );

$customer_id = $this->customer_service->create_customer_for_user( $user, $mock_customer_data );
Expand All @@ -215,20 +207,12 @@ public function test_create_customer_for_user_test_mode() {
$user = new WP_User( 1 );
$user->user_login = 'testUser';

$mock_customer_data = $this->get_mock_customer_data();

$this->mock_session_service
->method( 'get_sift_session_id' )
->willReturn( 'sift_session_id' );
$mock_client_data = $this->get_mock_client_data();
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

$this->mock_api_client->expects( $this->once() )
->method( 'create_customer' )
->with(
array_merge(
$mock_customer_data,
[ 'session_id' => 'sift_session_id' ]
)
)
->with( $mock_customer_data )
->willReturn( 'cus_test12345' );

$customer_id = $this->customer_service->create_customer_for_user( $user, $mock_customer_data );
Expand All @@ -246,7 +230,8 @@ public function test_create_customer_for_user_test_mode() {
public function test_update_customer_for_user() {
$user = new WP_User( 0 );

$mock_customer_data = $this->get_mock_customer_data();
$mock_client_data = $this->get_mock_client_data();
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

$this->mock_api_client->expects( $this->once() )
->method( 'update_customer' )
Expand All @@ -268,22 +253,15 @@ public function test_update_customer_for_user() {
* Test non logged in user keeps its customer id saved in the Session.
*/
public function test_non_logged_in_user_saves_customer_id_in_session() {
$user = new WP_User( 0 );
$mock_customer_data = $this->get_mock_customer_data();
$customer_id = 'cus_test12345';
$user = new WP_User( 0 );
$customer_id = 'cus_test12345';

$this->mock_session_service
->method( 'get_sift_session_id' )
->willReturn( 'sift_session_id' );
$mock_client_data = $this->get_mock_client_data();
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

$this->mock_api_client->expects( $this->once() )
->method( 'create_customer' )
->with(
array_merge(
$mock_customer_data,
[ 'session_id' => 'sift_session_id' ]
)
)
->with( $mock_customer_data )
->willReturn( $customer_id );

$this->customer_service->create_customer_for_user( $user, $mock_customer_data );
Expand All @@ -307,7 +285,8 @@ public function test_update_customer_for_user_when_user_not_found() {
$user = new WP_User( 1 );
$user->user_login = 'testUser';

$mock_customer_data = $this->get_mock_customer_data();
$mock_client_data = $this->get_mock_client_data( [ 'session_id' => null ] );
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

// Wire the mock to throw a resource not found exception.
$this->mock_api_client->expects( $this->once() )
Expand Down Expand Up @@ -347,7 +326,8 @@ public function test_update_customer_for_user_when_user_not_found_test_mode() {
$user = new WP_User( 1 );
$user->user_login = 'testUser';

$mock_customer_data = $this->get_mock_customer_data();
$mock_client_data = $this->get_mock_client_data( [ 'session_id' => null ] );
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

// Wire the mock to throw a resource not found exception.
$this->mock_api_client->expects( $this->once() )
Expand Down Expand Up @@ -388,7 +368,8 @@ public function test_update_customer_for_user_when_general_exception_is_thrown()
$user = new WP_User( 1 );
$user->user_login = 'testUser';

$mock_customer_data = $this->get_mock_customer_data();
$mock_client_data = $this->get_mock_client_data();
$mock_customer_data = $this->get_mock_customer_data( $mock_client_data );

// Wire the mock to throw a resource not found exception.
$this->mock_api_client->expects( $this->once() )
Expand Down Expand Up @@ -719,16 +700,12 @@ public function test_get_customer_id_for_order() {
],
];

$this->mock_session_service
->method( 'get_sift_session_id' )
->willReturn( 'sift_session_id' );

$this->mock_api_client->expects( $this->once() )
->method( 'create_customer' )
->with(
array_merge(
$mock_customer_data,
[ 'session_id' => 'sift_session_id' ]
$this->get_mock_client_data()
)
)
->willReturn( 'wcpay_cus_test12345' );
Expand All @@ -754,4 +731,31 @@ public function test_clear_cached_payment_methods_for_user() {
);
$this->customer_service->clear_cached_payment_methods_for_user( 1 );
}

private function get_mock_client_data( $overrides = [] ) {
$data = array_merge(
[
'session_id' => 'sift_session_id',
'ip_address' => '127.0.0.1',
'browser' => [
'user_agent' => 'Unit Test Agent/0.1.0',
'accept_language' => 'en-US',
'content_language' => 'en-US',
],
],
$overrides
);

$this->mock_session_service
->method( 'get_sift_session_id' )
->willReturn( $data['session_id'] );

wp_set_current_user( 1 );
wp_get_current_user()->locale = 'en-US';

$_SERVER['HTTP_USER_AGENT'] = 'Unit Test Agent/0.1.0';
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US';

return $data;
}
}
Loading