Skip to content

Commit c7fe7c5

Browse files
Mayishamalithsen
authored andcommitted
ECE: Fix state mapping (#4357)
* create ajax for normalizing addresses on server side * use normalized address in checkout * mock function in js tests * remove unused deprecated create_order method * add changelog * rename method
1 parent 474ed6c commit c7fe7c5

File tree

8 files changed

+89
-69
lines changed

8 files changed

+89
-69
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.5.3 - xxxx-xx-xx =
4+
* Fix - Reimplement mapping of Express Checkout state values to align with WooCommerce's expected state formats
45
* Tweak - Track charge completed via webhooks in order notes
56

67
= 9.5.2 - 2025-05-22 =

client/api/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,23 @@ export default class WCStripeAPI {
497497
);
498498
}
499499

500+
/**
501+
* Normalizes address fields in WooCommerce supported format.
502+
*
503+
* @param {Object} billingAddress Billing address.
504+
* @param {Object} shippingAddress Shipping address.
505+
* @return {Promise} Promise for the request to the server.
506+
*/
507+
expressCheckoutNormalizeAddress( billingAddress, shippingAddress ) {
508+
return this.request( getExpressCheckoutAjaxURL( 'normalize_address' ), {
509+
security: getExpressCheckoutData( 'nonce' )?.normalize_address,
510+
data: {
511+
billing_address: billingAddress,
512+
shipping_address: shippingAddress,
513+
},
514+
} );
515+
}
516+
500517
/**
501518
* Get cart items and total amount.
502519
*

client/express-checkout/__tests__/event-handler.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ describe( 'Express checkout event handlers', () => {
219219

220220
beforeEach( () => {
221221
api = {
222+
expressCheckoutNormalizeAddress: jest.fn(),
222223
expressCheckoutECECreateOrder: jest.fn(),
223224
expressCheckoutECEPayForOrder: jest.fn(),
224225
confirmIntent: jest.fn(),

client/express-checkout/payment-flow.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,23 +148,33 @@ const processOrder = async ( {
148148
orderDetails = {},
149149
} ) => {
150150
let orderResponse;
151+
152+
const normalizedOrderData = normalizeOrderData( {
153+
event,
154+
paymentMethodId,
155+
confirmationTokenId,
156+
} );
157+
158+
const normalizedAddress = await api.expressCheckoutNormalizeAddress(
159+
normalizedOrderData.billing_address,
160+
normalizedOrderData.shipping_address
161+
);
162+
163+
if ( normalizedAddress ) {
164+
normalizedOrderData.billing_address = normalizedAddress.billing_address;
165+
normalizedOrderData.shipping_address =
166+
normalizedAddress.shipping_address;
167+
}
168+
151169
if ( order ) {
152170
orderResponse = await api.expressCheckoutECEPayForOrder(
153171
order,
154172
orderDetails,
155-
normalizeOrderData( {
156-
event,
157-
paymentMethodId,
158-
confirmationTokenId,
159-
} )
173+
normalizedOrderData
160174
);
161175
} else {
162176
orderResponse = await api.expressCheckoutECECreateOrder(
163-
normalizeOrderData( {
164-
event,
165-
paymentMethodId,
166-
confirmationTokenId,
167-
} )
177+
normalizedOrderData
168178
);
169179
}
170180

includes/payment-methods/class-wc-stripe-express-checkout-ajax-handler.php

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public function __construct( WC_Stripe_Express_Checkout_Helper $express_checkout
3131
public function init() {
3232
add_action( 'wc_ajax_wc_stripe_get_cart_details', [ $this, 'ajax_get_cart_details' ] );
3333
add_action( 'wc_ajax_wc_stripe_get_shipping_options', [ $this, 'ajax_get_shipping_options' ] );
34+
add_action( 'wc_ajax_wc_stripe_normalize_address', [ $this, 'ajax_normalize_address' ] );
3435
add_action( 'wc_ajax_wc_stripe_update_shipping_method', [ $this, 'ajax_update_shipping_method' ] );
35-
add_action( 'wc_ajax_wc_stripe_create_order', [ $this, 'ajax_create_order' ] );
3636
add_action( 'wc_ajax_wc_stripe_add_to_cart', [ $this, 'ajax_add_to_cart' ] );
3737
add_action( 'wc_ajax_wc_stripe_get_selected_product_data', [ $this, 'ajax_get_selected_product_data' ] );
3838
add_action( 'wc_ajax_wc_stripe_clear_cart', [ $this, 'ajax_clear_cart' ] );
@@ -140,6 +140,21 @@ public function ajax_clear_cart() {
140140
exit;
141141
}
142142

143+
/**
144+
* Normalizes address fields in WooCommerce supported format.
145+
*/
146+
public function ajax_normalize_address() {
147+
check_ajax_referer( 'wc-stripe-express-checkout-normalize-address', 'security' );
148+
149+
$data = filter_input( INPUT_POST, 'data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
150+
151+
// Normalizes billing and shipping state values.
152+
$normalized_data = $this->express_checkout_helper->normalize_state( $data );
153+
$normalized_data = $this->express_checkout_helper->fix_address_fields_mapping( $normalized_data );
154+
155+
wp_send_json( $normalized_data );
156+
}
157+
143158
/**
144159
* Get shipping options.
145160
*
@@ -297,44 +312,6 @@ public function ajax_get_selected_product_data() {
297312
}
298313
}
299314

300-
/**
301-
* Create order. Security is handled by WC.
302-
*
303-
* @deprecated 9.2.0 Payment is processed using the Blocks API by default.
304-
*/
305-
public function ajax_create_order() {
306-
_deprecated_function( __METHOD__, '9.2.0' );
307-
try {
308-
if ( WC()->cart->is_empty() ) {
309-
wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
310-
}
311-
312-
if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
313-
define( 'WOOCOMMERCE_CHECKOUT', true );
314-
}
315-
316-
$this->express_checkout_helper->fix_address_fields_mapping();
317-
318-
// Normalizes billing and shipping state values.
319-
$this->express_checkout_helper->normalize_state();
320-
321-
// In case the state is required, but is missing, add a more descriptive error notice.
322-
$this->express_checkout_helper->validate_state();
323-
324-
WC()->checkout()->process_checkout();
325-
} catch ( Exception $e ) {
326-
WC_Stripe_Logger::log( 'Failed to create order for express checkout payment: ' . $e );
327-
328-
$response = [
329-
'result' => 'error',
330-
'messages' => $e->getMessage(),
331-
];
332-
wp_send_json( $response, 400 );
333-
}
334-
335-
die( 0 );
336-
}
337-
338315
/**
339316
* Log errors coming from express checkout elements
340317
*/

