Skip to content

Commit 97b5270

Browse files
authored
Merge branch 'develop' into add/settings-synchronization
2 parents a02dec7 + 91353c5 commit 97b5270

32 files changed

+1483
-156
lines changed

changelog.txt

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
*** Changelog ***
22

33
= 9.4.0 - xxxx-xx-xx =
4+
* Dev - Introduces new payment method constants for the express methods: Google Pay, Apple Pay, Link, and Amazon Pay (backend version).
5+
* Dev - Introduces a new Stripe Order class to wrap Stripe-specific logic and data on the backend.
6+
* Dev - Improves how we handle express payment method titles by introducing new constants and methods to replace duplicate code.
7+
* Fix - Fixes an issue where the order signature retrieval method could throw a fatal error when the received order parameter is actually an OrderRefund object (instead of a WC_Order).
48
* Fix - Fixes a possible fatal error when a product added to the cart cannot be found (with Payment Request Buttons).
59
* Add - Add Amazon Pay payment method class.
610
* Tweak - Record a Tracks event when enabling/disabling SPE
711
* Tweak - Updates the Single Payment Element setting copy. Now it is labeled "Smart Checkout".
812
* Update - Enable/disable Amazon Pay by adding/removing it from the enabled payment methods list.
913
* Add - Add ACSS payment tokenization.
14+
* Update - Update payment method type for Amazon Pay orders.
15+
* Dev - Fetch Stripe settings with Stripe configuration API.
16+
17+
= 9.3.1 - 2025-03-14 =
18+
* Fix - Temporarily disables the subscriptions detached notice feature due to long loading times on stores with many subscriptions.
19+
* Fix - Update ACH capability check key
20+
* Fix - Update legacy checkout documentation links and deprecation notice display logic
21+
* Fix - Fixes an issue where the order signature retrieval method could throw a fatal error when the received order parameter is actually an OrderRefund object (instead of a WC_Order).
22+
* Fix - Fixes an error with the `filter_thankyou_order_received_text` filter when it does not receive a valid WC_Order instance.
1023

1124
= 9.3.0 - 2025-03-13 =
1225
* Dev - Adds a new README.md file to the plugin with specific development-focused instructions.
@@ -51,7 +64,7 @@
5164
* Fix - Prevent potential duplicate renewal charges by ensuring subscription integration hooks are only attached once per Gateway ID
5265
* Update - Update Amazon Pay icon to use image from WooCommerce Design Library.
5366
* Add - Show upcoming legacy checkout experience deprecation notice.
54-
* Dev - Fetch Stripe settings with Stripe configuration API.
67+
* Fix - Fix variable dump in ACH customer error message when retrying a payment.
5568

5669
= 9.2.0 - 2025-02-13 =
5770
* Fix - Fix missing product_id parameter for the express checkout add-to-cart operation.

