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

Fix: Hide payment methods with domestic transactions restrictions (Klarna, Affirm, Afterpay) when conditions are not met #8980

Merged
4 changes: 4 additions & 0 deletions changelog/fix-8718-restrict-klarna-non-domestic-transactions
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Hide payment methods with domestic transactions restrictions (Klarna, Affirm, Afterpay) when conditions are not met.
42 changes: 42 additions & 0 deletions includes/class-wc-payments-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -1147,4 +1147,46 @@ public static function get_active_upe_theme_transient_for_location( string $loca
// Fallback to 'stripe' if no transients are set.
return 'stripe';
}

/**
* Returns the list of countries in the European Economic Area (EEA).
*
* Based on the list documented at https://www.gov.uk/eu-eea.
*
* @return string[]
*/
public static function get_european_economic_area_countries() {
return [
Country_Code::AUSTRIA,
Country_Code::BELGIUM,
Country_Code::BULGARIA,
Country_Code::CROATIA,
Country_Code::CYPRUS,
Country_Code::CZECHIA,
Country_Code::DENMARK,
Country_Code::ESTONIA,
Country_Code::FINLAND,
Country_Code::FRANCE,
Country_Code::GERMANY,
Country_Code::GREECE,
Country_Code::HUNGARY,
Country_Code::IRELAND,
Country_Code::ICELAND,
Country_Code::ITALY,
Country_Code::LATVIA,
Country_Code::LIECHTENSTEIN,
Country_Code::LITHUANIA,
Country_Code::LUXEMBOURG,
Country_Code::MALTA,
Country_Code::NORWAY,
Country_Code::NETHERLANDS,
Country_Code::POLAND,
Country_Code::PORTUGAL,
Country_Code::ROMANIA,
Country_Code::SLOVAKIA,
Country_Code::SLOVENIA,
Country_Code::SPAIN,
Country_Code::SWEDEN,
];
}
}
30 changes: 30 additions & 0 deletions includes/payment-methods/class-klarna-payment-method.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,36 @@ public function __construct( $token_service ) {
];
}

/**
* Returns payment method supported countries.
*
* For Klarna we need to include additional logic to support transactions between countries in the EEA,
* UK, and Switzerland.
*
* @return array
*/
public function get_countries() {
$account = \WC_Payments::get_account_service()->get_cached_account_data();
$account_country = isset( $account['country'] ) ? strtoupper( $account['country'] ) : '';

// Countries in the EEA can transact across all other EEA countries. This includes Switzerland and the UK who aren't strictly in the EU.
$eea_countries = array_merge(
WC_Payments_Utils::get_european_economic_area_countries(),
[ Country_Code::SWITZERLAND, Country_Code::UNITED_KINGDOM ]
);

// If the merchant is in the EEA, UK, or Switzerland, only the countries that have the same domestic currency as the store currency will be supported.
if ( in_array( $account_country, $eea_countries, true ) ) {
$store_currency = strtoupper( get_woocommerce_currency() );

$countries_that_support_store_currency = array_keys( $this->limits_per_currency[ $store_currency ] );

return array_values( array_intersect( $eea_countries, $countries_that_support_store_currency ) );
}

return parent::get_countries();
}

/**
* Returns testing credentials to be printed at checkout in test mode.
*
Expand Down
5 changes: 4 additions & 1 deletion includes/payment-methods/class-upe-payment-method.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,10 @@ public function get_payment_method_icon_for_location( string $location = 'checko
* @return array
*/
public function get_countries() {
return $this->countries;
$account = \WC_Payments::get_account_service()->get_cached_account_data();
$account_country = isset( $account['country'] ) ? strtoupper( $account['country'] ) : '';

return $this->has_domestic_transactions_restrictions() ? [ $account_country ] : $this->countries;
}

/**
Expand Down
155 changes: 155 additions & 0 deletions tests/unit/payment-methods/test-class-klarna-payment-method.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php
/**
* Class Klarna_Payment_Method_Test
*
* @package WooCommerce\Payments\Tests
*/

namespace WCPay\Payment_Methods;

