Skip to content

Commit

Permalink
Merge branch 'develop' into add/8797-consitional-rest-apis-init
Browse files Browse the repository at this point in the history
  • Loading branch information
kalessil committed May 14, 2024
2 parents 6c62737 + 1e74d6b commit b02458d
Show file tree
Hide file tree
Showing 30 changed files with 377 additions and 259 deletions.
4 changes: 4 additions & 0 deletions changelog/add-phpstan-qit-tests-command
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: dev

Add command to run QIT PHPStan tests.
4 changes: 4 additions & 0 deletions changelog/as-remove-auto-redirect
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: update

Do not auto-redirect to WooPay on page load.
5 changes: 5 additions & 0 deletions changelog/fix-8716-duplicate-query-checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: fix
Comment: A small defensive check for PRB gateway title filtering.


4 changes: 4 additions & 0 deletions changelog/fix-8775-direct-checkout-shortcode-orders
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Fix shortcode orders when using WooPay Direct Checkout.
4 changes: 4 additions & 0 deletions changelog/update-billing-address-saved-card
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Updating saved payment method billing address before processing the payment
143 changes: 11 additions & 132 deletions client/checkout/woopay/email-input-iframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const handleWooPayEmailInput = async (
const waitTime = 500;
const woopayEmailInput = await getTargetElement( field );
const tracksUserId = await getTracksIdentity();
let hasCheckedLoginSession = false;

// If we can't find the input, return.
if ( ! woopayEmailInput ) {
Expand All @@ -34,24 +33,6 @@ export const handleWooPayEmailInput = async (
const parentDiv = woopayEmailInput.parentNode;
spinner.classList.add( 'wc-block-components-spinner' );

// Make the login session iframe wrapper.
const loginSessionIframeWrapper = document.createElement( 'div' );
loginSessionIframeWrapper.setAttribute( 'role', 'dialog' );
loginSessionIframeWrapper.setAttribute( 'aria-modal', 'true' );

// Make the login session iframe.
const loginSessionIframe = document.createElement( 'iframe' );
loginSessionIframe.title = __(
'WooPay Login Session',
'woocommerce-payments'
);
loginSessionIframe.classList.add( 'woopay-login-session-iframe' );

// To prevent twentytwenty.intrinsicRatioVideos from trying to resize the iframe.
loginSessionIframe.classList.add( 'intrinsic-ignore' );

loginSessionIframeWrapper.insertBefore( loginSessionIframe, null );

// Make the otp iframe wrapper.
const iframeWrapper = document.createElement( 'div' );
iframeWrapper.setAttribute( 'role', 'dialog' );
Expand Down Expand Up @@ -442,54 +423,7 @@ export const handleWooPayEmailInput = async (
} );
};

const closeLoginSessionIframe = () => {
loginSessionIframeWrapper.remove();
loginSessionIframe.classList.remove( 'open' );
woopayEmailInput.focus( {
preventScroll: true,
} );

// Check the initial value of the email input and trigger input validation.
if ( validateEmail( woopayEmailInput.value ) ) {
woopayLocateUser( woopayEmailInput.value );
}
};

const openLoginSessionIframe = ( email ) => {
const emailParam = new URLSearchParams();

if ( validateEmail( email ) ) {
parentDiv.insertBefore( spinner, woopayEmailInput );
emailParam.append( 'email', email );
emailParam.append( 'test_mode', !! getConfig( 'testMode' ) );
}

loginSessionIframe.src = `${ getConfig(
'woopayHost'
) }/login-session?${ emailParam.toString() }`;

// Insert the wrapper into the DOM.
parentDiv.insertBefore( loginSessionIframeWrapper, null );

// Focus the iframe.
loginSessionIframe.focus();

// fallback to close the login session iframe in case failed to receive event
// via postMessage.
setTimeout( () => {
if ( ! hasCheckedLoginSession ) {
closeLoginSessionIframe();
}
}, 15000 );
};

woopayEmailInput.addEventListener( 'input', ( e ) => {
if ( ! hasCheckedLoginSession && ! customerClickedBackButton ) {
openLoginSessionIframe( woopayEmailInput.value );

return;
}

const email = e.currentTarget.value;

clearTimeout( timer );
Expand All @@ -506,52 +440,7 @@ export const handleWooPayEmailInput = async (
if ( ! getConfig( 'woopayHost' ).startsWith( e.origin ) ) {
return;
}

switch ( e.data.action ) {
case 'auto_redirect_to_platform_checkout':
case 'auto_redirect_to_woopay':
hasCheckedLoginSession = true;
api.initWooPay(
e.data.userEmail,
e.data.platformCheckoutUserSession
)
.then( ( response ) => {
if ( response.result === 'success' ) {
loginSessionIframeWrapper.classList.add(
'woopay-login-session-iframe-wrapper'
);
loginSessionIframe.classList.add( 'open' );
recordUserEvent( 'checkout_woopay_auto_redirect' );
spinner.remove();
// Do nothing if the iframe has been closed.
if (
! document.querySelector(
'.woopay-login-session-iframe'
)
) {
return;
}
window.location = response.url;
} else {
closeLoginSessionIframe();
}
} )
.catch( ( err ) => {
// Only show the error if it's not an AbortError,
// it occurs when the fetch request is aborted because user
// clicked the Place Order button while loading.
if ( err.name !== 'AbortError' ) {
showErrorMessage();
}
} )
.finally( () => {
spinner.remove();
} );
break;
case 'close_auto_redirection_modal':
hasCheckedLoginSession = true;
closeLoginSessionIframe();
break;
case 'redirect_to_woopay_skip_session_init':
if ( e.data.redirectUrl ) {
deleteSkipWooPayCookie();
Expand All @@ -562,10 +451,18 @@ export const handleWooPayEmailInput = async (
break;
case 'redirect_to_platform_checkout':
case 'redirect_to_woopay':
api.initWooPay(
const promise = api.initWooPay(
woopayEmailInput.value,
e.data.platformCheckoutUserSession
)
);

// The <Login> component on WooPay re-renders sending the `redirect_to_platform_checkout` message twice.
// `api.initWooPay` skips the request the second time and returns undefined.
if ( ! promise ) {
break;
}

promise
.then( ( response ) => {
// Do nothing if the iframe has been closed.
if (
Expand Down Expand Up @@ -633,25 +530,7 @@ export const handleWooPayEmailInput = async (
}
} );

if ( ! customerClickedBackButton ) {
const hasWcPayElementOnBlocks = document.getElementById(
'radio-control-wc-payment-method-options-woocommerce_payments'
);
const hasWcPayElementOnShortcode = document.getElementById(
'payment_method_woocommerce_payments'
);
const hasWCPayPaymentMethod =
hasWcPayElementOnBlocks || hasWcPayElementOnShortcode;

// Check if user already has a WooPay login session and only open the iframe if there is WCPay.
if (
! hasCheckedLoginSession &&
hasWCPayPaymentMethod &&
! getConfig( 'isWooPayDirectCheckoutEnabled' )
) {
openLoginSessionIframe( woopayEmailInput.value );
}
} else {
if ( customerClickedBackButton ) {
// Dispatch an event declaring this user exists as returned via back button. Wait for the window to load.
setTimeout( () => {
dispatchUserExistEvent( true );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ jest.mock( 'tracks', () => ( {
events: {
WOOPAY_EMAIL_CHECK: 'checkout_email_address_woopay_check',
WOOPAY_OFFERED: 'checkout_woopay_save_my_info_offered',
WOOPAY_AUTO_REDIRECT: 'checkout_woopay_auto_redirect',
WOOPAY_SKIPPED: 'woopay_skipped',
WOOPAY_BUTTON_LOAD: 'woopay_button_load',
WOOPAY_BUTTON_CLICK: 'woopay_button_click',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ jest.mock( 'tracks', () => ( {
events: {
WOOPAY_EMAIL_CHECK: 'checkout_email_address_woopay_check',
WOOPAY_OFFERED: 'checkout_woopay_save_my_info_offered',
WOOPAY_AUTO_REDIRECT: 'checkout_woopay_auto_redirect',
WOOPAY_SKIPPED: 'woopay_skipped',
WOOPAY_BUTTON_LOAD: 'woopay_button_load',
WOOPAY_BUTTON_CLICK: 'woopay_button_click',
Expand Down
1 change: 0 additions & 1 deletion client/tracks/event.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ export type Event =
| 'checkout_save_my_info_privacy_policy_click'
| 'checkout_save_my_info_tooltip_click'
| 'checkout_save_my_info_tooltip_learn_more_click'
| 'checkout_woopay_auto_redirect'
| 'woopay_skipped'
| 'woopay_button_load'
| 'woopay_button_click'
Expand Down
6 changes: 3 additions & 3 deletions includes/admin/class-wc-rest-payments-charges-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function generate_charge_from_order( $request ) {

$currency = $order->get_currency();
$amount = WC_Payments_Utils::prepare_amount( $order->get_total(), $currency );
$billing_details = WC_Payments_Utils::get_billing_details_from_order( $order );
$billing_details = WC_Payments::get_order_service()->get_billing_data_from_order( $order ); // TODO: Inject order_service after #7464 is fixed.
$date_created = $order->get_date_created();
$intent_id = $order->get_meta( '_intent_id' );
$intent_status = $order->get_meta( '_intent_status' );
Expand All @@ -102,7 +102,7 @@ public function generate_charge_from_order( $request ) {
'currency' => $currency,
'disputed' => false,
'outcome' => false,
'order' => WC_Payments::get_payments_api_client()->build_order_info( $order ),
'order' => $this->api_client->build_order_info( $order ),
'paid' => false,
'paydown' => null,
'payment_intent' => ! empty( $intent_id ) ? $intent_id : null,
Expand All @@ -119,7 +119,7 @@ public function generate_charge_from_order( $request ) {
'status' => ! empty( $intent_status ) ? $intent_status : $order->get_status(),
];

$charge = WC_Payments::get_payments_api_client()->add_formatted_address_to_charge_object( $charge );
$charge = $this->api_client->add_formatted_address_to_charge_object( $charge );

return rest_ensure_response( $charge );
}
Expand Down
33 changes: 20 additions & 13 deletions includes/class-wc-payment-gateway-wcpay.php
Original file line number Diff line number Diff line change
Expand Up @@ -1431,19 +1431,6 @@ public function process_payment_for_order( $cart, $payment_information, $schedul
];
list( $user, $customer_id ) = $this->manage_customer_details_for_order( $order, $customer_details_options );

// Update saved payment method async to include billing details, if missing.
if ( $payment_information->is_using_saved_payment_method() ) {
$this->action_scheduler_service->schedule_job(
time(),
self::UPDATE_SAVED_PAYMENT_METHOD,
[
'payment_method' => $payment_information->get_payment_method(),
'order_id' => $order->get_id(),
'is_test_mode' => WC_Payments::mode()->is_test(),
]
);
}

$intent_failed = false;
$payment_needed = $amount > 0;

Expand All @@ -1461,6 +1448,16 @@ public function process_payment_for_order( $cart, $payment_information, $schedul
// We need to make sure the saved payment method is saved to the order so we can
// charge the payment method for a future payment.
$this->add_token_to_order( $order, $payment_information->get_payment_token() );
// If we are not hitting the API for the intent, we need to update the saved payment method ourselves.
$this->action_scheduler_service->schedule_job(
time(),
self::UPDATE_SAVED_PAYMENT_METHOD,
[
'payment_method' => $payment_information->get_payment_method(),
'order_id' => $order->get_id(),
'is_test_mode' => WC_Payments::mode()->is_test(),
]
);
}

if ( $is_changing_payment_method_for_subscription && $payment_information->is_using_saved_payment_method() ) {
Expand Down Expand Up @@ -1543,6 +1540,16 @@ public function process_payment_for_order( $cart, $payment_information, $schedul
$request->set_payment_methods( $payment_methods );
$request->set_cvc_confirmation( $payment_information->get_cvc_confirmation() );
$request->set_hook_args( $payment_information );
if ( $payment_information->is_using_saved_payment_method() ) {
$billing_details = $this->order_service->get_billing_data_from_order( $order );

$is_legacy_card_object = (bool) preg_match( '/^(card_|src_)/', $payment_information->get_payment_method() );

// Not updating billing details for legacy card objects because they have a different structure and are no longer supported.
if ( ! empty( $billing_details ) && ! $is_legacy_card_object ) {
$request->set_payment_method_update_data( [ 'billing_details' => $billing_details ] );
}
}
// Add specific payment method parameters to the request.
$this->modify_create_intent_parameters_when_processing_payment( $request, $payment_information, $order );

Expand Down
4 changes: 2 additions & 2 deletions includes/class-wc-payments-account.php
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ public function has_card_readers_available(): bool {
*
* @return array Fees.
*/
public function get_fees() {
public function get_fees(): array {
$account = $this->get_cached_account_data();
return ! empty( $account ) && isset( $account['fees'] ) ? $account['fees'] : [];
}
Expand Down Expand Up @@ -1892,7 +1892,7 @@ public function get_account_country() {
*
* @return string Currency code in lowercase.
*/
public function get_account_default_currency() {
public function get_account_default_currency(): string {
$account = $this->get_cached_account_data();
return $account['store_currencies']['default'] ?? strtolower( Currency_Code::UNITED_STATES_DOLLAR );
}
Expand Down
13 changes: 11 additions & 2 deletions includes/class-wc-payments-customer-service.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ class WC_Payments_Customer_Service {
*/
private $session_service;

/**
* WC_Payments_Order_Service instance
*
* @var WC_Payments_Order_Service
*/
private $order_service;

/**
* Class constructor
*
Expand All @@ -83,12 +90,14 @@ public function __construct(
WC_Payments_API_Client $payments_api_client,
WC_Payments_Account $account,
Database_Cache $database_cache,
WC_Payments_Session_Service $session_service
WC_Payments_Session_Service $session_service,
WC_Payments_Order_Service $order_service
) {
$this->payments_api_client = $payments_api_client;
$this->account = $account;
$this->database_cache = $database_cache;
$this->session_service = $session_service;
$this->order_service = $order_service;

/*
* Adds the WooCommerce Payments customer ID found in the user session
Expand Down Expand Up @@ -283,7 +292,7 @@ public function get_payment_methods_for_customer( $customer_id, $type = 'card' )
* @param WC_Order $order Order to be used on the update.
*/
public function update_payment_method_with_billing_details_from_order( $payment_method_id, $order ) {
$billing_details = WC_Payments_Utils::get_billing_details_from_order( $order );
$billing_details = $this->order_service->get_billing_data_from_order( $order );

if ( ! empty( $billing_details ) ) {
$this->payments_api_client->update_payment_method(
Expand Down

0 comments on commit b02458d

Please sign in to comment.