client/components/payment-method-capability-status-pill/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ const IconComponent = ( { children, ...props } ) => (
4747

4848
const PaymentMethodCapabilityStatusPill = ( { id, label } ) => {
4949
const capabilities = useGetCapabilities();
50-
const capabilityStatus = capabilities[ `${ id }_payments` ];
50+
const capabilityStatus =
51+
id === 'us_bank_account'
52+
? capabilities[ `${ id }_ach_payments` ]
53+
: capabilities[ `${ id }_payments` ];
5154

5255
return (
5356
<>

client/components/payment-method-deprecation-pill/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const PaymentMethodDeprecationPill = () => {
6060
components: {
6161
currencySettingsLink: (
6262
<StyledLink
63-
href="https://support.stripe.com/topics/shutdown-of-the-legacy-sources-api-for-non-card-payment-methods"
63+
href="https://woocommerce.com/document/stripe/admin-experience/legacy-checkout-experience/"
6464
target="_blank"
6565
rel="noreferrer"
6666
onClick={ ( ev ) => {

client/data/account/actions.js

+19-7
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@ export function* refreshAccount() {
4040

4141
// Check new payment methods available for account.
4242
const newPaymentMethods = activeCapabilitiesAfterRefresh.filter(
43-
( paymentMethod ) =>
44-
! activeCapabilitiesBeforeRefresh.includes( paymentMethod ) &&
45-
PaymentMethodsMap[
46-
paymentMethod.replace( '_payments', '' )
47-
] !== undefined
43+
( capability ) => {
44+
const paymentMethodFromCapability =
45+
capability === 'us_bank_account_ach_payments'
46+
? 'us_bank_account'
47+
: capability.replace( '_payments', '' );
48+
49+
return (
50+
! activeCapabilitiesBeforeRefresh.includes( capability ) &&
51+
PaymentMethodsMap[ paymentMethodFromCapability ] !==
52+
undefined
53+
);
54+
}
4855
);
4956

5057
// If there are new payment methods available, show a toast informing the user.
@@ -57,9 +64,14 @@ export function* refreshAccount() {
5764
'woocommerce-gateway-stripe'
5865
),
5966
newPaymentMethods
60-
.map( ( method ) => {
67+
.map( ( capability ) => {
68+
const paymentMethodFromCapability =
69+
capability === 'us_bank_account_ach_payments'
70+
? 'us_bank_account'
71+
: capability.replace( '_payments', '' );
72+
6173
return PaymentMethodsMap[
62-
method.replace( '_payments', '' )
74+
paymentMethodFromCapability
6375
].label;
6476
} )
6577
.join( ', ' )

client/settings/general-settings-section/payment-methods-unavailable-list.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ const PaymentMethodsUnavailableList = () => {
1313
const capabilities = useGetCapabilities();
1414
const upePaymentMethodIds = useGetAvailablePaymentMethodIds();
1515
const unavailablePaymentMethodIds = upePaymentMethodIds
16-
.filter(
17-
( methodId ) =>
18-
! capabilities.hasOwnProperty( `${ methodId }_payments` )
19-
)
16+
.filter( ( methodId ) => {
17+
const capabilityId =
18+
methodId === 'us_bank_account'
19+
? `${ methodId }_ach_payments`
20+
: `${ methodId }_payments`;
21+
return ! capabilities.hasOwnProperty( capabilityId );
22+
} )
2023
.filter(
2124
( id ) =>
2225
! [ PAYMENT_METHOD_LINK, PAYMENT_METHOD_AMAZON_PAY ].includes(

client/settings/payment-settings/promotional-banner-section.js

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ const PromotionalBannerSection = ( {
9999
'woocommerce-gateway-stripe'
100100
)
101101
);
102+
103+
window.location.reload();
102104
} catch ( err ) {
103105
createErrorNotice(
104106
__(

includes/abstracts/abstract-wc-stripe-payment-gateway.php

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<?php
2+
3+
use Automattic\WooCommerce\Admin\Overrides\OrderRefund;
4+
25
if ( ! defined( 'ABSPATH' ) ) {
36
exit;
47
}
@@ -602,7 +605,12 @@ public function process_response( $response, $order ) {
602605

603606
if ( 'failed' === $response->status ) {
604607
$localized_message = __( 'Payment processing failed. Please retry.', 'woocommerce-gateway-stripe' );
605-
$order->add_order_note( $localized_message );
608+
$order->add_order_note(
609+
property_exists( $response, 'outcome' ) && isset( $response->outcome->seller_message )
610+
? $response->outcome->seller_message
611+
: $localized_message
612+
);
613+
606614
throw new WC_Stripe_Exception( print_r( $response, true ), $localized_message );
607615
}
608616
} else {
@@ -2389,10 +2397,12 @@ public function get_balance_transaction_id_from_charge( $charge ) {
23892397
*
23902398
* This signature is included as metadata in Stripe requests and used to identify the order when webhooks are received.
23912399
*
2392-
* @param WC_Order $order The Order object.
2400+
* @param WC_Order|OrderRefund $order The Order object.
23932401
* @return string The order's unique signature. Format: order_id:md5(order_id-order_key-customer_id-order_total).
23942402
*/
23952403
protected function get_order_signature( $order ) {
2404+
$order = ! is_a( $order, 'WC_Order' ) ? wc_get_order( $order ) : $order;
2405+
23962406
$signature = [
23972407
absint( $order->get_id() ),
23982408
$order->get_order_key(),

includes/admin/class-wc-stripe-admin-notices.php

+13-6
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public function admin_notices() {
104104
public static function display_legacy_deprecation_notice( $plugin_file ) {
105105
global $wp_list_table;
106106

107-
if ( version_compare( WC_STRIPE_VERSION, '9.3.0', '!=' ) || WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ) {
107+
if ( WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ) {
108108
return;
109109
}
110110

@@ -372,7 +372,7 @@ public function stripe_check_environment() {
372372

373373
if ( empty( $legacy_deprecation_notice ) ) {
374374
// Show legacy deprecation notice in version 9.3.0 if legacy checkout experience is enabled.
375-
if ( ! WC_Stripe_Feature_Flags::is_upe_checkout_enabled() && version_compare( WC_STRIPE_VERSION, '9.3.0', '==' ) ) {
375+
if ( ! WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ) {
376376
$setting_link = $this->get_setting_link();
377377
$message = sprintf(
378378
/* translators: 1) HTML anchor open tag 2) HTML anchor closing tag */
@@ -469,22 +469,30 @@ public function payment_methods_check_environment() {
469469
* @return void
470470
*/
471471
public function subscriptions_check_environment() {
472+
// @todo Temporarily disabling this due long load times on stores with too many subscriptions.
473+
return;
474+
475+
$show_notice = get_option( 'wc_stripe_show_subscriptions_notice' );
476+
if ( 'yes' !== $show_notice ) {
477+
return;
478+
}
479+
472480
$detached_messages = '';
473481
$subscriptions = WC_Stripe_Subscriptions_Helper::get_detached_subscriptions();
474482
foreach ( $subscriptions as $subscription ) {
475483
$customer_payment_method_link = sprintf(
476484
'<a href="%s">%s</a>',
477485
esc_url( $subscription['change_payment_method_url'] ),
478486
esc_html(
479-
/* translators: this is a text for a link pointing to the customer's payment method page */
487+
/* translators: this is a text for a link pointing to the customer's payment method page */
480488
__( 'this link &rarr;', 'woocommerce-gateway-stripe' )
481489
)
482490
);
483491
$customer_stripe_page = sprintf(
484492
'<a href="%s">%s</a>',
485493
esc_url( self::STRIPE_CUSTOMER_PAGE_BASE_URL . $subscription['customer_id'] ),
486494
esc_html(
487-
/* translators: this is a text for a link pointing to the customer's page on Stripe */
495+
/* translators: this is a text for a link pointing to the customer's page on Stripe */
488496
__( 'here &rarr;', 'woocommerce-gateway-stripe' )
489497
)
490498
);
@@ -496,8 +504,7 @@ public function subscriptions_check_environment() {
496504
$customer_stripe_page
497505
);
498506
}
499-
$show_notice = get_option( 'wc_stripe_show_subscriptions_notice' );
500-
if ( ! empty( $detached_messages ) && 'no' !== $show_notice ) {
507+
if ( ! empty( $detached_messages ) ) {
501508
$this->add_admin_notice( 'subscriptions', 'notice notice-error', $detached_messages, true );
502509
}
503510
}

includes/admin/class-wc-stripe-settings-controller.php

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ public function admin_scripts( $hook_suffix ) {
237237
'is_acss_enabled' => WC_Stripe_Feature_Flags::is_acss_lpm_enabled(),
238238
'is_bacs_enabled' => WC_Stripe_Feature_Flags::is_bacs_lpm_enabled(),
239239
'is_blik_enabled' => WC_Stripe_Feature_Flags::is_blik_lpm_enabled(),
240+
'is_becs_debit_enabled' => WC_Stripe_Feature_Flags::is_becs_debit_lpm_enabled(),
240241
'stripe_oauth_url' => $oauth_url,
241242
'stripe_test_oauth_url' => $test_oauth_url,
242243
'show_customization_notice' => get_option( 'wc_stripe_show_customization_notice', 'yes' ) === 'yes' ? true : false,

includes/class-wc-stripe-blocks-support.php

+16-8
Original file line numberDiff line numberDiff line change
@@ -515,14 +515,22 @@ public function add_stripe_intents( PaymentContext $context, PaymentResult &$res
515515
* @param string $payment_request_type The payment request type used for payment.
516516
*/
517517
private function add_order_meta( \WC_Order $order, $payment_request_type ) {
518-
if ( 'apple_pay' === $payment_request_type ) {
519-
$order->set_payment_method_title( 'Apple Pay (Stripe)' );
520-
$order->save();
521-
} elseif ( 'google_pay' === $payment_request_type ) {
522-
$order->set_payment_method_title( 'Google Pay (Stripe)' );
523-
$order->save();
524-
} elseif ( 'payment_request_api' === $payment_request_type ) {
525-
$order->set_payment_method_title( 'Payment Request (Stripe)' );
518+
$payment_method_title = '';
519+
switch ( $payment_request_type ) {
520+
case WC_Stripe_Payment_Methods::APPLE_PAY:
521+
$payment_method_title = WC_Stripe_Payment_Methods::APPLE_PAY_LABEL;
522+
break;
523+
case WC_Stripe_Payment_Methods::GOOGLE_PAY:
524+
$payment_method_title = WC_Stripe_Payment_Methods::GOOGLE_PAY_LABEL;
525+
break;
526+
case 'payment_request_api':
527+
$payment_method_title = WC_Stripe_Payment_Methods::PAYMENT_REQUEST_LABEL;
528+
break;
529+
}
530+
531+
if ( $payment_method_title ) {
532+
$payment_method_suffix = WC_Stripe_Express_Checkout_Helper::get_payment_method_title_suffix();
533+
$order->set_payment_method_title( $payment_method_title . $payment_method_suffix );
526534
$order->save();
527535
}
528536
}

includes/class-wc-stripe-feature-flags.php

+19-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class WC_Stripe_Feature_Flags {
1212
const LPM_ACSS_FEATURE_FLAG_NAME = '_wcstripe_feature_lpm_acss';
1313
const LPM_BACS_FEATURE_FLAG_NAME = '_wcstripe_feature_lpm_bacs';
1414
const LPM_BLIK_FEATURE_FLAG_NAME = '_wcstripe_feature_lpm_blik';
15+
const LPM_BECS_DEBIT_FEATURE_FLAG_NAME = '_wcstripe_feature_lpm_becs_debit';
1516

1617
/**
1718
* Map of feature flag option names => their default "yes"/"no" value.
@@ -20,13 +21,14 @@ class WC_Stripe_Feature_Flags {
2021
* @var array
2122
*/
2223
protected static $feature_flags = [
23-
'_wcstripe_feature_upe' => 'yes',
24-
self::ECE_FEATURE_FLAG_NAME => 'yes',
25-
self::AMAZON_PAY_FEATURE_FLAG_NAME => 'no',
26-
self::SPE_FEATURE_FLAG_NAME => 'no',
27-
self::LPM_ACH_FEATURE_FLAG_NAME => 'yes',
28-
self::LPM_ACSS_FEATURE_FLAG_NAME => 'no',
29-
self::LPM_BACS_FEATURE_FLAG_NAME => 'yes',
24+
'_wcstripe_feature_upe' => 'yes',
25+
self::ECE_FEATURE_FLAG_NAME => 'yes',
26+
self::AMAZON_PAY_FEATURE_FLAG_NAME => 'no',
27+
self::SPE_FEATURE_FLAG_NAME => 'no',
28+
self::LPM_ACH_FEATURE_FLAG_NAME => 'yes',
29+
self::LPM_ACSS_FEATURE_FLAG_NAME => 'no',
30+
self::LPM_BACS_FEATURE_FLAG_NAME => 'yes',
31+
self::LPM_BECS_DEBIT_FEATURE_FLAG_NAME => 'no',
3032
];
3133

3234
/**
@@ -99,6 +101,16 @@ public static function is_blik_lpm_enabled(): bool {
99101
return 'yes' === self::get_option_with_default( self::LPM_BLIK_FEATURE_FLAG_NAME );
100102
}
101103

104+
/**
105+
* Checks whether BECS Debit LPM (Local Payment Method) feature flag is enabled.
106+
* https://docs.stripe.com/payments/au-becs-debit.
107+
*
108+
* @return bool
109+
*/
110+
public static function is_becs_debit_lpm_enabled(): bool {
111+
return 'yes' === self::get_option_with_default( self::LPM_BECS_DEBIT_FEATURE_FLAG_NAME );
112+
}
113+
102114
/**
103115
* Checks whether Stripe ECE (Express Checkout Element) feature flag is enabled.
104116
* Express checkout buttons are rendered with either ECE or PRB depending on this feature flag.

includes/class-wc-stripe-helper.php

+27-2
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ public static function filter_payment_methods_with_capabilities( $payment_method
737737
$payment_method_ids_with_capability = [];
738738

739739
foreach ( $payment_method_ids as $payment_method_id ) {
740-
$key = $payment_method_id . '_payments';
740+
$key = self::get_payment_method_capability_id( $payment_method_id );
741741
// Check if the payment method has capabilities set in the account data.
742742
// Generally the key is the payment method id appended with '_payments' (i.e. 'card_payments', 'sepa_debit_payments', 'klarna_payments').
743743
// In some cases, the Stripe account might have the legacy key set. For example, for Klarna, the legacy key is 'klarna'.
@@ -1490,7 +1490,17 @@ public static function get_european_economic_area_countries() {
14901490
* @return bool Whether the payment method allows manual capture.
14911491
*/
14921492
public static function payment_method_allows_manual_capture( string $payment_method_id ) {
1493-
return in_array( $payment_method_id, [ 'stripe', 'stripe_affirm', 'stripe_klarna', 'stripe_afterpay_clearpay' ], true );
1493+
return in_array(
1494+
$payment_method_id,
1495+
[
1496+
'stripe',
1497+
'stripe_affirm',
1498+
'stripe_klarna',
1499+
'stripe_afterpay_clearpay',
1500+
'stripe_amazon_pay',
1501+
],
1502+
true
1503+
);
14941504
}
14951505

14961506
/**
@@ -1653,4 +1663,19 @@ public static function maybe_log_ip_issues( $ip_address ) {
16531663
WC_Stripe_Logger::log( 'Invalid IP address detected. Data: ' . wp_json_encode( $log_data ) );
16541664
}
16551665
}
1666+
1667+
/**
1668+
* Return capability ID based on payment method ID.
1669+
*
1670+
* @param string $payment_method_id The payment method ID.
1671+
* @return string The capability ID.
1672+
*/
1673+
public static function get_payment_method_capability_id( $payment_method_id ) {
1674+
// "_payments" is a suffix that comes from Stripe API, except when it is "transfers" or ACH.
1675+
if ( WC_Stripe_UPE_Payment_Method_ACH::STRIPE_ID === $payment_method_id ) {
1676+
return $payment_method_id . '_ach_payments';
1677+
}
1678+
1679+
return $payment_method_id . '_payments';
1680+
}
16561681
}

includes/class-wc-stripe-intent-controller.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ public function update_order_status_ajax() {
636636
wp_send_json_error(
637637
[
638638
'error' => [
639-
'message' => $e->getMessage(),
639+
'message' => $e->getLocalizedMessage(),
640640
],
641641
]
642642
);

0 commit comments

Comments
 (0)