woocommerce / woocommerce

A customizable, open-source ecommerce platform built on WordPress. Build any commerce solution you can imagine.
https://woocommerce.com
9.38k stars 10.76k forks source link

#38983 is causing issues for some merchants #39750

Closed Babylon1999 closed 11 months ago

Babylon1999 commented 1 year ago

Prerequisites

Describe the bug

This PR #38983 is causing issues for some merchants, specifically the new woocommerce_order_email_verification_required feature—even when turned off.

I wasn't able to reproduce this myself, here are the cases I came by in the forums:

I would appreciate any feedback on this matter.

Cheers!

Expected behavior

/

Actual behavior

/

Steps to reproduce

/

WordPress Environment

/

Isolating the problem

shameemreza commented 1 year ago

Possibly another related report here: 6653861-zen

anastas10s-afk commented 1 year ago

6657912-zen

shameemreza commented 1 year ago

Another report 6675275-zen

Babylon1999 commented 1 year ago

zd-6624453

Babylon1999 commented 1 year ago

A lot of reports in https://wordpress.org/support/topic/email-verification-after-woo-order-from-guest

barryhughes commented 1 year ago

Possibly another related report here: 6653861-zen

I don't believe this is related.

zoupkat commented 1 year ago

Another one: 6784086-ZD

Mattgivertz commented 1 year ago

We have experienced this issue and found it only occurs for guest checkouts. WooCommerce support reviewed our account settings and saw no issues there. Whilst I can understand some code I wouldn't say I was a developer. Would it be possible to add some debug code to help debug this. I'd be happy to include this in our staging environment

Babylon1999 commented 1 year ago

in zd-6746326 the merchant can only reproduce the issue in chrome

Mattgivertz commented 1 year ago

We have observed this behavior on Firefox and Microsoft Edge

gsim commented 1 year ago

Yikes, not a small thing. No matter the browser, desktop or mobile. add_filter( 'woocommerce_order_email_verification_required', '__return_false' ); has no effect what so ever. Interestingly on a new site, with no theme installed, or rather a very simplistic theme just to load woocommerce, guest checkout works with no problem and no additional code.

barryhughes commented 1 year ago

Depending on the scenario being faced, this code (intended as a short term solution only) may be useful, as a way to help ensure guest shoppers can see the confirmation page without extra checks:

<?php

( function () {
    $post_vars = [];

    add_filter( 'woocommerce_thankyou_order_id', function ( $pass ) use ( &$post_vars ) {
        $post_vars = $_POST;
        $_POST = [];
        return $pass;
    } );

    add_filter( 'woocommerce_order_email_verification_grace_period', function () use ( &$post_vars ) {
        if ( ! empty( $post_vars ) ) {
            $_POST = $post_vars;
        }
        return PHP_INT_MAX;
    } );
} )();

It could for instance be added to wp-content/mu-plugins/temporary-39750.php. Again, it doesn't cover all scenarios. If it doesn't work, or causes problems, simply remove it (and if you follow the advice to set it up as a mu-plugin file, you could simply delete the file whenever you are ready).

dustinatx commented 1 year ago

@barryhughes Thank you for the code. I just wanted to report that, for me, it has the same effect as add_filter( 'woocommerce_order_email_verification_required', '__return_false' );.

It removes the email verification requirement for the initial page load of the checkout page.

Unfortunately, if the customer’s payment fails they are still asked to login or verify their email address.

I'm using WooCommerce Stripe Payment Gateway to test.

I described this issue in detail here:

https://wordpress.org/support/topic/problems-with-email-verification-for-orders/

gsim commented 1 year ago

Thank you @barryhughes that worked perfectly in my case. Both EFT and Card payments now redirect to the thank you page without asking for the login. So much better than my temp fix of editing the thank you page in the plugin core. I cannot confirm yet if the issue will still occurs when a payment fails as in @dustinatx's case, but if a payment fails it would not redirect to the thank you page anyway... different problem. I can confirm that if I cancel the transaction at the payment gateway it redirects back to the cart with no issue.

Mattgivertz commented 1 year ago

Thanks @barryhughes this worked for us in staging when using PayPal standard payments for both guest and logged in account checkout. Don't know what's going to happen on a failed payment as it seems impossible to fail a payment when using paypal sandbox :) Cancelled payment returns to the checkout page which is the expected behaviour with our installation.

I'll deploy this into production and keep an eye on this but looks like your temporary fix works OK

barryhughes commented 1 year ago

It removes the email verification requirement for the initial page load of the checkout page ... Unfortunately, if the customer’s payment fails they are still asked to login or verify their email address.

Yep, it doesn't attempt to address that. In most cases, when the shortcode renders, it is too late to establish a new user session—which would be one way of solving this. Not to say it is impossible to do, just that that is outwith what this simple snippet addresses.

Thank you @barryhughes that worked perfectly in my case.

Thank you for confirming!

Don't know what's going to happen on a failed payment as it seems impossible to fail a payment when using paypal sandbox

I suspect exactly as @dustinatx outlined: they would be asked to re-verify their email address. We'll look into a substantive fix for that, and also see if a further snippet is possible in the interim.

gsim commented 1 year ago

Update. It turns out the fix works on desktop only, but fails on mobile, both Android and iPhone. Both go to the log in screen again. I am still investigating as I have just found out.

diegoversiani commented 11 months ago

Hi @barryhughes,

Our plugin Fluid Checkout has an account matching feature to allow registered customers to complete an new order without logging into their account first, as explained in our documentation.

Since this new security check was introduced, our feature is half broken as the customer cannot confirm the details of the order that was just placed, and is forced to log in to do so.

This happens because the order is associated with the existing customer when placed, so $order->get_customer_id() will return the registered customer ID associated with the email provided for the guest order, while get_current_user_id() would return 0 since the user is not logged in at this point.

It would be really helpful if WooCommerce could use the filter woocommerce_order_email_verification_grace_period (or a similar one) on the email verification for registered customers too. Below is a code example with these changes:

/**
 * Refactored: extracted grace period verification into a separate function to be reused.
 */
private static function is_email_verification_within_grace_period( WC_Order $order, $context ) {
    // [...] (filter documentation omitted for brevity)
    $verification_grace_period = (int) apply_filters( 'woocommerce_order_email_verification_grace_period', 10 * MINUTE_IN_SECONDS, $order, $context );
    $date_created              = $order->get_date_created();

    // We do not need to verify the email address if we are within the grace period immediately following order creation.
    if (
        is_a( $date_created, WC_DateTime::class )
        && time() - $date_created->getTimestamp() <= $verification_grace_period
    ) {
        // CHANGE: Return `true` to indicate that we are within the grace period.
        return true;
    }

    // CHANGE: Return `false` to indicate that we are NOT within the grace period.
    return false;
}

/**
 * Show the thanks page.
 *
 * @param int $order_id Order ID.
 */
private static function order_received( $order_id = 0 ) {
    // [...] (omitted for brevity)

    $order_customer_id = $order->get_customer_id();

    // CHANGE: Get whether we are within the grace period.
    $within_grace_period = self::is_email_verification_within_grace_period( $order, 'order-received' );

    // For non-guest orders, require the user to be logged in before showing this page.
    if ( ! $within_grace_period && $order_customer_id && get_current_user_id() !== $order_customer_id ) {
        wc_get_template( 'checkout/order-received.php', array( 'order' => false ) );
        wc_print_notice( esc_html__( 'Please log in to your account to view this order.', 'woocommerce' ), 'notice' );
        woocommerce_login_form( array( 'redirect' => $order->get_checkout_order_received_url() ) );
        return;
    }

    // [...] (omitted for brevity)
}

With that filter being used for both guest and non-guest orders, the order received (thank you) page could be displayed to the customers for a brief amount of time — the grace period — while preserving the utility of this new security check if the link was to be reused later.

Hopefully this can be implemented soon :)

Best, Diego.

barryhughes commented 11 months ago