Skip to content

Commit 812becb

Browse files
wjrosadaledupreez
andauthored
Deactivates Affirm or Klarna in PMC when other extensions are active (#4515)
* Deactivates Affirm or Klarna in PMC when other extensions are active * Avoid request when the related methods are not enabled * Update includes/payment-methods/class-wc-stripe-upe-payment-gateway.php Co-authored-by: daledupreez <[email protected]> * Update includes/payment-methods/class-wc-stripe-upe-payment-gateway.php Co-authored-by: daledupreez <[email protected]> * Fix suggestion patch * Removing redaunt calls * Moving deactivation method to the main Stripe class hooking to init * Unit tests * Moving some unit tests to their correct place * PHP doc * Update includes/class-wc-stripe.php Co-authored-by: daledupreez <[email protected]> * Checking for UPE gateway instance --------- Co-authored-by: daledupreez <[email protected]>
1 parent 1b25c00 commit 812becb

File tree

6 files changed

+396
-210
lines changed

6 files changed

+396
-210
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*** Changelog ***
22

33
= 9.8.0 - xxxx-xx-xx =
4+
* Update - Deactivates Affirm or Klarna when other official plugins are active in merchant's Payment Method Configuration
45
* Fix - Fixes issues related to booking multiple slots with express checkout payment methods enabled
56
* Fix - Update the Optimized Checkout promotional inbox note to link to the relevant section in the Stripe settings page
67
* Add - Makes the Optimized Checkout feature available for all merchants by default

includes/class-wc-stripe.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ public function init() {
281281
add_action( 'init', [ $this, 'initialize_status_page' ], 15 );
282282

283283
add_action( 'init', [ $this, 'initialize_apple_pay_registration' ] );
284+
285+
// Check if other official plugins are active for Klarna or Affirm and deactivate those BNPLs if so.
286+
add_action( 'init', [ $this, 'maybe_deactivate_bnpls' ] );
284287
}
285288

286289
/**
@@ -857,4 +860,42 @@ public function initialize_status_page() {
857860
$wcstripe_status = new WC_Stripe_Status( self::get_main_stripe_gateway(), $this->account );
858861
$wcstripe_status->init_hooks();
859862
}
863+
864+
/**
865+
* Maybe deactivate Affirm or Klarna payment methods if other official plugins are active.
866+
*
867+
* @return void
868+
*/
869+
public function maybe_deactivate_bnpls() {
870+
$has_affirm_plugin_active = WC_Stripe_Helper::has_gateway_plugin_active( WC_Stripe_Helper::OFFICIAL_PLUGIN_ID_AFFIRM );
871+
$has_klarna_plugin_active = WC_Stripe_Helper::has_gateway_plugin_active( WC_Stripe_Helper::OFFICIAL_PLUGIN_ID_KLARNA );
872+
if ( ! $has_affirm_plugin_active && ! $has_klarna_plugin_active ) {
873+
return;
874+
}
875+
876+
$gateway = $this->get_main_stripe_gateway();
877+
if ( ! is_a( $gateway, 'WC_Stripe_UPE_Payment_Gateway' ) ) {
878+
return;
879+
}
880+
881+
$enabled_payment_methods = $gateway->get_upe_enabled_payment_method_ids();
882+
$payment_method_ids_to_disable = [];
883+
if ( $has_affirm_plugin_active && in_array( WC_Stripe_Payment_Methods::AFFIRM, $enabled_payment_methods, true ) ) {
884+
$payment_method_ids_to_disable[] = WC_Stripe_Payment_Methods::AFFIRM;
885+
}
886+
if ( $has_klarna_plugin_active && in_array( WC_Stripe_Payment_Methods::KLARNA, $enabled_payment_methods, true ) ) {
887+
$payment_method_ids_to_disable[] = WC_Stripe_Payment_Methods::KLARNA;
888+
}
889+
890+
if ( [] === $payment_method_ids_to_disable ) {
891+
return;
892+
}
893+
894+
$gateway->update_enabled_payment_methods(
895+
array_diff(
896+
$enabled_payment_methods,
897+
$payment_method_ids_to_disable
898+
)
899+
);
900+
}
860901
}

readme.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
111111
== Changelog ==
112112

