Skip to content

Commit

Permalink
Merge branch 'develop' into add/10382-adds-store-id-to-tracker-reques…
Browse files Browse the repository at this point in the history
…t-body
  • Loading branch information
FangedParakeet authored Feb 21, 2025
2 parents 9fa2de4 + a615dd0 commit 92e686e
Show file tree
Hide file tree
Showing 18 changed files with 92 additions and 502 deletions.
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
*** WooPayments Changelog ***

= 8.9.2 - 2025-02-21 =
* Fix - Fixed WooPay opt-in race condition

= 8.9.1 - 2025-02-07 =
* Fix - Ensures that the tokenised cart for ECE implementation is disabled by default.

Expand Down
4 changes: 4 additions & 0 deletions changelog/cleanup-new-payment-process
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: dev

Remove routing to the partially re-engineered payment process"
4 changes: 4 additions & 0 deletions changelog/feat-enable-tokenized-ece-by-default-round-2
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: update

feat: GooglePay/ApplePay refactor to leverage Store API is enabled by default - second try.
4 changes: 4 additions & 0 deletions changelog/fix-10379-woo-logo-size-test-drive-onboarding
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Update the size of Woo logo on the test drive onboarding page.
4 changes: 4 additions & 0 deletions changelog/fix-woopay-opt-in-race-condition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Fixed WooPay opt-in race condition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: update

Add a notice indicating that overview page needs to be reloaded after completing the requirements in the embedded component.
29 changes: 23 additions & 6 deletions client/components/woopay/save-user/checkout-page-save-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,17 +275,34 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => {
isBlocksCheckout,
] );

useEffect( () => {
if (
! getConfig( 'forceNetworkSavedCards' ) ||
! isWCPayWithNewTokenChosen ||
isRegisteredUser
) {
// Clicking the place order button sets the extension data in backend. If user changes the payment method
// due to an error, we need to clear the extension data in backend.
if ( isBlocksCheckout && userDataSent ) {
sendExtensionData( true );
}
clearValidationError( errorId );
}
}, [
clearValidationError,
errorId,
isBlocksCheckout,
isRegisteredUser,
isWCPayWithNewTokenChosen,
sendExtensionData,
userDataSent,
] );

if (
! getConfig( 'forceNetworkSavedCards' ) ||
! isWCPayWithNewTokenChosen ||
isRegisteredUser
) {
// Clicking the place order button sets the extension data in backend. If user changes the payment method
// due to an error, we need to clear the extension data in backend.
if ( isBlocksCheckout && userDataSent ) {
sendExtensionData( true );
}
clearValidationError( errorId );
return null;
}

Expand Down
7 changes: 3 additions & 4 deletions client/connect-account-page/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,9 @@

img.logo {
position: absolute;
height: 40px;
width: 40px;
top: 18px;
left: 36px;
width: 64px;
top: 24px;
left: 24px;
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions client/overview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
} from '@stripe/react-connect-js';
import { recordEvent } from 'wcpay/tracks';
import StripeSpinner from 'wcpay/components/stripe-spinner';
import { getAdminUrl } from 'wcpay/utils';