use PHPUnit\Framework\MockObject\MockObject;
use WCPay\Constants\Country_Code;
use WCPay\Constants\Currency_Code;
use WCPAY_UnitTestCase;
use WC_Payments_Account;
use WC_Payments_Token_Service;
use WC_Payments;

/**
* Klarna_Payment_Method unit tests
*/
class Klarna_Payment_Method_Test extends WCPAY_UnitTestCase {

/**
* Mock site currency string
*
* @var string
*/
public static $mock_site_currency = '';

/**
* Mock WC_Payments_Token_Service.
*
* @var WC_Payments_Token_Service|MockObject
*/
private $mock_token_service;

/**
* Klarna Payment Method Mock
*
* @var UPE_Payment_Method|MockObject
*/
private $mock_payment_method;

/**
* WC_Payments_Account mocked instance.
*
* @var WC_Payments_Account|MockObject
*/
private $mock_wcpay_account;

/**
* WC_Payments_Account original instance.
*
* @var WC_Payments_Account
*/
private $original_account_service;

/**
* Pre-test setup
*/
public function set_up() {
parent::set_up();

$this->mock_wcpay_account = $this->createMock( WC_Payments_Account::class );
$this->original_account_service = WC_Payments::get_account_service();
WC_Payments::set_account_service( $this->mock_wcpay_account );

// Arrange: Mock WC_Payments_Token_Service so its methods aren't called directly.
$this->mock_token_service = $this->getMockBuilder( 'WC_Payments_Token_Service' )
->disableOriginalConstructor()
->onlyMethods( [ 'add_payment_method_to_user' ] )
->getMock();

$this->mock_payment_method = $this->getMockBuilder( Klarna_Payment_Method::class )
->setConstructorArgs( [ $this->mock_token_service ] )
->onlyMethods( [] )
->getMock();
}

/**
* Cleanup after tests.
*
* @return void
*/
public function tear_down() {
parent::tear_down();
wcpay_get_test_container()->reset_all_replacements();
WC_Payments::set_account_service( $this->original_account_service );
WC_Helper_Site_Currency::$mock_site_currency = '';
}

/**
* @dataProvider provider_test_get_countries
*/
public function test_get_countries(
string $account_country,
?string $site_currency,
array $expected_result
) {
$this->mock_wcpay_account->method( 'get_cached_account_data' )->willReturn(
[
'country' => $account_country,
]
);

if ( $site_currency ) {
WC_Helper_Site_Currency::$mock_site_currency = $site_currency;
}

$this->assertEqualsCanonicalizing( $expected_result, $this->mock_payment_method->get_countries() );
}

public function provider_test_get_countries() {
return [
'US account' => [
'account_country' => Country_Code::UNITED_STATES,
'site_currency' => null,
'expected_result' => [ Country_Code::UNITED_STATES ],
],
'UK account with GBP store currency' => [
'account_country' => Country_Code::UNITED_KINGDOM,
'site_currency' => Currency_Code::POUND_STERLING,
'expected_result' => [ Country_Code::UNITED_KINGDOM ],
],
'UK account with EUR store currency' => [
'account_country' => Country_Code::UNITED_KINGDOM,
'site_currency' => Currency_Code::EURO,
'expected_result' => [
Country_Code::AUSTRIA,
Country_Code::BELGIUM,
Country_Code::FINLAND,
Country_Code::GERMANY,
Country_Code::IRELAND,
Country_Code::ITALY,
Country_Code::NETHERLANDS,
Country_Code::SPAIN,
],
],
Comment on lines +125 to +138
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this is a valid scenario, currently there is not way to manually test it due to the limitations described here #8718 (comment) Which should be addressed as part of a new issue.

'BE account with EUR store currency' => [
'account_country' => Country_Code::BELGIUM,
'site_currency' => Currency_Code::EURO,
'expected_result' => [
Country_Code::AUSTRIA,
Country_Code::BELGIUM,
Country_Code::FINLAND,
Country_Code::GERMANY,
Country_Code::IRELAND,
Country_Code::ITALY,
Country_Code::NETHERLANDS,
Country_Code::SPAIN,
],
],
];
}
}
Loading
Loading