From 8467c25ddcc0855d8b00567cf6677b76ed099e25 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Mon, 4 Aug 2025 17:41:45 -0300 Subject: [PATCH 1/5] Allow purchase of free trials with ECE --- .../class-wc-stripe-express-checkout-helper.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/includes/payment-methods/class-wc-stripe-express-checkout-helper.php b/includes/payment-methods/class-wc-stripe-express-checkout-helper.php index eec5c79f4b..a7ffa2a52e 100644 --- a/includes/payment-methods/class-wc-stripe-express-checkout-helper.php +++ b/includes/payment-methods/class-wc-stripe-express-checkout-helper.php @@ -684,10 +684,9 @@ public function should_show_express_checkout_button() { return false; } - // Don't show in the product page if the product price is 0. - // ToDo: support free trials. Free trials should be supported if the product does not require shipping. - if ( $is_product && $product && 0.0 === (float) $product->get_price() ) { - WC_Stripe_Logger::log( 'Stripe Express Checkout does not support free products.' ); + // Don't show in the product page if the product price is 0 and the product requires shipping. + if ( $is_product && $product && 0.0 === (float) $product->get_price() && $this->product_or_cart_needs_shipping() ) { + WC_Stripe_Logger::log( 'Stripe Express Checkout does not support free products that requires shipping.' ); return false; } From c17d9de7c0c55b4687bc34b7c7e9a4647d1c08da Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Mon, 4 Aug 2025 17:44:55 -0300 Subject: [PATCH 2/5] Changelog and readme entries --- changelog.txt | 1 + readme.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/changelog.txt b/changelog.txt index 71de87dbf4..f7ffd72493 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ *** Changelog *** = 9.8.0 - xxxx-xx-xx = +* Add - Allow the purchase of free trials using the Express Payment methods when the product does not require shipping * Add - A new pill to the payment methods page to indicate the credit card requirement when the Optimized Checkout feature is enabled * Add - Tracks the toggle of the Optimized Checkout feature in the promotional banner * Fix - Force the card payment method to be enabled when the Optimized Checkout is enabled in the merchant's Payment Method Configuration diff --git a/readme.txt b/readme.txt index 55d04cf08a..a447edfb2d 100644 --- a/readme.txt +++ b/readme.txt @@ -111,6 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o == Changelog == = 9.8.0 - xxxx-xx-xx = +* Add - Allow the purchase of free trials using the Express Payment methods when the product does not require shipping * Add - A new pill to the payment methods page to indicate the credit card requirement when the Optimized Checkout feature is enabled * Add - Tracks the toggle of the Optimized Checkout feature in the promotional banner * Fix - Force the card payment method to be enabled when the Optimized Checkout is enabled in the merchant's Payment Method Configuration From 33e176ce6ce59edae2109d77cd03c3234940b3f1 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 5 Aug 2025 10:05:32 -0300 Subject: [PATCH 3/5] Unit tests --- ...WC_Stripe_Express_Checkout_Helper_Test.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/phpunit/PaymentMethods/WC_Stripe_Express_Checkout_Helper_Test.php b/tests/phpunit/PaymentMethods/WC_Stripe_Express_Checkout_Helper_Test.php index d00e703aa2..bf81db887a 100644 --- a/tests/phpunit/PaymentMethods/WC_Stripe_Express_Checkout_Helper_Test.php +++ b/tests/phpunit/PaymentMethods/WC_Stripe_Express_Checkout_Helper_Test.php @@ -314,6 +314,86 @@ public function test_hides_ece_if_stripe_gateway_unavailable() { WC()->payment_gateways()->payment_gateways = $original_gateways; } + /** + * Test should_show_express_checkout_button, free trial logic. + * + * @return void + */ + public function test_hides_ece_if_free_trial_requires_shipping() { + $this->set_up_shipping_methods(); + + $wc_stripe_ece_helper_mock = $this->createPartialMock( + WC_Stripe_Express_Checkout_Helper::class, + [ + 'is_product', + 'get_product', + 'allowed_items_in_cart', + 'should_show_ece_on_cart_page', + 'should_show_ece_on_checkout_page', + ], + ); + + $wc_stripe_ece_helper_mock->expects( $this->any() )->method( 'is_product' )->willReturn( true ); + $wc_stripe_ece_helper_mock->expects( $this->any() )->method( 'allowed_items_in_cart' )->willReturn( true ); + $wc_stripe_ece_helper_mock->expects( $this->any() )->method( 'should_show_ece_on_cart_page' )->willReturn( true ); + $wc_stripe_ece_helper_mock->expects( $this->any() )->method( 'should_show_ece_on_checkout_page' )->willReturn( true ); + $wc_stripe_ece_helper_mock->testmode = true; + + if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { + define( 'WOOCOMMERCE_CHECKOUT', true ); + } + + // Ensure that the 'stripe' gateway is available. + $original_gateways = WC()->payment_gateways()->payment_gateways; + WC()->payment_gateways()->payment_gateways = [ + 'stripe' => new WC_Gateway_Stripe(), + ]; + + update_option( 'woocommerce_calc_taxes', 'no' ); + + // Should show, as free virtual products does not require shipping. + $virtual_product = WC_Helper_Product::create_simple_product(); + $virtual_product->set_virtual( true ); + $virtual_product->set_tax_status( 'none' ); + $virtual_product->set_price( 0 ); + $virtual_product->save(); + + WC()->session->init(); + WC()->cart->empty_cart(); + + WC()->cart->add_to_cart( $virtual_product->get_id(), 1 ); + $wc_stripe_ece_helper_mock + ->expects( $this->any() ) + ->method( 'get_product' ) + ->willReturn( $virtual_product ); + + $this->assertTrue( $wc_stripe_ece_helper_mock->should_show_express_checkout_button() ); + + // Should hide if the free product requires shipping. + $shippable_product = WC_Helper_Product::create_simple_product(); + $shippable_product->set_virtual( false ); + $shippable_product->set_tax_status( 'none' ); + $shippable_product->save(); + + WC()->session->init(); + WC()->cart->empty_cart(); + + WC()->cart->add_to_cart( $shippable_product->get_id(), 1 ); + $wc_stripe_ece_helper_mock + ->expects( $this->any() ) + ->method( 'get_product' ) + ->willReturn( $shippable_product ); + + $this->assertFalse( $wc_stripe_ece_helper_mock->should_show_express_checkout_button() ); + + // Restore original settings. + WC()->cart->empty_cart(); + WC()->session->cleanup_sessions(); + WC()->payment_gateways()->payment_gateways = $original_gateways; + + update_option( 'woocommerce_calc_taxes', 'yes' ); + } + /** * Test for get_checkout_data(). */ From 63d45fdf37dafc8fa4e9f98196b800efdbd25c0a Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 5 Aug 2025 17:56:51 -0300 Subject: [PATCH 4/5] Remove condition inside canMakePayment --- client/blocks/express-checkout/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/blocks/express-checkout/index.js b/client/blocks/express-checkout/index.js index a297842cfb..6442bc92c4 100644 --- a/client/blocks/express-checkout/index.js +++ b/client/blocks/express-checkout/index.js @@ -83,10 +83,6 @@ const expressCheckoutElement = ( expressPaymentMethod, api ) => { ); const edit = getEditorElement( expressPaymentMethod ); const canMakePayment = ( { cart } ) => { - if ( parseFloat( cart.cartTotals.total_price ) === 0.0 ) { - return false; - } - if ( ! getBlocksConfiguration()?.shouldShowExpressCheckoutButton ) { return false; } From cdca3511efeece6b7f7d141368dfc733d1db0380 Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Tue, 19 Aug 2025 15:48:55 -0300 Subject: [PATCH 5/5] Temporary changes to debug --- client/blocks/express-checkout/index.js | 2 ++ client/express-checkout/utils/index.js | 1 - .../payment-methods/class-wc-stripe-express-checkout-helper.php | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/client/blocks/express-checkout/index.js b/client/blocks/express-checkout/index.js index 6442bc92c4..c40a4feba1 100644 --- a/client/blocks/express-checkout/index.js +++ b/client/blocks/express-checkout/index.js @@ -83,6 +83,8 @@ const expressCheckoutElement = ( expressPaymentMethod, api ) => { ); const edit = getEditorElement( expressPaymentMethod ); const canMakePayment = ( { cart } ) => { + return true; + if ( ! getBlocksConfiguration()?.shouldShowExpressCheckoutButton ) { return false; } diff --git a/client/express-checkout/utils/index.js b/client/express-checkout/utils/index.js index 7dab154c39..f701b35a50 100644 --- a/client/express-checkout/utils/index.js +++ b/client/express-checkout/utils/index.js @@ -105,7 +105,6 @@ export const getExpressCheckoutButtonAppearance = () => { return { variables: { borderRadius: `${ - getExpressCheckoutData( 'button' )?.radius || getDefaultBorderRadius() }px`, spacingUnit: '6px', diff --git a/includes/payment-methods/class-wc-stripe-express-checkout-helper.php b/includes/payment-methods/class-wc-stripe-express-checkout-helper.php index 1851a10c12..e03a4a8912 100644 --- a/includes/payment-methods/class-wc-stripe-express-checkout-helper.php +++ b/includes/payment-methods/class-wc-stripe-express-checkout-helper.php @@ -622,6 +622,8 @@ public function is_page_supported() { * @return boolean True if express checkout elements are supported on current page, false otherwise */ public function should_show_express_checkout_button() { + return true; + // Bail if account is not connected. if ( ! WC_Stripe::get_instance()->connect->is_connected() ) { WC_Stripe_Logger::log( 'Account is not connected.' );