const OverviewPageError = () => {
const queryParams = getQuery();
Expand Down Expand Up @@ -98,6 +99,11 @@ const OverviewPage = () => {
const [ stripeComponentLoading, setStripeComponentLoading ] = useState(
true
);
// Variable to memoize the count of Stripe notifications.
const [
stripeNotificationsCountToAddressMemo,
setStripeNotificationsCountToAddressMemo,
] = useState( 0 );

const isTestModeOnboarding = wcpaySettings.testModeOnboarding;
const { isLoading: settingsIsLoading } = useSettings();
Expand Down Expand Up @@ -216,6 +222,28 @@ const OverviewPage = () => {
// Do something related to notifications that don't require action.
setNotificationsBannerMessage( 'The items below are in review.' );
} else {
// This is the case where we addressed everything and previously had some notifications to address.
// We recommend the merchant to reload the page in this case.
if ( stripeNotificationsCountToAddressMemo > 0 ) {
dispatch( 'core/notices' ).createSuccessNotice(
__(
'Updates take a moment to appear. Please refresh the page in a minute.',
'woocommerce-payments'
),
{
actions: [
{
label: __( 'Refresh', 'woocommerce-payments' ),
url: getAdminUrl( {
page: 'wc-admin',
path: '/payments/overview',
} ),
},
],
explicitDismiss: true,
}
);
}
setNotificationsBannerMessage( '' );
}
if ( response.actionRequired > 0 || response.total > 0 ) {
Expand All @@ -224,6 +252,8 @@ const OverviewPage = () => {
action_required_count: response.actionRequired,
total_count: response.total,
} );
// Memoize the notifications count to be able to compare it with the fresh count when this function is called one more time.
setStripeNotificationsCountToAddressMemo( response.total );
}
// If the component inits successfully, this function is always called.
// It's safe to set the loading false here rather than onLoaderStart, because it happens too early and the UX is not smooth.
Expand Down
168 changes: 1 addition & 167 deletions includes/class-wc-payment-gateway-wcpay.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
Invalid_Phone_Number_Exception,
Rate_Limiter_Enabled_Exception,
Order_ID_Mismatch_Exception,
Order_Not_Found_Exception,
New_Process_Payment_Exception};
Order_Not_Found_Exception};
use WCPay\Core\Server\Request\Cancel_Intention;
use WCPay\Core\Server\Request\Capture_Intention;
use WCPay\Core\Server\Request\Create_And_Confirm_Intention;
Expand All @@ -47,20 +46,13 @@
use WCPay\Duplicates_Detection_Service;
use WCPay\Fraud_Prevention\Fraud_Prevention_Service;
use WCPay\Fraud_Prevention\Fraud_Risk_Tools;
use WCPay\Internal\Payment\State\AuthenticationRequiredState;
use WCPay\Internal\Payment\State\DuplicateOrderDetectedState;
use WCPay\Internal\Service\DuplicatePaymentPreventionService;
use WCPay\Logger;
use WCPay\Payment_Information;
use WCPay\Payment_Methods\Link_Payment_Method;
use WCPay\WooPay\WooPay_Order_Status_Sync;
use WCPay\WooPay\WooPay_Utilities;
use WCPay\Session_Rate_Limiter;
use WCPay\Tracker;
use WCPay\Internal\Service\PaymentProcessingService;
use WCPay\Internal\Payment\Factor;
use WCPay\Internal\Payment\Router;
use WCPay\Internal\Payment\State\CompletedState;
use WCPay\Internal\Service\Level3Service;
use WCPay\Internal\Service\OrderService;
use WCPay\Payment_Methods\Affirm_Payment_Method;
Expand Down Expand Up @@ -1036,159 +1028,6 @@ public function should_use_stripe_platform_on_checkout_page() {
return false;
}

/**
* Checks whether the new payment process should be used to pay for a given order.
*
* @param WC_Order $order Order that's being paid.
* @return bool
*/
public function should_use_new_process( WC_Order $order ) {
$order_id = $order->get_id();

// The new process us under active development, and not ready for production yet.
if ( ! WC_Payments::mode()->is_dev() ) {
return false;
}

// This array will contain all factors, present during checkout.
$factors = [
/**
* The new payment process is a factor itself.
* Even if no other factors are present, this will make entering
* the new payment process possible only if this factor is allowed.
*/
Factor::NEW_PAYMENT_PROCESS(),
];

// If there is a token in the request, we're using a saved PM.
// phpcs:ignore WordPress.Security.NonceVerification.Missing
$using_saved_payment_method = ! empty( Payment_Information::get_token_from_request( $_POST ) );
if ( $using_saved_payment_method ) {
$factors[] = Factor::USE_SAVED_PM();
}

// The PM should be saved when chosen, or when it's a recurrent payment, but not if already saved.
$save_payment_method = ! $using_saved_payment_method && (
// phpcs:ignore WordPress.Security.NonceVerification.Missing
! empty( $_POST[ 'wc-' . static::GATEWAY_ID . '-new-payment-method' ] )
|| $this->is_payment_recurring( $order_id )
);
if ( $save_payment_method ) {
$factors[] = Factor::SAVE_PM();
}

// In case amount is 0 and we're not saving the payment method, we won't be using intents and can confirm the order payment.
if (
apply_filters(
'wcpay_confirm_without_payment_intent',
$order->get_total() <= 0 && ! $save_payment_method
)
) {
$factors[] = Factor::NO_PAYMENT();
}

// Subscription (both WCPay and WCSubs) if when the order contains one.
if ( function_exists( 'wcs_order_contains_subscription' ) && wcs_order_contains_subscription( $order_id ) ) {
$factors[] = Factor::SUBSCRIPTION_SIGNUP();
}

// WooPay might change how payment fields were loaded.
if (
$this->woopay_util->should_enable_woopay( $this )
&& $this->woopay_util->should_enable_woopay_on_cart_or_checkout()
) {
$factors[] = Factor::WOOPAY_ENABLED();
}

// WooPay payments are indicated by the platform checkout intent.
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( isset( $_POST['platform-checkout-intent'] ) ) {
$factors[] = Factor::WOOPAY_PAYMENT();
}

// Check whether the customer is signining up for a WCPay subscription.
if (
function_exists( 'wcs_order_contains_subscription' )
&& wcs_order_contains_subscription( $order_id )
&& WC_Payments_Features::should_use_stripe_billing()
) {
$factors[] = Factor::WCPAY_SUBSCRIPTION_SIGNUP();
}

if ( defined( 'WCPAY_PAYMENT_REQUEST_CHECKOUT' ) && WCPAY_PAYMENT_REQUEST_CHECKOUT ) {
$factors[] = Factor::PAYMENT_REQUEST();
}

if ( defined( 'WCPAY_EXPRESS_CHECKOUT_CHECKOUT' ) && WCPAY_EXPRESS_CHECKOUT_CHECKOUT ) {
$factors[] = Factor::EXPRESS_CHECKOUT_ELEMENT();
}

$router = wcpay_get_container()->get( Router::class );
return $router->should_use_new_payment_process( $factors );
}

