diff --git a/changelog/add-country-specific-test-cards b/changelog/add-country-specific-test-cards new file mode 100644 index 00000000000..7d7ff495c04 --- /dev/null +++ b/changelog/add-country-specific-test-cards @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add country-specific test card numbers for credit card testing diff --git a/includes/class-wc-payments-checkout.php b/includes/class-wc-payments-checkout.php index c4593f54b7e..bf8f623897b 100644 --- a/includes/class-wc-payments-checkout.php +++ b/includes/class-wc-payments-checkout.php @@ -324,7 +324,7 @@ public function get_enabled_payment_method_config() { $gateway_for_payment_method = $this->gateway->wc_payments_get_payment_gateway_by_id( $payment_method_id ); $settings[ $payment_method_id ]['testingInstructions'] = WC_Payments_Utils::esc_interpolated_html( /* translators: link to Stripe testing page */ - $payment_method->get_testing_instructions(), + $payment_method->get_testing_instructions( $account_country ), [ 'a' => '', 'strong' => '', @@ -420,14 +420,14 @@ function () use ( $prepared_customer_data ) { is_test() && false !== $this->gateway->get_payment_method()->get_testing_instructions() ) : + if ( WC_Payments::mode()->is_test() && false !== $this->gateway->get_payment_method()->get_testing_instructions( $this->account->get_account_country() ) ) : ?>

gateway->get_payment_method()->get_testing_instructions(), + $this->gateway->get_payment_method()->get_testing_instructions( $this->account->get_account_country() ), [ 'a' => '', 'strong' => '', diff --git a/includes/class-wc-payments.php b/includes/class-wc-payments.php index d236abc0fd4..c7038657b82 100644 --- a/includes/class-wc-payments.php +++ b/includes/class-wc-payments.php @@ -465,6 +465,7 @@ public static function init() { include_once __DIR__ . '/exceptions/class-invalid-address-exception.php'; include_once __DIR__ . '/constants/class-base-constant.php'; include_once __DIR__ . '/constants/class-country-code.php'; + include_once __DIR__ . '/constants/class-country-test-cards.php'; include_once __DIR__ . '/constants/class-currency-code.php'; include_once __DIR__ . '/constants/class-fraud-meta-box-type.php'; include_once __DIR__ . '/constants/class-order-mode.php'; diff --git a/includes/constants/class-country-test-cards.php b/includes/constants/class-country-test-cards.php new file mode 100644 index 00000000000..2e9a8287c84 --- /dev/null +++ b/includes/constants/class-country-test-cards.php @@ -0,0 +1,95 @@ + '4242 4242 4242 4242', + Country_Code::ARGENTINA => '4000 0003 2000 0021', + Country_Code::BRAZIL => '4000 0007 6000 0002', + Country_Code::CANADA => '4000 0012 4000 0000', + Country_Code::CHILE => '4000 0015 2000 0001', + Country_Code::COLOMBIA => '4000 0017 0000 0003', + Country_Code::COSTA_RICA => '4000 0018 8000 0005', + Country_Code::ECUADOR => '4000 0021 8000 0000', + Country_Code::MEXICO => '4000 0048 4000 8001', + Country_Code::PANAMA => '4000 0059 1000 0000', + Country_Code::PARAGUAY => '4000 0060 0000 0066', + Country_Code::PERU => '4000 0060 4000 0068', + Country_Code::URUGUAY => '4000 0085 8000 0003', + Country_Code::UNITED_ARAB_EMIRATES => '4000 0078 4000 0001', + Country_Code::AUSTRIA => '4000 0004 0000 0008', + Country_Code::BELGIUM => '4000 0005 6000 0004', + Country_Code::BULGARIA => '4000 0010 0000 0000', + Country_Code::BELARUS => '4000 0011 2000 0005', + Country_Code::CROATIA => '4000 0019 1000 0009', + Country_Code::CYPRUS => '4000 0019 6000 0008', + Country_Code::CZECHIA => '4000 0020 3000 0002', + Country_Code::DENMARK => '4000 0020 8000 0001', + Country_Code::ESTONIA => '4000 0023 3000 0009', + Country_Code::FINLAND => '4000 0024 6000 0001', + Country_Code::FRANCE => '4000 0025 0000 0003', + Country_Code::GERMANY => '4000 0027 6000 0016', + Country_Code::GIBRALTAR => '4000 0029 2000 0005', + Country_Code::GREECE => '4000 0030 0000 0030', + Country_Code::HUNGARY => '4000 0034 8000 0005', + Country_Code::IRELAND => '4000 0037 2000 0005', + Country_Code::ITALY => '4000 0038 0000 0008', + Country_Code::LATVIA => '4000 0042 8000 0005', + Country_Code::LIECHTENSTEIN => '4000 0043 8000 0004', + Country_Code::LITHUANIA => '4000 0044 0000 0000', + Country_Code::LUXEMBOURG => '4000 0044 2000 0006', + Country_Code::MALTA => '4000 0047 0000 0007', + Country_Code::NETHERLANDS => '4000 0052 8000 0002', + Country_Code::NORWAY => '4000 0057 8000 0007', + Country_Code::POLAND => '4000 0061 6000 0005', + Country_Code::PORTUGAL => '4000 0062 0000 0007', + Country_Code::ROMANIA => '4000 0064 2000 0001', + Country_Code::SAUDI_ARABIA => '4000 0068 2000 0007', + Country_Code::SLOVENIA => '4000 0070 5000 0006', + Country_Code::SLOVAKIA => '4000 0070 3000 0001', + Country_Code::SPAIN => '4000 0072 4000 0007', + Country_Code::SWEDEN => '4000 0075 2000 0008', + Country_Code::SWITZERLAND => '4000 0075 6000 0009', + Country_Code::UNITED_KINGDOM => '4000 0082 6000 0000', + Country_Code::AUSTRALIA => '4000 0003 6000 0006', + Country_Code::CHINA => '4000 0015 6000 0002', + Country_Code::HONG_KONG => '4000 0034 4000 0004', + Country_Code::INDIA => '4000 0035 6000 0008', + Country_Code::JAPAN => '4000 0039 2000 0003', + Country_Code::MALAYSIA => '4000 0045 8000 0002', + Country_Code::NEW_ZEALAND => '4000 0055 4000 0008', + Country_Code::SINGAPORE => '4000 0070 2000 0003', + Country_Code::TAIWAN => '4000 0015 8000 0008', + Country_Code::THAILAND => '4000 0076 4000 0003', + ]; + + /** + * Get test card number for a specific country. + * + * @param string $country_code Two-letter country code. + * @return string Test card number + */ + public static function get_test_card_for_country( string $country_code ) { + return self::$country_test_cards[ $country_code ] ?? self::$country_test_cards[ Country_Code::UNITED_STATES ]; + } +} diff --git a/includes/payment-methods/class-affirm-payment-method.php b/includes/payment-methods/class-affirm-payment-method.php index 68699548124..24dba99b021 100644 --- a/includes/payment-methods/class-affirm-payment-method.php +++ b/includes/payment-methods/class-affirm-payment-method.php @@ -41,9 +41,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-afterpay-payment-method.php b/includes/payment-methods/class-afterpay-payment-method.php index 89062a4a7f9..a0a4acbbf30 100644 --- a/includes/payment-methods/class-afterpay-payment-method.php +++ b/includes/payment-methods/class-afterpay-payment-method.php @@ -71,9 +71,10 @@ public function get_icon( string $account_country = null ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-bancontact-payment-method.php b/includes/payment-methods/class-bancontact-payment-method.php index 6d4f845416c..422636084ff 100644 --- a/includes/payment-methods/class-bancontact-payment-method.php +++ b/includes/payment-methods/class-bancontact-payment-method.php @@ -36,9 +36,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-becs-payment-method.php b/includes/payment-methods/class-becs-payment-method.php index 1d2c20b5b70..763a181d059 100644 --- a/includes/payment-methods/class-becs-payment-method.php +++ b/includes/payment-methods/class-becs-payment-method.php @@ -36,9 +36,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return __( 'Test mode: use the test account number 000123456. Other payment methods may redirect to a Stripe test page to authorize payment. More test card numbers are listed here.', 'woocommerce-payments' ); } } diff --git a/includes/payment-methods/class-cc-payment-method.php b/includes/payment-methods/class-cc-payment-method.php index df14d4ecd8c..3f0c114aa8a 100644 --- a/includes/payment-methods/class-cc-payment-method.php +++ b/includes/payment-methods/class-cc-payment-method.php @@ -8,6 +8,7 @@ namespace WCPay\Payment_Methods; use WC_Payments_Token_Service; +use WCPay\Constants\Country_Test_Cards; /** * Credit card Payment Method class extending UPE base class @@ -67,9 +68,16 @@ public function get_title( string $account_country = null, $payment_details = fa /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { - return __( 'Use test card 4242 4242 4242 4242 or refer to our testing guide.', 'woocommerce-payments' ); + public function get_testing_instructions( string $account_country ) { + $test_card_number = Country_Test_Cards::get_test_card_for_country( $account_country ); + + return sprintf( + // Translators: %s is a test card number. + __( 'Use test card %s or refer to our testing guide.', 'woocommerce-payments' ), + $test_card_number + ); } } diff --git a/includes/payment-methods/class-eps-payment-method.php b/includes/payment-methods/class-eps-payment-method.php index 5b2e73ed441..ab936ace70d 100644 --- a/includes/payment-methods/class-eps-payment-method.php +++ b/includes/payment-methods/class-eps-payment-method.php @@ -36,9 +36,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-giropay-payment-method.php b/includes/payment-methods/class-giropay-payment-method.php index b117382f0da..82095ffbf33 100644 --- a/includes/payment-methods/class-giropay-payment-method.php +++ b/includes/payment-methods/class-giropay-payment-method.php @@ -36,9 +36,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-ideal-payment-method.php b/includes/payment-methods/class-ideal-payment-method.php index 084499b6efe..5c1ac9abfbe 100644 --- a/includes/payment-methods/class-ideal-payment-method.php +++ b/includes/payment-methods/class-ideal-payment-method.php @@ -36,9 +36,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-klarna-payment-method.php b/includes/payment-methods/class-klarna-payment-method.php index 1e439a8d476..aaea0697423 100644 --- a/includes/payment-methods/class-klarna-payment-method.php +++ b/includes/payment-methods/class-klarna-payment-method.php @@ -70,9 +70,10 @@ public function get_countries() { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-link-payment-method.php b/includes/payment-methods/class-link-payment-method.php index 6a9b904a03f..c5c189bbad8 100644 --- a/includes/payment-methods/class-link-payment-method.php +++ b/includes/payment-methods/class-link-payment-method.php @@ -34,9 +34,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-p24-payment-method.php b/includes/payment-methods/class-p24-payment-method.php index 8718911b480..4237beab155 100644 --- a/includes/payment-methods/class-p24-payment-method.php +++ b/includes/payment-methods/class-p24-payment-method.php @@ -36,9 +36,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-sepa-payment-method.php b/includes/payment-methods/class-sepa-payment-method.php index 8ea671f7706..012828be15c 100644 --- a/includes/payment-methods/class-sepa-payment-method.php +++ b/includes/payment-methods/class-sepa-payment-method.php @@ -40,9 +40,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return __( 'Test mode: use the test account number AT611904300234573201. Other payment methods may redirect to a Stripe test page to authorize payment. More test card numbers are listed here.', 'woocommerce-payments' ); } } diff --git a/includes/payment-methods/class-sofort-payment-method.php b/includes/payment-methods/class-sofort-payment-method.php index 2f4f4fba212..291ff6c2b95 100644 --- a/includes/payment-methods/class-sofort-payment-method.php +++ b/includes/payment-methods/class-sofort-payment-method.php @@ -37,9 +37,10 @@ public function __construct( $token_service ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - public function get_testing_instructions() { + public function get_testing_instructions( string $account_country ) { return ''; } } diff --git a/includes/payment-methods/class-upe-payment-method.php b/includes/payment-methods/class-upe-payment-method.php index 93bf0797088..2e69e916c1b 100644 --- a/includes/payment-methods/class-upe-payment-method.php +++ b/includes/payment-methods/class-upe-payment-method.php @@ -270,9 +270,10 @@ public function get_payment_token_for_user( $user, $payment_method_id ) { /** * Returns testing credentials to be printed at checkout in test mode. * + * @param string $account_country The country of the account. * @return string */ - abstract public function get_testing_instructions(); + abstract public function get_testing_instructions( string $account_country ); /** * Returns the payment method icon URL or an empty string. diff --git a/tests/unit/test-class-wc-payments-checkout.php b/tests/unit/test-class-wc-payments-checkout.php index 2394328c430..962c7bc4d8b 100644 --- a/tests/unit/test-class-wc-payments-checkout.php +++ b/tests/unit/test-class-wc-payments-checkout.php @@ -103,9 +103,6 @@ public function set_up() { ->disableOriginalConstructor() ->getMock(); $this->mock_wcpay_account = $this->createMock( WC_Payments_Account::class ); - $this->mock_wcpay_account - ->method( 'get_account_country' ) - ->willReturn( 'US' ); $this->mock_customer_service = $this->createMock( WC_Payments_Customer_Service::class ); $this->mock_fraud_service = $this->createMock( WC_Payments_Fraud_Service::class ); @@ -309,6 +306,9 @@ public function test_force_network_saved_cards_disabled_when_should_not_use_stri } public function test_link_payment_method_provided_when_card_enabled() { + $this->mock_wcpay_account + ->method( 'get_account_country' ) + ->willReturn( 'US' ); $icon_url = 'test-icon-url'; $dark_icon_url = 'test-dark-icon-url'; $this->mock_wcpay_gateway @@ -404,6 +404,10 @@ public function test_link_payment_method_provided_when_card_enabled() { * @dataProvider non_reusable_payment_method_provider */ public function test_no_save_option_for_non_reusable_payment_method( $payment_method_id, $payment_method_class ) { + $this->mock_wcpay_account + ->method( 'get_account_country' ) + ->willReturn( 'US' ); + $this->mock_wcpay_gateway ->expects( $this->any() ) ->method( 'get_payment_method_ids_enabled_at_checkout' ) @@ -434,6 +438,9 @@ public function non_reusable_payment_method_provider() { } public function test_no_save_option_for_reusable_payment_payment_with_subscription_in_cart() { + $this->mock_wcpay_account + ->method( 'get_account_country' ) + ->willReturn( 'US' ); $this->mock_wcpay_gateway ->method( 'is_subscription_item_in_cart' ) ->willReturn( true ); @@ -460,6 +467,9 @@ public function test_no_save_option_for_reusable_payment_payment_with_subscripti } public function test_no_save_option_for_reusable_payment_payment_but_with_saved_cards_disabled() { + $this->mock_wcpay_account + ->method( 'get_account_country' ) + ->willReturn( 'US' ); $this->mock_wcpay_gateway ->method( 'is_subscription_item_in_cart' ) ->willReturn( false ); @@ -486,6 +496,9 @@ public function test_no_save_option_for_reusable_payment_payment_but_with_saved_ } public function test_save_option_for_reusable_payment_payment() { + $this->mock_wcpay_account + ->method( 'get_account_country' ) + ->willReturn( 'US' ); $this->mock_wcpay_gateway ->method( 'is_subscription_item_in_cart' ) ->willReturn( false ); @@ -512,6 +525,9 @@ public function test_save_option_for_reusable_payment_payment() { } public function test_upe_appearance_transients() { + $this->mock_wcpay_account + ->method( 'get_account_country' ) + ->willReturn( 'US' ); $this->mock_wcpay_gateway ->expects( $this->any() ) ->method( 'get_payment_method_ids_enabled_at_checkout' ) @@ -536,4 +552,60 @@ public function test_upe_appearance_transients() { $this->assertSame( 'night', $js_config['wcBlocksUPEAppearanceTheme'] ); $this->assertFalse( $js_config['upeAddPaymentMethodAppearance'] ); } + + /** + * Data provider for testing different country card numbers + */ + public function country_test_cards_provider(): array { + return [ + 'US card' => [ + 'country' => 'US', + 'expected_card' => '4242 4242 4242 4242', + ], + 'Brazil card' => [ + 'country' => 'BR', + 'expected_card' => '4000 0007 6000 0002', + ], + 'UK card' => [ + 'country' => 'GB', + 'expected_card' => '4000 0082 6000 0000', + ], + 'Invalid country defaults to US' => [ + 'country' => 'XX', + 'expected_card' => '4242 4242 4242 4242', + ], + ]; + } + + /** + * @dataProvider country_test_cards_provider + */ + public function test_credit_card_testing_instructions_by_country( string $country, string $expected_card ) { + $cc_payment_method = new CC_Payment_Method( $this->mock_token_service ); + + $this->mock_wcpay_account + ->expects( $this->once() ) + ->method( 'get_account_country' ) + ->willReturn( $country ); + + $this->mock_wcpay_gateway + ->method( 'get_payment_method_ids_enabled_at_checkout' ) + ->willReturn( [ 'card' ] ); + + $this->mock_wcpay_gateway + ->method( 'wc_payments_get_payment_method_by_id' ) + ->willReturn( $cc_payment_method ); + + $config = $this->system_under_test->get_payment_fields_js_config(); + + $expected_instructions = sprintf( + 'Use test card or refer to our testing guide.', + $expected_card + ); + + $this->assertEquals( + $expected_instructions, + $config['paymentMethodsConfig']['card']['testingInstructions'] + ); + } }