includes/payment-methods/class-wc-stripe-express-checkout-element.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ public function javascript_params() {
196196
'nonce' => [
197197
'payment' => wp_create_nonce( 'wc-stripe-express-checkout' ),
198198
'shipping' => wp_create_nonce( 'wc-stripe-express-checkout-shipping' ),
199+
'normalize_address' => wp_create_nonce( 'wc-stripe-express-checkout-normalize-address' ),
199200
'get_cart_details' => wp_create_nonce( 'wc-stripe-get-cart-details' ),
200201
'update_shipping' => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
201202
'checkout' => wp_create_nonce( 'woocommerce-process_checkout' ),

includes/payment-methods/class-wc-stripe-express-checkout-helper.php

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -971,12 +971,16 @@ public function update_shipping_method( $shipping_methods ) {
971971

972972
/**
973973
* Normalizes billing and shipping state fields.
974+
*
975+
* @param array $data Address data.
976+
*
977+
* @return array Normalized address data.
974978
*/
975-
public function normalize_state() {
976-
$billing_country = ! empty( $_POST['billing_country'] ) ? wc_clean( wp_unslash( $_POST['billing_country'] ) ) : '';
977-
$shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( wp_unslash( $_POST['shipping_country'] ) ) : '';
978-
$billing_state = ! empty( $_POST['billing_state'] ) ? wc_clean( wp_unslash( $_POST['billing_state'] ) ) : '';
979-
$shipping_state = ! empty( $_POST['shipping_state'] ) ? wc_clean( wp_unslash( $_POST['shipping_state'] ) ) : '';
979+
public function normalize_state( $data ) {
980+
$billing_country = ! empty( $data['billing_address']['country'] ) ? wc_clean( wp_unslash( $data['billing_address']['country'] ) ) : '';
981+
$shipping_country = ! empty( $data['shipping_address']['country'] ) ? wc_clean( wp_unslash( $data['shipping_address']['country'] ) ) : '';
982+
$billing_state = ! empty( $data['billing_address']['state'] ) ? wc_clean( wp_unslash( $data['billing_address']['state'] ) ) : '';
983+
$shipping_state = ! empty( $data['shipping_address']['state'] ) ? wc_clean( wp_unslash( $data['shipping_address']['state'] ) ) : '';
980984

981985
// Due to a bug in Apple Pay, the "Region" part of a Hong Kong address is delivered in
982986
// `shipping_postcode`, so we need some special case handling for that. According to
@@ -1000,7 +1004,7 @@ public function normalize_state() {
10001004
include_once WC_STRIPE_PLUGIN_PATH . '/includes/constants/class-wc-stripe-hong-kong-states.php';
10011005

10021006
if ( ! WC_Stripe_Hong_Kong_States::is_valid_state( strtolower( $billing_state ) ) ) {
1003-
$billing_postcode = ! empty( $_POST['billing_postcode'] ) ? wc_clean( wp_unslash( $_POST['billing_postcode'] ) ) : '';
1007+
$billing_postcode = ! empty( $data['billing_address']['postcode'] ) ? wc_clean( wp_unslash( $data['billing_address']['postcode'] ) ) : '';
10041008
if ( WC_Stripe_Hong_Kong_States::is_valid_state( strtolower( $billing_postcode ) ) ) {
10051009
$billing_state = $billing_postcode;
10061010
}
@@ -1010,7 +1014,7 @@ public function normalize_state() {
10101014
include_once WC_STRIPE_PLUGIN_PATH . '/includes/constants/class-wc-stripe-hong-kong-states.php';
10111015

10121016
if ( ! WC_Stripe_Hong_Kong_States::is_valid_state( strtolower( $shipping_state ) ) ) {
1013-
$shipping_postcode = ! empty( $_POST['shipping_postcode'] ) ? wc_clean( wp_unslash( $_POST['shipping_postcode'] ) ) : '';
1017+
$shipping_postcode = ! empty( $data['shipping_address']['postcode'] ) ? wc_clean( wp_unslash( $data['shipping_address']['postcode'] ) ) : '';
10141018
if ( WC_Stripe_Hong_Kong_States::is_valid_state( strtolower( $shipping_postcode ) ) ) {
10151019
$shipping_state = $shipping_postcode;
10161020
}
@@ -1019,12 +1023,14 @@ public function normalize_state() {
10191023

10201024
// Finally we normalize the state value we want to process.
10211025
if ( $billing_state && $billing_country ) {
1022-
$_POST['billing_state'] = $this->get_normalized_state( $billing_state, $billing_country );
1026+
$data['billing_address']['state'] = $this->get_normalized_state( $billing_state, $billing_country );
10231027
}
10241028

10251029
if ( $shipping_state && $shipping_country ) {
1026-
$_POST['shipping_state'] = $this->get_normalized_state( $shipping_state, $shipping_country );
1030+
$data['shipping_address']['state'] = $this->get_normalized_state( $shipping_state, $shipping_country );
10271031
}
1032+
1033+
return $data;
10281034
}
10291035

10301036
/**
@@ -1174,34 +1180,40 @@ public function validate_state() {
11741180

11751181
/**
11761182
* Performs special mapping for address fields for specific contexts.
1183+
*
1184+
* @param array $data Address data.
1185+
*
1186+
* @return array Address data.
11771187
*/
1178-
public function fix_address_fields_mapping() {
1179-
$billing_country = ! empty( $_POST['billing_country'] ) ? wc_clean( wp_unslash( $_POST['billing_country'] ) ) : '';
1180-
$shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( wp_unslash( $_POST['shipping_country'] ) ) : '';
1188+
public function fix_address_fields_mapping( $data ) {
1189+
$billing_country = ! empty( $data['billing_address']['country'] ) ? wc_clean( wp_unslash( $data['billing_address']['country'] ) ) : '';
1190+
$shipping_country = ! empty( $data['shipping_address']['country'] ) ? wc_clean( wp_unslash( $data['shipping_address']['country'] ) ) : '';
11811191

11821192
// For UAE, Google Pay stores the emirate in "region", which gets mapped to the "state" field,
11831193
// but WooCommerce expects it in the "city" field.
11841194
if ( 'AE' === $billing_country ) {
1185-
$billing_state = ! empty( $_POST['billing_state'] ) ? wc_clean( wp_unslash( $_POST['billing_state'] ) ) : '';
1186-
$billing_city = ! empty( $_POST['billing_city'] ) ? wc_clean( wp_unslash( $_POST['billing_city'] ) ) : '';
1195+
$billing_state = ! empty( $data['billing_address']['state'] ) ? wc_clean( wp_unslash( $data['billing_address']['state'] ) ) : '';
1196+
$billing_city = ! empty( $data['billing_address']['city'] ) ? wc_clean( wp_unslash( $data['billing_address']['city'] ) ) : '';
11871197

11881198
// Move the state (emirate) to the city field.
11891199
if ( empty( $billing_city ) && ! empty( $billing_state ) ) {
1190-
$_POST['billing_city'] = $billing_state;
1191-
$_POST['billing_state'] = '';
1200+
$data['billing_address']['city'] = $billing_state;
1201+
$data['billing_address']['state'] = '';
11921202
}
11931203
}
11941204

11951205
if ( 'AE' === $shipping_country ) {
1196-
$shipping_state = ! empty( $_POST['shipping_state'] ) ? wc_clean( wp_unslash( $_POST['shipping_state'] ) ) : '';
1197-
$shipping_city = ! empty( $_POST['shipping_city'] ) ? wc_clean( wp_unslash( $_POST['shipping_city'] ) ) : '';
1206+
$shipping_state = ! empty( $data['shipping_address']['state'] ) ? wc_clean( wp_unslash( $data['shipping_address']['state'] ) ) : '';
1207+
$shipping_city = ! empty( $data['shipping_address']['city'] ) ? wc_clean( wp_unslash( $data['shipping_address']['city'] ) ) : '';
11981208

11991209
// Move the state (emirate) to the city field.
12001210
if ( empty( $shipping_city ) && ! empty( $shipping_state ) ) {
1201-
$_POST['shipping_city'] = $shipping_state;
1202-
$_POST['shipping_state'] = '';
1211+
$data['shipping_address']['city'] = $shipping_state;
1212+
$data['shipping_address']['state'] = '';
12031213
}
12041214
}
1215+
1216+
return $data;
12051217
}
12061218

12071219
/**

readme.txt

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

113113
= 9.5.3 - xxxx-xx-xx =
114114

115+
* Fix - Reimplement mapping of Express Checkout state values to align with WooCommerce's expected state formats
115116
* Tweak - Track charge completed via webhooks in order notes
116117

117118
[See changelog for full details across versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).

0 commit comments

Comments
 (0)