/**
* Checks whether the new payment process should be entered,
* and if the answer is yes, uses it and returns the result.
*
* @param WC_Order $order Order that needs payment.
* @return array|null Array if processed, null if the new process is not supported.
* @throws Exception Error processing the payment.
*/
public function new_process_payment( WC_Order $order ) {
$manual_capture = $this->get_capture_type() === Payment_Capture_Type::MANUAL();

// Important: No factors are provided here, they were meant just for `Feature`.
$service = wcpay_get_container()->get( PaymentProcessingService::class );
$state = $service->process_payment( $order->get_id(), $manual_capture );

if ( $state instanceof DuplicateOrderDetectedState ) {
$duplicate_order_return_url = add_query_arg(
DuplicatePaymentPreventionService::FLAG_PREVIOUS_ORDER_PAID,
'yes',
$this->get_return_url( wc_get_order( $state->get_context()->get_duplicate_order_id() ) )
);

return [ // nosemgrep: audit.php.wp.security.xss.query-arg -- https://woocommerce.github.io/code-reference/classes/WC-Payment-Gateway.html#method_get_return_url is passed in.
'result' => 'success',
'redirect' => $duplicate_order_return_url,
];
}

if ( $state instanceof CompletedState ) {
$return_url = $this->get_return_url( $order );
if ( $state->get_context()->is_detected_authorized_intent() ) {
$return_url = add_query_arg(
DuplicatePaymentPreventionService::FLAG_PREVIOUS_SUCCESSFUL_INTENT,
'yes',
$return_url
);
}

return [ // nosemgrep: audit.php.wp.security.xss.query-arg -- https://woocommerce.github.io/code-reference/classes/WC-Payment-Gateway.html#method_get_return_url is passed in.
'result' => 'success',
'redirect' => $return_url,
];
}

if ( $state instanceof AuthenticationRequiredState ) {
$context = $state->get_context();
return [
'result' => 'success',
'redirect' => $service->get_authentication_redirect_url( $context->get_intent(), $context->get_order_id() ),
];
}

throw new Exception(
__( 'The payment process could not be completed.', 'woocommerce-payments' ),
0,
new New_Process_Payment_Exception(
__( 'The payment process could not be completed.', 'woocommerce-payments' ),
'new_process_payment'
)
);
}

/**
* Process the payment for a given order.
*
Expand All @@ -1200,11 +1039,6 @@ public function new_process_payment( WC_Order $order ) {
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );

// Use the new payment process if allowed.
if ( $this->should_use_new_process( $order ) ) {
return $this->new_process_payment( $order );
}

try {
if ( 20 < strlen( $order->get_billing_phone() ) ) {
throw new Invalid_Phone_Number_Exception(
Expand Down
2 changes: 1 addition & 1 deletion includes/class-wc-payments-features.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static function are_payments_enabled() {
public static function is_tokenized_cart_ece_enabled(): bool {
$account = WC_Payments::get_database_cache()->get( WCPay\Database_Cache::ACCOUNT_KEY, true );

return is_array( $account ) && ! ( $account['is_tokenized_ece_disabled'] ?? false ) && '1' === get_option( self::TOKENIZED_CART_ECE_FLAG_NAME, '0' );
return is_array( $account ) && ! ( $account['is_tokenized_ece_disabled'] ?? false ) && '1' === get_option( self::TOKENIZED_CART_ECE_FLAG_NAME, '1' );
}

/**
Expand Down
1 change: 0 additions & 1 deletion includes/class-wc-payments.php
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,6 @@ public static function init() {
include_once __DIR__ . '/exceptions/class-invalid-price-exception.php';
include_once __DIR__ . '/exceptions/class-fraud-ruleset-exception.php';
include_once __DIR__ . '/exceptions/class-fraud-prevention-enabled-exception.php';
include_once __DIR__ . '/exceptions/class-new-process-payment-exception.php';
include_once __DIR__ . '/exceptions/class-order-not-found-exception.php';
include_once __DIR__ . '/exceptions/class-order-id-mismatch-exception.php';
include_once __DIR__ . '/exceptions/class-rate-limiter-enabled-exception.php';
Expand Down
16 changes: 0 additions & 16 deletions includes/exceptions/class-new-process-payment-exception.php

This file was deleted.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 92e686e

Please sign in to comment.