-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* Normalizes incoming cart total items for use as a displayItems with the Stripe api. | ||
* | ||
* @param {Array} displayItems Items to normalize. | ||
* | ||
* @return {Array} An array of PaymentItems | ||
*/ | ||
export const normalizeLineItems = ( displayItems ) => { | ||
return displayItems.map( ( displayItem ) => { | ||
let amount = displayItem?.amount ?? displayItem?.value; | ||
if ( displayItem.key === 'total_discount' ) { | ||
amount = -amount; | ||
} | ||
|
||
return { | ||
name: displayItem.label, | ||
amount, | ||
}; | ||
} ); | ||
}; | ||
|
||
/** | ||
* Normalize shipping address information from Stripe's address object to | ||
* the cart shipping address object shape. | ||
* | ||
* @param {Object} shippingAddress Stripe's shipping address item | ||
* | ||
* @return {Object} The shipping address in the shape expected by the cart. | ||
*/ | ||
export const normalizeShippingAddress = ( shippingAddress ) => { | ||
return { | ||
first_name: | ||
shippingAddress?.recipient | ||
?.split( ' ' ) | ||
?.slice( 0, 1 ) | ||
?.join( ' ' ) ?? '', | ||
last_name: | ||
shippingAddress?.recipient?.split( ' ' )?.slice( 1 )?.join( ' ' ) ?? | ||
'', | ||
company: '', | ||
address_1: shippingAddress?.addressLine?.[ 0 ] ?? '', | ||
address_2: shippingAddress?.addressLine?.[ 1 ] ?? '', | ||
city: shippingAddress?.city ?? '', | ||
state: shippingAddress?.state ?? '', | ||
country: shippingAddress?.country ?? '', | ||
postcode: shippingAddress?.postal_code ?? '', | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { normalizeShippingAddress, getExpressCheckoutData } from '.'; | ||
|
||
/** | ||
* Checks if the intermediate address is redacted for the given country. | ||
* CA and GB addresses are redacted and are causing errors until WooCommerce is able to | ||
* handle redacted addresses. | ||
* https://developers.google.com/pay/api/web/reference/response-objects#IntermediateAddress | ||
* | ||
* @param {string} country - The country code. | ||
* | ||
* @return {boolean} True if the postcode is redacted for the country, false otherwise. | ||
*/ | ||
const isPostcodeRedactedForCountry = ( country ) => { | ||
return [ 'CA', 'GB' ].includes( country ); | ||
}; | ||
|
||
/* | ||
* Updates a field in a form with a new value. | ||
* | ||
* @param {String} formSelector - The selector for the form containing the field. | ||
* @param {Object} fieldName - The name of the field to update. | ||
* @param {Object} value - The new value for the field. | ||
*/ | ||
const updateShortcodeField = ( formSelector, fieldName, value ) => { | ||
const field = document.querySelector( | ||
`${ formSelector } [name="${ fieldName }"]` | ||
); | ||
|
||
if ( ! field ) return; | ||
|
||
// Check if the field is a dropdown (country/state). | ||
if ( field.tagName === 'SELECT' && /country|state/.test( fieldName ) ) { | ||
const options = Array.from( field.options ); | ||
const match = options.find( | ||
( opt ) => | ||
opt.value === value || | ||
opt.textContent.trim().toLowerCase() === value.toLowerCase() | ||
); | ||
|
||
if ( match ) { | ||
field.value = match.value; | ||
jQuery( field ).trigger( 'change' ).trigger( 'close' ); | ||
} | ||
} else { | ||
// Default behavior for text inputs. | ||
field.value = value; | ||
jQuery( field ).trigger( 'change' ); | ||
} | ||
}; | ||
|
||
/** | ||
* Updates the WooCommerce Blocks shipping UI to reflect a new shipping address. | ||
* | ||
* @param {Object} eventAddress - The shipping address returned by the payment event. | ||
*/ | ||
const updateBlocksShippingUI = ( eventAddress ) => { | ||
wp?.data | ||
?.dispatch( 'wc/store/cart' ) | ||
?.setShippingAddress( normalizeShippingAddress( eventAddress ) ); | ||
}; | ||
|
||
/** | ||
* Updates the WooCommerce shortcode cart/checkout shipping UI to reflect a new shipping address. | ||
* | ||
* @param {Object} eventAddress - The shipping address returned by the payment event. | ||
*/ | ||
const updateShortcodeShippingUI = ( eventAddress ) => { | ||
const context = getExpressCheckoutData( 'button_context' ); | ||
const address = normalizeShippingAddress( eventAddress ); | ||
|
||
const keys = [ 'country', 'state', 'city', 'postcode' ]; | ||
|
||
if ( context === 'cart' ) { | ||
keys.forEach( ( key ) => { | ||
if ( address[ key ] ) { | ||
updateShortcodeField( | ||
'form.woocommerce-shipping-calculator', | ||
`calc_shipping_${ key }`, | ||
address[ key ] | ||
); | ||
} | ||
} ); | ||
document | ||
.querySelector( | ||
'form.woocommerce-shipping-calculator [name="calc_shipping"]' | ||
) | ||
?.click(); | ||
} else if ( context === 'checkout' ) { | ||
keys.forEach( ( key ) => { | ||
if ( address[ key ] ) { | ||
updateShortcodeField( | ||
'form.woocommerce-checkout', | ||
`billing_${ key }`, | ||
address[ key ] | ||
); | ||
} | ||
} ); | ||
} | ||
}; | ||
|
||
/** | ||
* Updates the WooCommerce shipping UI to reflect a new shipping address. | ||
* | ||
* Determines the current context (cart or checkout) and updates either | ||
* WooCommerce Blocks or shortcode-based shipping forms, if applicable. | ||
* | ||
* @param {Object} newAddress - The new shipping address object returned by the payment event. | ||
* @param {string} newAddress.country - The country code of the shipping address. | ||
* @param {string} [newAddress.state] - The state/province of the shipping address. | ||
* @param {string} [newAddress.city] - The city of the shipping address. | ||
* @param {string} [newAddress.postcode] - The postal/ZIP code of the shipping address. | ||
*/ | ||
export const updateShippingAddressUI = ( newAddress ) => { | ||
const context = getExpressCheckoutData( 'button_context' ); | ||
const isBlocks = getExpressCheckoutData( 'has_block' ); | ||
|
||
if ( | ||
[ 'cart', 'checkout' ].includes( context ) && | ||
! isPostcodeRedactedForCountry( newAddress.country ) | ||
) { | ||
if ( isBlocks ) { | ||
updateBlocksShippingUI( newAddress ); | ||
} else { | ||
updateShortcodeShippingUI( newAddress ); | ||
} | ||
} | ||
}; |