diff --git a/changelog/update-4163-compatibility-service b/changelog/update-4163-compatibility-service new file mode 100644 index 00000000000..3a524da05ae --- /dev/null +++ b/changelog/update-4163-compatibility-service @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Adding Compatibility Service to assist with flagging possible compatibility issues in the future. diff --git a/includes/class-compatibility-service.php b/includes/class-compatibility-service.php new file mode 100644 index 00000000000..444b3383cb1 --- /dev/null +++ b/includes/class-compatibility-service.php @@ -0,0 +1,61 @@ +payments_api_client = $payments_api_client; + } + + /** + * Initializes this class's WP hooks. + * + * @return void + */ + public function init_hooks() { + add_action( 'woocommerce_payments_account_refreshed', [ $this, 'update_compatibility_data' ] ); + } + + /** + * Gets the data we need to confirm compatibility and sends it to the server. + * + * @return void + */ + public function update_compatibility_data() { + try { + $this->payments_api_client->update_compatibility_data( + [ + 'woopayments_version' => WCPAY_VERSION_NUMBER, + 'woocommerce_version' => WC_VERSION, + ] + ); + } catch ( API_Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch + // The exception is already logged if logging is on, nothing else needed. + } + } +} diff --git a/includes/class-wc-payments.php b/includes/class-wc-payments.php index f2e038afe59..26e51088d9f 100644 --- a/includes/class-wc-payments.php +++ b/includes/class-wc-payments.php @@ -44,6 +44,7 @@ use WCPay\Internal\Service\OrderService; use WCPay\WooPay\WooPay_Scheduler; use WCPay\WooPay\WooPay_Session; +use WCPay\Compatibility_Service; /** * Main class for the WooPayments extension. Its responsibility is to initialize the extension. @@ -295,6 +296,13 @@ class WC_Payments { */ private static $incentives_service; + /** + * Instance of Compatibility_Service, created in init function + * + * @var Compatibility_Service + */ + private static $compatibility_service; + /** * Entry point to the initialization logic. */ @@ -463,6 +471,7 @@ public static function init() { include_once __DIR__ . '/core/service/class-wc-payments-customer-service-api.php'; include_once __DIR__ . '/class-duplicate-payment-prevention-service.php'; include_once __DIR__ . '/class-wc-payments-incentives-service.php'; + include_once __DIR__ . '/class-compatibility-service.php'; include_once __DIR__ . '/multi-currency/wc-payments-multi-currency.php'; self::$woopay_checkout_service = new Checkout_Service(); @@ -497,6 +506,7 @@ public static function init() { self::$woopay_tracker = new WooPay_Tracker( self::get_wc_payments_http() ); self::$incentives_service = new WC_Payments_Incentives_Service( self::$database_cache ); self::$duplicate_payment_prevention_service = new Duplicate_Payment_Prevention_Service(); + self::$compatibility_service = new Compatibility_Service( self::$api_client ); ( new WooPay_Scheduler( self::$api_client ) )->init(); @@ -505,6 +515,7 @@ public static function init() { self::$fraud_service->init_hooks(); self::$onboarding_service->init_hooks(); self::$incentives_service->init_hooks(); + self::$compatibility_service->init_hooks(); self::$legacy_card_gateway = new CC_Payment_Gateway( self::$api_client, self::$account, self::$customer_service, self::$token_service, self::$action_scheduler_service, self::$failed_transaction_rate_limiter, self::$order_service, self::$duplicate_payment_prevention_service, self::$localization_service, self::$fraud_service ); diff --git a/includes/core/server/class-request.php b/includes/core/server/class-request.php index 80e35dba0de..6264660bb29 100644 --- a/includes/core/server/class-request.php +++ b/includes/core/server/class-request.php @@ -161,6 +161,7 @@ abstract class Request { WC_Payments_API_Client::AUTHORIZATIONS_API => 'authorizations', WC_Payments_API_Client::FRAUD_OUTCOMES_API => 'fraud_outcomes', WC_Payments_API_Client::FRAUD_RULESET_API => 'fraud_ruleset', + WC_Payments_API_Client::COMPATIBILITY_API => 'compatibility', ]; /** diff --git a/includes/wc-payment-api/class-wc-payments-api-client.php b/includes/wc-payment-api/class-wc-payments-api-client.php index f6cd60bfb87..637126b3fa4 100644 --- a/includes/wc-payment-api/class-wc-payments-api-client.php +++ b/includes/wc-payment-api/class-wc-payments-api-client.php @@ -76,6 +76,7 @@ class WC_Payments_API_Client { const FRAUD_SERVICES_API = 'accounts/fraud_services'; const FRAUD_OUTCOMES_API = 'fraud_outcomes'; const FRAUD_RULESET_API = 'fraud_ruleset'; + const COMPATIBILITY_API = 'compatibility'; /** * Common keys in API requests/responses that we might want to redact. @@ -1703,6 +1704,27 @@ public function get_onboarding_po_eligible( array $business_info, array $store_i ); } + /** + * Sends the compatibility data to the server to be saved to the account. + * + * @param array $compatibility_data The array containing the data. + * + * @return array HTTP response on success. + * + * @throws API_Exception - If not connected or request failed. + */ + public function update_compatibility_data( $compatibility_data ) { + $response = $this->request( + [ + 'compatibility_data' => $compatibility_data, + ], + self::COMPATIBILITY_API, + self::POST + ); + + return $response; + } + /** * Sends a request object. * diff --git a/tests/unit/test-class-compatibility-service.php b/tests/unit/test-class-compatibility-service.php new file mode 100644 index 00000000000..70e86b5d2dc --- /dev/null +++ b/tests/unit/test-class-compatibility-service.php @@ -0,0 +1,61 @@ +mock_api_client = $this->createMock( WC_Payments_API_Client::class ); + $this->compatibility_service = new Compatibility_Service( $this->mock_api_client ); + $this->compatibility_service->init_hooks(); + } + + public function test_registers_woocommerce_filters_properly() { + $priority = has_filter( 'woocommerce_payments_account_refreshed', [ $this->compatibility_service, 'update_compatibility_data' ] ); + $this->assertEquals( 10, $priority ); + } + + public function test_update_compatibility_data() { + // Arrange: Create the expected value to be passed to update_compatibility_data. + $expected = [ + 'woopayments_version' => WCPAY_VERSION_NUMBER, + 'woocommerce_version' => WC_VERSION, + ]; + + // Arrange/Assert: Set the expectations for update_compatibility_data. + $this->mock_api_client + ->expects( $this->once() ) + ->method( 'update_compatibility_data' ) + ->with( $expected ); + + // Act: Call the method we're testing. + $this->compatibility_service->update_compatibility_data(); + } +} diff --git a/tests/unit/wc-payment-api/test-class-wc-payments-api-client.php b/tests/unit/wc-payment-api/test-class-wc-payments-api-client.php index 4476cce139a..d6320c14bd0 100644 --- a/tests/unit/wc-payment-api/test-class-wc-payments-api-client.php +++ b/tests/unit/wc-payment-api/test-class-wc-payments-api-client.php @@ -907,7 +907,7 @@ public function test_get_disputes_summary_success() { $this->assertSame( 12, $disputes_summary['data']['count'] ); } - public function get_onboarding_po_eligible() { + public function test_get_onboarding_po_eligible() { $this->set_http_mock_response( 200, [ @@ -1203,6 +1203,33 @@ public function test_request_doesnt_retry_get_without_idempotency_header_on_netw [ [], 'intentions', 'GET' ] ); } + + public function test_update_compatibility_data() { + // Arrange: Set expectation and return for remote_request. + $this->mock_http_client + ->expects( $this->once() ) + ->method( 'remote_request' ) + ->willReturn( + [ + 'body' => wp_json_encode( [ 'result' => 'success' ] ), + 'response' => [ + 'code' => 200, + 'message' => 'OK', + ], + ] + ); + + // Act: Get the result of updating the data. + $result = $this->payments_api_client->update_compatibility_data( + [ + 'woocommerce_core_version' => WC_VERSION, + ] + ); + + // Assert: Confirm we get the expected response. + $this->assertSame( 'success', $result['result'] ); + } + /** * Set up http mock response. *