Skip to content

Commit 93cd56c

Browse files
authored
Disable WooPay for unavailable countries (#5454)
* Disable WooPay for unavailable countries * Add changelog entry * Define country availability from merchant site * Skip get ip address as the geolocate_ip function already includes it
1 parent ebb4b40 commit 93cd56c

File tree

5 files changed

+131
-1
lines changed

5 files changed

+131
-1
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: fix
3+
4+
Disable WooPay for unavailable countries

includes/class-wc-payments-platform-checkout-button-handler.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use WCPay\Exceptions\Invalid_Price_Exception;
1717
use WCPay\Logger;
1818
use WCPay\Payment_Information;
19+
use WCPay\Platform_Checkout\Platform_Checkout_Utilities;
1920

2021
/**
2122
* WC_Payments_Platform_Checkout_Button_Handler class.
@@ -457,6 +458,12 @@ public function should_show_platform_checkout_button() {
457458
return false;
458459
}
459460

461+
// Check if WooPay is available in the user country.
462+
$platform_checkout_utilities = new Platform_Checkout_Utilities();
463+
if ( ! $platform_checkout_utilities->is_country_available( $this->gateway ) ) {
464+
return false;
465+
}
466+
460467
// Product page, but not available in settings.
461468
if ( $this->is_product() && ! $this->is_available_at( 'product' ) ) {
462469
return false;

includes/platform-checkout-user/class-platform-checkout-save-user.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ public function register_checkout_page_scripts() {
4242
return;
4343
}
4444

45+
if ( ! $this->platform_checkout_util->is_country_available( $gateways['woocommerce_payments'] ) ) {
46+
return;
47+
}
48+
4549
$script_src_url = plugins_url( 'dist/platform-checkout.js', WCPAY_PLUGIN_FILE );
4650
$style_url = plugins_url( 'dist/platform-checkout.css', WCPAY_PLUGIN_FILE );
4751
$script_asset_path = WCPAY_ABSPATH . 'dist/platform-checkout.asset.php';

includes/platform-checkout/class-platform-checkout-utilities.php

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@
1010
use WC_Payments_Features;
1111
use WC_Payments_Subscriptions_Utilities;
1212
use Platform_Checkout_Extension;
13+
use WCPay\Logger;
14+
use WC_Geolocation;
15+
use WC_Payments;
1316

1417
/**
1518
* Platform_Checkout
1619
*/
1720
class Platform_Checkout_Utilities {
1821
use WC_Payments_Subscriptions_Utilities;
1922

23+
const AVAILABLE_COUNTRIES_KEY = 'woocommerce_woocommerce_payments_woopay_available_countries';
24+
const AVAILABLE_COUNTRIES_LAST_CHECK_KEY = 'woocommerce_woocommerce_payments_woopay_available_countries_last_check';
25+
2026
/**
2127
* Check various conditions to determine if we should enable platform checkout.
2228
*
@@ -36,7 +42,7 @@ public function should_enable_platform_checkout( $gateway ) {
3642
* @return boolean
3743
*/
3844
public function is_woopay_express_checkout_enabled() {
39-
return WC_Payments_Features::is_woopay_express_checkout_enabled(); // Feature flag.
45+
return WC_Payments_Features::is_woopay_express_checkout_enabled() && $this->is_country_available( WC_Payments::get_gateway() ); // Feature flag.
4046
}
4147

4248
/**
@@ -62,6 +68,73 @@ public function should_save_platform_customer() {
6268
return ( isset( $_POST['save_user_in_platform_checkout'] ) && filter_var( wp_unslash( $_POST['save_user_in_platform_checkout'] ), FILTER_VALIDATE_BOOLEAN ) ) || ( isset( $session_data['save_user_in_platform_checkout'] ) && filter_var( $session_data['save_user_in_platform_checkout'], FILTER_VALIDATE_BOOLEAN ) ); // phpcs:ignore WordPress.Security.NonceVerification
6369
}
6470

71+
/**
72+
* Get the list of WooPay available countries and cache it for 24 hours.
73+
*
74+
* @return array
75+
*/
76+
public function get_woopay_available_countries() {
77+
$last_check = get_option( self::AVAILABLE_COUNTRIES_LAST_CHECK_KEY );
78+
79+
if ( $last_check && gmdate( 'Y-m-d' ) === $last_check ) {
80+
$available_countries = get_option( self::AVAILABLE_COUNTRIES_KEY, '["US"]' );
81+
82+
return json_decode( $available_countries, true );
83+
}
84+
85+
$platform_checkout_host = defined( 'PLATFORM_CHECKOUT_HOST' ) ? PLATFORM_CHECKOUT_HOST : 'https://pay.woo.com';
86+
$url = $platform_checkout_host . '/wp-json/platform-checkout/v1/user/available-countries';
87+
88+
$args = [
89+
'url' => $url,
90+
'method' => 'GET',
91+
'timeout' => 30,
92+
'headers' => [
93+
'Content-Type' => 'application/json',
94+
],
95+
];
96+
97+
/**
98+
* Suppress psalm error from Jetpack Connection namespacing WP_Error.
99+
*
100+
* @psalm-suppress UndefinedDocblockClass
101+
*/
102+
$response = \Automattic\Jetpack\Connection\Client::remote_request( $args );
103+
104+
if ( is_wp_error( $response ) || ! is_array( $response ) || ! empty( $response['code'] ) ) {
105+
Logger::error( 'HTTP_REQUEST_ERROR ' . var_export( $response, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
106+
107+
// If there's an error, return current data and check again on the next day.
108+
$available_countries = get_option( self::AVAILABLE_COUNTRIES_KEY, '["US"]' );
109+
} else {
110+
$available_countries = wp_remote_retrieve_body( $response );
111+
112+
update_option( self::AVAILABLE_COUNTRIES_KEY, $available_countries );
113+
}
114+
115+
update_option( self::AVAILABLE_COUNTRIES_LAST_CHECK_KEY, gmdate( 'Y-m-d' ) );
116+
117+
return json_decode( $available_countries, true );
118+
}
119+
120+
/**
121+
* Get if WooPay is available on the user country.
122+
*
123+
* @param \WC_Payment_Gateway_WCPay $gateway Gateway instance.
124+
* @return boolean
125+
*/
126+
public function is_country_available( $gateway ) {
127+
if ( $gateway->is_in_test_mode() ) {
128+
return true;
129+
}
130+
131+
$location_data = WC_Geolocation::geolocate_ip();
132+
133+
$available_countries = $this->get_woopay_available_countries();
134+
135+
return in_array( $location_data['country'], $available_countries, true );
136+
}
137+
65138
/**
66139
* Get phone number for creating platform checkout customer.
67140
*

tests/unit/platform-checkout/test-class-platform-checkout-utilities.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,48 @@ public function test_should_enable_platform_checkout( $platform_checkout_eligibl
6060
$this->assertSame( $expected, $actual );
6161
}
6262

63+
/**
64+
* Data provider for test_should_enable_platform_checkout.
65+
*
66+
* @return boolean
67+
*/
68+
public function is_country_available_data_provider() {
69+
return [
70+
[ '206.71.50.230', true ], // US.
71+
[ '187.34.8.193', false ], // BR.
72+
];
73+
}
74+
75+
/**
76+
* Platform checkout is available if feature flags are enabled.
77+
*
78+
* @dataProvider is_country_available_data_provider
79+
* @return void
80+
*/
81+
public function test_is_country_available( $ip_address, $expected ) {
82+
$_SERVER['REMOTE_ADDR'] = $ip_address;
83+
84+
$this->gateway_mock
85+
->expects( $this->once() )
86+
->method( 'is_in_test_mode' )
87+
->willReturn( false );
88+
89+
$platform_checkout_utilities = new Platform_Checkout_Utilities();
90+
$actual = $platform_checkout_utilities->is_country_available( $this->gateway_mock );
91+
$this->assertSame( $expected, $actual );
92+
}
93+
94+
public function test_is_country_available_in_test_mode_return_true() {
95+
$this->gateway_mock
96+
->expects( $this->once() )
97+
->method( 'is_in_test_mode' )
98+
->willReturn( true );
99+
100+
$platform_checkout_utilities = new Platform_Checkout_Utilities();
101+
$actual = $platform_checkout_utilities->is_country_available( $this->gateway_mock );
102+
$this->assertSame( true, $actual );
103+
}
104+
63105
/**
64106
* Cache account details.
65107
*

0 commit comments

Comments
 (0)