113113
= 9.8.0 - xxxx-xx-xx =
114+
* Update - Deactivates Affirm or Klarna when other official plugins are active in merchant's Payment Method Configuration
114115
* Fix - Fixes issues related to booking multiple slots with express checkout payment methods enabled
115116
* Fix - Update the Optimized Checkout promotional inbox note to link to the relevant section in the Stripe settings page
116117
* Add - Makes the Optimized Checkout feature available for all merchants by default

tests/phpunit/WC_Stripe_Feature_Flags_Test.php

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
namespace WooCommerce\Stripe\Tests;
44

55
use WC_Stripe_Feature_Flags;
6+
use WC_Stripe_Helper;
7+
use WC_Stripe_UPE_Payment_Gateway;
68
use WooCommerce\Stripe\Tests\Helpers\PMC_Test_Helper;
9+
use WooCommerce\Stripe\Tests\Helpers\UPE_Test_Helper;
710
use WP_UnitTestCase;
811

912
/**
@@ -13,7 +16,18 @@
1316
*
1417
* @package WooCommerce/Stripe/WC_Stripe_Feature_Flags
1518
*/
16-
class WC_Stripe_Feature_Flags_Test extends WP_UnitTestCase {
19+
class WC_Stripe_Feature_Flags_Test extends WC_Mock_Stripe_API_Unit_Test_Case {
20+
/**
21+
* @var UPE_Test_Helper
22+
*/
23+
private $upe_helper;
24+
25+
public function set_up() {
26+
parent::set_up();
27+
$this->upe_helper = new UPE_Test_Helper();
28+
$this->set_stripe_account_data( [ 'country' => 'US' ] );
29+
}
30+
1731
/**
1832
* Test for `is_oc_available`.
1933
*
@@ -84,4 +98,30 @@ public function provide_test_is_oc_available() {
8498
],
8599
];
86100
}
101+
102+
public function test_legacy_payment_methods_supported_by_upe_are_not_loaded_when_upe_is_enabled() {
103+
$this->upe_helper->enable_upe_feature_flag();
104+
$this->assertTrue( WC_Stripe_Feature_Flags::is_upe_preview_enabled() );
105+
106+
WC_Stripe_Helper::update_main_stripe_settings( [ 'upe_checkout_experience_enabled' => 'yes' ] );
107+
$this->upe_helper->reload_payment_gateways();
108+
109+
$this->assertTrue( WC_Stripe_Feature_Flags::is_upe_checkout_enabled() );
110+
111+
$loaded_gateway_classes = array_map(
112+
function ( $gateway ) {
113+
return get_class( $gateway );
114+
},
115+
WC()->payment_gateways->payment_gateways()
116+
);
117+
118+
foreach ( WC_Stripe_UPE_Payment_Gateway::UPE_AVAILABLE_METHODS as $upe_method ) {
119+
if ( ! defined( "$upe_method::LPM_GATEWAY_CLASS" ) ) {
120+
continue;
121+
}
122+
$this->assertNotContains( $upe_method::LPM_GATEWAY_CLASS, $loaded_gateway_classes );
123+
}
124+
125+
$this->assertContains( WC_Stripe_UPE_Payment_Gateway::class, $loaded_gateway_classes );
126+
}
87127
}

tests/phpunit/WC_Stripe_Helper_Test.php

Lines changed: 199 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
use WC_Stripe_Currency_Code;
99
use WC_Stripe_Helper;
1010
use WC_Stripe_Payment_Methods;
11+
use WooCommerce\Stripe\Tests\Helpers\UPE_Test_Helper;
1112
use WooCommerce\Stripe\Tests\Helpers\WC_Helper_Order;
12-
use WP_UnitTestCase;
1313

1414
/**
1515
* These tests make assertions against class WC_Stripe_Helper.
@@ -18,7 +18,18 @@
1818
*
1919
* WC_Stripe_Helper_Test class.
2020
*/
21-
class WC_Stripe_Helper_Test extends WP_UnitTestCase {
21+
class WC_Stripe_Helper_Test extends WC_Mock_Stripe_API_Unit_Test_Case {
22+
/**
23+
* @var UPE_Test_Helper
24+
*/
25+
private $upe_helper;
26+
27+
public function set_up() {
28+
parent::set_up();
29+
$this->upe_helper = new UPE_Test_Helper();
30+
$this->set_stripe_account_data( [ 'country' => 'US' ] );
31+
}
32+
2233
public function test_convert_to_stripe_locale() {
2334
$result = WC_Stripe_Helper::convert_wc_locale_to_stripe_locale( 'en_GB' );
2435
$this->assertEquals( 'en-GB', $result );
@@ -698,4 +709,190 @@ public function provide_has_gateway_plugin_active() {
698709
],
699710
];
700711
}
712+
713+
/**
714+
* Stripe requires price in the smallest dominations aka cents.
715+
* This test will see if we're indeed converting the price correctly.
716+
*/
717+
public function test_price_conversion_before_send_to_stripe() {
718+
$this->assertEquals( 10050, WC_Stripe_Helper::get_stripe_amount( 100.50, WC_Stripe_Currency_Code::UNITED_STATES_DOLLAR ) );
719+
$this->assertEquals( 10050, WC_Stripe_Helper::get_stripe_amount( 10050, WC_Stripe_Currency_Code::JAPANESE_YEN ) );
720+
$this->assertEquals( 100, WC_Stripe_Helper::get_stripe_amount( 100.50, WC_Stripe_Currency_Code::JAPANESE_YEN ) );
721+
$this->assertEquals( 10050, WC_Stripe_Helper::get_stripe_amount( 100.50 ) );
722+
$this->assertIsInt( WC_Stripe_Helper::get_stripe_amount( 100.50, WC_Stripe_Currency_Code::UNITED_STATES_DOLLAR ) );
723+
}
724+
725+
/**
726+
* We store balance fee/net amounts coming from Stripe.
727+
* We need to make sure we format it correctly to be stored in WC.
728+
* These amounts are posted in lowest dominations.
729+
*/
730+
public function test_format_balance_fee() {
731+
$balance_fee1 = new stdClass();
732+
$balance_fee1->fee = 10500;
733+
$balance_fee1->net = 10000;
734+
$balance_fee1->currency = WC_Stripe_Currency_Code::UNITED_STATES_DOLLAR;
735+
736+
$this->assertEquals( 105.00, WC_Stripe_Helper::format_balance_fee( $balance_fee1, 'fee' ) );
737+
738+
$balance_fee2 = new stdClass();
739+
$balance_fee2->fee = 10500;
740+
$balance_fee2->net = 10000;
741+
$balance_fee2->currency = WC_Stripe_Currency_Code::JAPANESE_YEN;
742+
743+
$this->assertEquals( 10500, WC_Stripe_Helper::format_balance_fee( $balance_fee2, 'fee' ) );
744+
745+
$balance_fee3 = new stdClass();
746+
$balance_fee3->fee = 10500;
747+
$balance_fee3->net = 10000;
748+
$balance_fee3->currency = WC_Stripe_Currency_Code::UNITED_STATES_DOLLAR;
749+
750+
$this->assertEquals( 100.00, WC_Stripe_Helper::format_balance_fee( $balance_fee3, 'net' ) );
751+
752+
$balance_fee4 = new stdClass();
753+
$balance_fee4->fee = 10500;
754+
$balance_fee4->net = 10000;
755+
$balance_fee4->currency = WC_Stripe_Currency_Code::JAPANESE_YEN;
756+
757+
$this->assertEquals( 10000, WC_Stripe_Helper::format_balance_fee( $balance_fee4, 'net' ) );
758+
759+
$balance_fee5 = new stdClass();
760+
$balance_fee5->fee = 10500;
761+
$balance_fee5->net = 10000;
762+
$balance_fee5->currency = WC_Stripe_Currency_Code::UNITED_STATES_DOLLAR;
763+
764+
$this->assertEquals( 105.00, WC_Stripe_Helper::format_balance_fee( $balance_fee5 ) );
765+
766+
$this->assertIsString( WC_Stripe_Helper::format_balance_fee( $balance_fee5 ) );
767+
}
768+
769+
/**
770+
* Stripe requires statement_descriptor to be no longer than 22 characters.
771+
* In addition, it cannot contain <>"' special characters.
772+
*
773+
* @dataProvider statement_descriptor_sanitation_provider
774+
*/
775+
public function test_statement_descriptor_sanitation( $original, $expected ) {
776+
$this->assertEquals( $expected, WC_Stripe_Helper::clean_statement_descriptor( $original ) );
777+
}
778+
779+
public function statement_descriptor_sanitation_provider() {
780+
return [
781+
'removes \'' => [ 'Test\'s Store', 'Tests Store' ],
782+
'removes "' => [ 'Test " Store', 'Test Store' ],
783+
'removes <' => [ 'Test < Store', 'Test Store' ],
784+
'removes >' => [ 'Test > Store', 'Test Store' ],
785+
'removes /' => [ 'Test / Store', 'Test Store' ],
786+
'removes (' => [ 'Test ( Store', 'Test Store' ],
787+
'removes )' => [ 'Test ) Store', 'Test Store' ],
788+
'removes {' => [ 'Test { Store', 'Test Store' ],
789+
'removes }' => [ 'Test } Store', 'Test Store' ],
790+
'removes \\' => [ 'Test \\ Store', 'Test Store' ],
791+
'removes *' => [ 'Test * Store', 'Test Store' ],
792+
'keeps at most 22 chars' => [ 'Test\'s Store > Driving Course Range', 'Tests Store Driving C' ],
793+
'mixed length, \' and >' => [ 'Test\'s Store > Driving Course Range', 'Tests Store Driving C' ],
794+
'mixed length, \' and <' => [ 'Test\'s Store < Driving Course Range', 'Tests Store Driving C' ],
795+
'mixed length, \' and "' => [ 'Test\'s Store " Driving Course Range', 'Tests Store Driving C' ],
796+
'removes non-Latin' => [ 'Test-Storeシ Drהiving?12', 'Test-Store Driving?12' ],
797+
];
798+
}
799+
800+
public function test_turning_on_upe_with_no_stripe_legacy_payment_methods_enabled_will_not_turn_on_the_upe_gateway_and_default_to_card_and_link() {
801+
$this->upe_helper->enable_upe_feature_flag();
802+
803+
$stripe_settings = WC_Stripe_Helper::get_stripe_settings();
804+
$this->assertEquals( 'no', $stripe_settings['enabled'] );
805+
$this->assertEquals( 'no', $stripe_settings['upe_checkout_experience_enabled'] );
806+
807+
$stripe_settings['upe_checkout_experience_enabled'] = 'yes';
808+
WC_Stripe_Helper::update_main_stripe_settings( $stripe_settings );
809+
810+
$stripe_settings = WC_Stripe_Helper::get_stripe_settings();
811+
// Because no Stripe LPM's were enabled when UPE was enabled, the Stripe gateway is not enabled yet.
812+
$this->assertEquals( 'no', $stripe_settings['enabled'] );
813+
$this->assertEquals( 'yes', $stripe_settings['upe_checkout_experience_enabled'] );
814+
}
815+
816+
public function test_turning_on_upe_enables_the_correct_upe_methods_based_on_which_legacy_payment_methods_were_enabled() {
817+
update_option( 'woocommerce_currency', 'EUR' );
818+
$this->upe_helper->enable_upe_feature_flag();
819+
820+
// Enable sepa and iDEAL LPM gateways.
821+
update_option( 'woocommerce_stripe_sepa_settings', [ 'enabled' => 'yes' ] );
822+
update_option( 'woocommerce_stripe_ideal_settings', [ 'enabled' => 'yes' ] );
823+
$this->upe_helper->reload_payment_gateways();
824+
825+
// Initialize default stripe settings, turn on UPE.
826+
WC_Stripe_Helper::update_main_stripe_settings( [ 'upe_checkout_experience_enabled' => 'yes' ] );
827+
828+
$stripe_settings = WC_Stripe_Helper::get_stripe_settings();
829+
$this->assertEquals( 'yes', $stripe_settings['enabled'] );
830+
$this->assertEquals( 'yes', $stripe_settings['upe_checkout_experience_enabled'] );
831+
832+
// Make sure the SEPA and iDEAL LPMs were disabled.
833+
$sepa_settings = get_option( 'woocommerce_stripe_sepa_settings' );
834+
$this->assertEquals( 'no', $sepa_settings['enabled'] );
835+
$ideal_settings = get_option( 'woocommerce_stripe_ideal_settings' );
836+
$this->assertEquals( 'no', $ideal_settings['enabled'] );
837+
}
838+
839+
public function test_turning_off_upe_enables_the_correct_legacy_payment_methods_based_on_which_upe_payment_methods_were_enabled() {
840+
$this->upe_helper->enable_upe_feature_flag();
841+
842+
$stripe_settings = WC_Stripe_Helper::get_stripe_settings();
843+
844+
update_option( 'woocommerce_currency', 'EUR' );
845+
846+
// Disable sepa and iDEAL LPM gateways.
847+
update_option( 'woocommerce_stripe_sepa_settings', [ 'enabled' => 'no' ] );
848+
update_option( 'woocommerce_stripe_ideal_settings', [ 'enabled' => 'no' ] );
849+
850+
// Turn UPE on first.
851+
$stripe_settings['upe_checkout_experience_enabled'] = 'yes';
852+
WC_Stripe_Helper::update_main_stripe_settings( $stripe_settings );
853+
854+
$this->mock_payment_method_configurations( [ WC_Stripe_Payment_Methods::SEPA_DEBIT, WC_Stripe_Payment_Methods::IDEAL ] );
855+
856+
// Turn UPE off.
857+
$stripe_settings['upe_checkout_experience_enabled'] = 'no';
858+
WC_Stripe_Helper::update_main_stripe_settings( $stripe_settings );
859+
860+
// Check that the main 'stripe' gateway was disabled because the 'card' UPE method was not enabled.
861+
$stripe_settings = WC_Stripe_Helper::get_stripe_settings();
862+
$this->assertEquals( 'no', $stripe_settings['enabled'] );
863+
// Check that the correct LPMs were re-enabled.
864+
$sepa_settings = get_option( 'woocommerce_stripe_sepa_settings' );
865+
$this->assertEquals( 'yes', $sepa_settings['enabled'] );
866+
$ideal_settings = get_option( 'woocommerce_stripe_ideal_settings' );
867+
$this->assertEquals( 'yes', $ideal_settings['enabled'] );
868+
}
869+
870+
/**
871+
* Test that {@see WC_Stripe_Helper::is_webhook_url()} works as expected.
872+
*
873+
* @dataProvider is_webhook_url_provider
874+
* @covers WC_Stripe_Helper::is_webhook_url()
875+
*/
876+
public function test_is_webhook_url( $url, $webhook_url, $expected_result ) {
877+
$this->assertEquals( $expected_result, WC_Stripe_Helper::is_webhook_url( $url, $webhook_url ) );
878+
}
879+
880+
/**
881+
* Data provider for {@see test_is_webhook_url()}.
882+
*
883+
* @return array
884+
*/
885+
public function is_webhook_url_provider() {
886+
return [
887+
'webhook URLs with mismatched protocol should match' => [ 'https://example.com/?wc-api=wc_stripe', 'http://example.com/?wc-api=wc_stripe', true ],
888+
'webhook URLs with mismatched host should not match' => [ 'https://example.com/?wc-api=wc_stripe', 'https://test.example.com/?wc-api=wc_stripe', false ],
889+
'webhook URLs with mismatched path should not match' => [ 'https://example.com/foo?wc-api=wc_stripe', 'https://example.com/bar?wc-api=wc_stripe', false ],
890+
'webhook URL with empty path should match' => [ 'https://example.com/', 'https://example.com/?wc-api=wc_stripe', true ],
891+
'webhook URL with empty query string should match' => [ 'https://example.com/test/', 'https://example.com/test/', true ],
892+
'webhook URL with empty comparison query should not match' => [ 'https://example.com/test/?foo=bar', 'https://example.com/test/', false ],
893+
'webhook URL with missing parameter should not match' => [ 'https://example.com/test/?wc-api=wc_stripe', 'https://example.com/test/?wc-api=wc_stripe&foo=bar', false ],
894+
'webhook URL with wrong parameter should not match' => [ 'https://example.com/test/?wc-api=wc_stripe_BAD', 'https://example.com/test/?wc-api=wc_stripe', false ],
895+
'webhook URL with extra parameters should match' => [ 'https://example.com/test/?wc-api=wc_stripe&foo=bar', 'https://example.com/test/?wc-api=wc_stripe', true ],
896+
];
897+
}
701898
}

0 commit comments

Comments
 (0)