Automattic / woocommerce-subscriptions-core

Subscriptions core package for WooCommerce
Other
82 stars 29 forks source link

Ensure update_all_payment_methods_from_subscription() function call receives the latest version of the subscription after a payment method change #395

Closed james-allan closed 1 year ago

james-allan commented 1 year ago

Description

When a customer updates the payment method for one of their subscriptions, they have the option to update all their subscription payment methods.

Screen Shot 2023-01-26 at 5 12 01 pm

When a customer checks this box, on a HPOS environment, its possible (depending on the payment method) that the old payment meta (tokens) will be copied to all their subscriptions, not the new one.

This is because.

  1. When we update the subscription payment method, we call gateway->process_payment( $subscription->get_id() ).
    • Because only the subscription ID is passed, you can assume that all payment method changes would occur on a different instance of the subscription.
  2. Then we call update_all_payment_methods_from_subscription() to fire off all the updates.
    • However, the instance passed to this function, would be a original instance which has the old payment meta.
    • Any plugin hooked into that process, would naturally return the old payment tokens, not the new ones.

THis all occurs in this section of the change_payment_method_via_pay_shortcode() function.

This PR fixes that by ensuring we get a fresh instance after calling process_payment() to make sure the update_all_payment_methods_from_subscription() and APIs hooked into it, get the latest version of the subscription which has the new payment method and meta (tokens.

How to test this PR

  1. Checkout PR version of the Stripe payment gateway.
  2. Set up Stripe if you haven't before.
  3. Enable HPOS - sycning disabled.
  4. Purchase two subscriptions using Stripe.
  5. Go to one of the subscriptions from your My account page.
  6. Click the change payment button.
  7. Select a different payment method and check the box to "Update the payment method used for all ..."
  8. Change payment method.
  9. Note that all other subscriptions haven't been updated or have been updated to the old payment method, not the new one.

This video by @alefesouza, originally posted here, explains it perfectly

https://user-images.githubusercontent.com/1025173/214762531-2cfbd27d-5104-4aa9-9b44-278964bedfb2.mov

Product impact

asumaran commented 1 year ago

I can also confirm the fix works well using the branch from https://github.com/woocommerce/woocommerce-gateway-stripe/pull/2533 and with HPOS enabled/disabled and switching between orders/posts tables.