Automattic / woocommerce-subscriptions-core

Subscriptions core package for WooCommerce
Other
85 stars 31 forks source link

Error when completing pre-orders if subscriptions are also enabled #375

Closed douglas-johnson closed 1 year ago

douglas-johnson commented 1 year ago

Describe the bug

I'm experiencing an issue when using WooCommerce 7.2.2, WooCommerce Pre-Orders 1.8.0 and WooCommerce Subscriptions 4.7.0

Using the admin interface to complete pre-orders causes a fatal error in subscriptions-core.

Here is a screenshot of the error and stack trace

Screen Shot 2023-01-11 at 10 08 24 AM

To Reproduce

  1. Activate WooCommerce, WooCommerce Subscriptions, and WooCommerce Pre-Orders
  2. Create a product available for pre-order
  3. Place a pre-order
  4. Use the admin panel to manually complete the pre-order

Expected behavior

I would expect the pre-order to be completed, and not to interact with subscriptions at all.

Actual behavior

Fatal error: Uncaught Error: Call to a member function get_id() on bool in /woocommerce-subscriptions/vendor/woocommerce-subscriptions-core/includes/wcs-order-functions.php on line 352

WcPayWelcomePage from WooCommerce wants to know the available payment gateways.

The problem occurs when WC_Subscriptions_Payment_Gateways::get_available_payment_gateways() calls wcs_order_contains_subscription( $_GET['order_id'] ) without first verifying if $_GET['order_id'] is an integer.

https://github.com/Automattic/woocommerce-subscriptions-core/blob/5.1.0/includes/gateways/class-wc-subscriptions-core-payment-gateways.php#L101

When completing pre-orders, the order_id parameter is an array. For example in this specific case the parameters looked like: &order_id[]=300272&order_id[]=300244&order_id[]=300225

wcs_order_contains_subscription() expects to receive an integer or an order object. It eventually fails because it passes the same unverified order_id to wc_get_order() and never verifies if the returned value is an order.

https://github.com/Automattic/woocommerce-subscriptions-core/blob/5.1.0/includes/wcs-order-functions.php#L345-L352

Product impact

csmcneill commented 1 year ago

Hey @douglas-johnson! How are you manually completing the pre-orders? Are you doing that through WooCommerce > Pre-Orders > Complete, or are you using a different method?

douglas-johnson commented 1 year ago

@csmcneill I'm at this URL path /wp-admin/admin.php?page=wc_pre_orders and I'm using Complete in the Bulk actions like so:

Screen Shot 2023-01-17 at 9 30 09 AM
csmcneill commented 1 year ago

Thanks for the clarification @douglas-johnson!

I tried to replicate the issue using the above steps and was unable to: 9CKhPN.png

I tried using Pre-Order products where the fee is paid upfront and at release.

Please log in to your WooCommerce.com account that has an active license for WooCommerce Pre-Orders and/or WooCommerce Subscriptions. Once logged in, contact us at WooCommerce.com > My Account > Support so that we can assist you further with this. You can open a ticket, but if you'd prefer to handle this over live chat, you'll also see a Start Chat button when there are operators available.

Per our Support Policy, we’re only able to provide support for products purchased from WooCommerce.com, so you'll want to make sure that you're logged into an account that has an active license for Pre-Orders and/or Subscriptions.

When you open your support request, please include a link to this issue so that we can keep track of what's already been done. I also recommend including your System Status Report and the full stack trace of the fatal error log.

I will close this issue for the time being; if needed, our support team will re-open it after performing troubleshooting with you via ticket/chat.

douglas-johnson commented 1 year ago

@csmcneill I filed a ticket before posting this issue. The ticket number is 5860472. The Happiness Engineer I spoke with suggested I bring the issue here.

After I posted this issue, I received a response from WooCommerce that said the issue might be hidden on any site with WooCommerce Payments enabled because WcPayWelcomePage::register_payments_welcome_page() is never called.

csmcneill commented 1 year ago

Hey again @douglas-johnson,

Thanks for indicating that you've already contacted WooCommerce support in 5860472-zen; I caught up with @Brianmitchtay a bit, and I'm unable to reproduce the issue. For what it's worth, I do not have WooCommerce Payments active on my test site, so that rules out that as a potential reason for why Brian may have been unable to reproduce it.

Since this is not reproducible, I'm not going to suggest that this is a bug that requires input from the Subscriptions engineering team at this point in time. I've reached out to some of the folks on VIP to see if we can dig into this a bit further outside of GitHub.

We'll reach out to you again via email to help you get this sorted. Thank you for your patience!

csmcneill commented 1 year ago

Hey again @douglas-johnson,

I did a bit more digging into this issue and I was finally able to reproduce it.

To summarize, this issue seems to be closely linked to #344 where a URL query is trying to pass an ID that isn't an order (or fails in a similar fashion).

To reproduce:

  1. Install Pre-Orders and Subscriptions on a store that is 90+ days old
  2. Set the store location to the U.S. in WooCommerce > Settings > General
  3. Do not install WooCommerce Payments
  4. Install and set up two separate gateways (I used Stripe and Square)
  5. Place multiple orders for pre-order products (I placed 4; 2 with Stripe and 2 with Square)
  6. Navigate to /wp-admin/admin.php?page=wc_pre_orders
  7. Select multiple pre-orders and attempt to mark them as Complete via bulk actions

Here's the complete fatal error log:

2023-01-23T02:14:29+00:00 CRITICAL Uncaught Error: Call to a member function get_id() on bool in /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-content/plugins/woocommerce-subscriptions/vendor/woocommerce/subscriptions-core/includes/wcs-order-functions.php:352
Stack trace:
#0 /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-content/plugins/woocommerce-subscriptions/includes/gateways/class-wc-subscriptions-payment-gateways.php(39): wcs_order_contains_subscription(false)
#1 /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-includes/class-wp-hook.php(308): WC_Subscriptions_Payment_Gateways::get_available_payment_gateways(Array)
#2 /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-includes/plugin.php(205): WP_Hook->apply_filters(Array, Array)
#3 /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-content/plugins/woocommerce/includes/class-wc-payment-gateways.php(163): apply_filters('woocommerce_ava...', Array)
#4 /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-content/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Pay in /srv/users/userbf1367dd/apps/userbf1367dd/public/wp-content/plugins/woocommerce-subscriptions/vendor/woocommerce/subscriptions-core/includes/wcs-order-functions.php on line 352

Based on our assessment, this should be resolved by #348, which is scheduled to be included in the next version of WooCommerce Subscriptions.

douglas-johnson commented 1 year ago

@csmcneill OK, thank you for having another look! It's great there's already a fix in. I searched for related issues before filing this, I apologize I didn't find that one.