Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Legacy: skip save logic when using saved payment method #3994

Merged
merged 4 commits into from
Mar 4, 2025

Conversation

annemirasol
Copy link
Contributor

@annemirasol annemirasol commented Feb 27, 2025

Changes proposed in this Pull Request:

This PR fixes an edge-case scenario where we can end up unintentionally detaching saved payment methods from customers, potentially causing subscription renewals to fail.

For legacy checkout, when the customer requests to save the payment method but fails the card's auth challenge, we detach the payment method from the customer. This PR adds a condition that they were not using an already-saved payment method to begin with.

Additionally, if the customer clears the auth, we can end up saving duplicate payment method entries in wp_woocommerce_payment_tokens, pointing to the same Stripe payment method. This could lead to customers trying to delete the duplicates, unknowingly it also detaches the remaining payment method.

Background

We have received reports where subscriptions are failing to renew with the following error message from Stripe:

The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, shared with a connected account without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first.

@mattallan has flagged the following in p1738544815105449/1738346084.934989-slack-C3NCP7ZJ6

maybe customers are failing the 3DS auth check on an existing card and that's deleting their saved payment methods which is attached to a subscription

I have verified that this flow can lead to us detaching a payment method used by a subscription:

  • store is on legacy checkout
  • during checkout, the customer is using the saved payment method, and at the same time, the "save payment method" flag is set (i.e. the checkbox is checked, or wc_stripe_force_save_source filter is used)
  • the payment triggers a 3DS flow and the customer fails to complete the auth challenge

Testing instructions

  1. Enable legacy checkout for your store, and enable logging.
  2. As a logged in shopper, go to My account > Payment methods and save the credit card 4000002500003155.
    • Complete the 3DS authentication modal when it pops up.
  3. Go to the Stripe dashboard (https://dashboard.stripe.com/customers), to your customer's page, and under the Payment Methods section, verify that your saved payment method is there.
  4. As the same shopper, add a product to cart and go to shortcode checkout.
  5. Select Use a new payment method, and check the Save payment information to my account for future purchases..
  6. With "save for future purchases" still checked, switch from Use a new payment method to your saved payment method, and place your order.
    • In develop, you will see /detach requests in the logs. You will also find the payment method gone from the Stripe dashboard customers page.
    • In this branch, there should be no /detach requests, and the payment method should still be attached to the customer.

  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Changelog entry

  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Comment

Comment

Post merge

@annemirasol annemirasol marked this pull request as ready for review February 28, 2025 15:26
@annemirasol annemirasol requested review from a team and Mayisha and removed request for a team February 28, 2025 16:25
Copy link
Contributor

@Mayisha Mayisha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job in reproducing the issue @annemirasol. I can reproduce the issue in develop following the mentioned steps and confirming that the issue is fixed in this branch. 🎉

In develop

  • With "save for future purchases" still checked, switch from Use a new payment method to your saved payment method.
    • If I complete the checkout, a duplicate payment token is saved.
    • If I cancel the 3DS modal, a detach payment request is sent to Stripe which deletes the payment method from the customer.

In fix/legacy-skip-saved-payment-methods

  • With "save for future purchases" still checked, switch from Use a new payment method to your saved payment method.
    • If I complete the checkout, no duplicate payment token is saved.
    • If I cancel the 3DS modal, no detach request is sent and the previously saved method persists under the customer.

@annemirasol annemirasol self-assigned this Mar 4, 2025
@annemirasol annemirasol enabled auto-merge (squash) March 4, 2025 18:52
@annemirasol annemirasol merged commit ed221de into develop Mar 4, 2025
38 checks passed
@annemirasol annemirasol deleted the fix/legacy-skip-saved-payment-methods branch March 4, 2025 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants