woocommerce / woocommerce-gateway-stripe

The official Stripe Payment Gateway for WooCommerce
https://wordpress.org/plugins/woocommerce-gateway-stripe/
229 stars 200 forks source link

Pay button in My Account > Orders doesn't include `wc-stripe-confirmation=1` #2305

Open aheckler opened 2 years ago

aheckler commented 2 years ago

Describe the bug

If a subscription renewal needs 3DS auth, the user is sent an email with a link to do so. However, the order is also shown under My Account > Orders as needing payment. Clicking the Pay button there does not open the 3DS modal though!

To Reproduce

Steps to reproduce the behavior below. This might not be the most minimal set of steps, but it does show the issue.

  1. WC test site + Stripe + Subscriptions + a test subscription product.
  2. First, purchase the Subscriptions product using the second card listed here: https://stripe.com/docs/testing#regulatory-cards
  3. Click Complete Authentication in the test mode modal that pops up.
  4. The order should go through. Copy your subscription number for later.
  5. In the dashboard, under WooCommerce > Status > Scheduled Actions, search for your subscription number.
  6. You should see a pending action for woocommerce_scheduled_subscription_payment. Click Run to run it now.
  7. You'll get an email asking you to authorize the payment. This is normal.
  8. Also, under My Account > Orders, the order has a Pay button next to it.
  9. The link in the email is https://www.example.com/checkout/order-pay/116214/?pay_for_order=true&key=wc_order_XXXXXXXXXX&subscription_renewal=true&wc-stripe-confirmation=1 but the link in the My Account > Orders button is https://www.example.com/checkout/order-pay/116214/?pay_for_order=true&key=wc_order_XXXXXXXXXX&subscription_renewal=true, which is missing the wc-stripe-confirmation=1 argument.
  10. This means that paying for the order via My Account > Orders > the pay button doesn't pop up the 3DS modal for you.

Expected behavior

The modal should just appear for me, since it does via the email link.

aheckler commented 2 years ago

4733189-zen

reykjalin commented 2 years ago

I'm unable to reproduce this. No matter whether I choose to pay with the saved payment method or a new payment method in step 9.

I always see the 3DS modal.

Is there something else that could be interfering? Have we done a conflict test?

Ratsbew commented 2 years ago

The description above doesn't address the real issue clearly.

Although the subscription renewal just awaits the authorization of the payment, the missing wc-stripe-confirmation=1 argument for the pay button forces the customer to unnecessarily complete the checkout including payment method selection again (or even worse: If the "Enable payments via saved cards" option is not enabled in the Stripe Payments settings - the customer has to reenter the Credit card data).

Expected behavior: The same as following the link in the email, where the wc-stripe-confirmation=1 argument requires only the necessary action from the customer. The payment authorization modal opens automatically and the customer just has to confirm (or fail) the authorization, to complete the subscription renewal process without selecting or reentering any data.

reykjalin commented 2 years ago

the missing wc-stripe-confirmation=1 argument for the pay button forces the customer to unnecessarily complete the checkout including payment method selection again

This is intended behavior. Payments can fail for reasons other than failed 3DS verification, e.g. insufficient funds, suspected fraud, and trying to pay with a card that's been reported as stolen. It's essential that the customer is offered the option to choose a different payment method when going through the My Account > Orders page instead of retrying a payment method that might fail again for the same reason it did before (e.g. insufficient funds).

The difference is that in the email we ask customers to "authorize the payment", whereas from the My Account > Orders page customers are given the option to "pay" for an order.

Ratsbew commented 2 years ago

@reykjalin Isn't it also crucial to require only the minimum customers effort needed for the respective action(specially in relation with payment processes) to prevent any confusion which could lead to transaction abandonments? Especially the friction from 3DS authentication results in high abandonment rates!

In this particular case it is clear that the reason why the payment fails is the awaiting authorization, which also triggers the email where the customer gets asked to authorize the payment.

If the customer follows the link in the email(with the wc-stripe-confirmation=1 argument) and the payment should fail for another reason while authorizing it(e.g. insufficient funds) it'll redirect the customer to the order-received endpoint, where a clear message prompts the customer to go pay for the order because the transaction fails and offers the option to choose a different payment method - when pressing the pay button, now. Once the authorization fails the link (including the wc-stripe-confirmation=1 argument) does not open the authorization modal again - instead it directly redirects to the order-received endpoint with the option to choose a different payment method by pressing the pay button.

Adding the wc-stripe-confirmation=1 argument to the pay button on the My Account > Orders page(and maybe renaming it to "authorize the payment") in this specific case (where the awaiting authorization is the reason for the failed payment) would only require the minimum customers effort needed and still offer the option to choose a different payment method if the authorization fails(also only if needed). In all other situations the pay button would offer the customer the essential option to choose a different payment method directly.

In my opinion this would be the optimal user flow to minimize the friction from 3DS authentication - what do you think?

reykjalin commented 2 years ago

After discussing this internally with our UX designers we're going to see if we can add another button when 3DS authorization is required to allow customers to immediately try to authorize the payment.

So instead of the Pay button there will instead be two buttons:

  1. Authorize Payment: will immediately try to authorize the payment method that requires 3DS verification; and
  2. Pay another way: does the same thing as the current Pay button does; takes the customer to the Checkout page.

In the grand scheme of things this remains a low priority issue since the friction is ultimately low:

  1. Click Pay
  2. Click Place order
    • Note that customer information is prefilled, and the card is both saved to the account and selected in the list of payment methods.
Ratsbew commented 2 years ago

@reykjalin

So instead of the Pay button there will instead be two buttons:

  1. Authorize Payment: will immediately try to authorize the payment method that requires 3DS verification; and
  2. Pay another way: does the same thing as the current Pay button does; takes the customer to the Checkout page.

I do not really understand why there should be two buttons? Like I've mentioned before the required action in this case is the authorization of the payment - nothing more. Just in case the authorization fails, the option to choose a different payment method should be offered (Exactly like it's done by following the link in the email!). Adding the wc-stripe-confirmation=1 argument to the pay button and temporarily renaming it to "Authorize Payment" should ensure the same functionality like the button in the email - with only one button. Or am I wrong? And btw. if there should be the need for the second "Pay another way"-button, shouldn't the email contain this link then too?

In the grand scheme of things this remains a low priority issue since the friction is ultimately low:

  1. Click Pay
  2. Click Place order Note that customer information is prefilled, and the card is both saved to the account and selected in the list of payment methods.

Unfortunately, this is only partially correct: Once "Enable payments via saved cards" in the payment settings is disabled(Common setting for EU merchants due to GDPR compliance), the customer has to reenter the credit card data for every subscription renewal instead of just authorizing the payment when following the link with the wc-stripe-confirmation=1 argument! In my opinion this cannot be treated as "ultimately low" friction - or am I wrong?

reykjalin commented 2 years ago

I do not really understand why there should be two buttons?

So the customer can choose to either:

  1. Authorize the payment immediately; or
  2. Immediately choose a new payment method

if there should be the need for the second "Pay another way"-button, shouldn't the email contain this link then too?

Not necessarily, but it's certainly something we'll think about adding. Changing the email have to links along the lines of "[Authorize this payment method] or [choose a new payment method]" is a good idea 👍

Once "Enable payments via saved cards" in the payment settings is disabled(Common setting for EU merchants due to GDPR compliance)

I'm not sure how this applies to subscription payments. You can't process renewal payments without also saving the payment method so I'm not sure I fully understand why a merchant would allow subscription but also disable the option to allow customers to save their cards. You're allowing customers to save their cards anyway when they buy subscription products.

Ratsbew commented 2 years ago

@reykjalin Sorry, but I still don't understand why there is the need for the [choose a new payment method], when only an authorization for the payment is required - but anyway - two buttons, then.

I'm not sure how this applies to subscription payments. You can't process renewal payments without also saving the payment method so I'm not sure I fully understand why a merchant would allow subscription but also disable the option to allow customers to save their cards. You're allowing customers to save their cards anyway when they buy subscription products.

You're right, for recurring payments the credit card data is stored in relation to ongoing contracts, such as for subscription services. But when a merchant also sells non-recurring payment products, customers might expect that their credit card data does only get used in relation to the purposes for which they are processed ('data minimisation').
To give the impression that the merchant only stores the minimal necessary data and to strengthen trust it's common to disable the "Enable payments via saved cards" and require the customer to reenter the credit card data for future purchases(of non-recurring products).

Like I've mentioned before with this setting the customer has to reenter the credit card data for every subscription renewal instead of just authorizing the payment when following the link with the wc-stripe-confirmation=1 argument!

For recurring payments the credit card data is furthermore needed and should't be reentered for the subscription renewals if only the authorization of the payment is needed. => Could be implemented just by adding the wc-stripe-confirmation=1 argument to the pay button.

Ratsbew commented 2 years ago

@reykjalin Any news on this?

Ratsbew commented 2 years ago

@aheckler @reykjalin It's not very nice to ignore my comments! Would be great if someone could read my comment from 23 Feb. Thank you!

fetenlakhal commented 1 year ago

Hi there! Someone shared some information that could maybe be related to this issue:

I have a problem that occurs when I change the price of a subscription.

If I have changed the price of a customer's subscription, the payment with Stripe may not work afterwards. I found out now that this can be for example when a payment was confirmed with 3DS. If a renewal order is then triggered with this new price, the payment fails. WooCommerce then sends an email to the customer with the subject 'Payment authorization needed for renewal of.... '.

This email contains a link that directs the user to their account in our store, where they will need to re-enter their payment details. The link ends as follows: 'kasse/order-pay/6264/?pay_for_order=true&key=wc_order_yH0co484oQWPy&subscription_renewal=true&wc-stripe-confirmation=1'

If I now enter the credit card data here again and want to complete the process, it does not work. There is no 3DS window now. When I entered the credit card information during the order process, the 3DS window came up. Now it does not.

When I go to 'My account' in the test store and open my subscription there and click on 'Change payment details', I am landing in the same form. Here is only the link slightly modified. It ends with: 'kasse/order-pay/6270/?pay_for_order=true&key=wc_order_KFPu4ueu8WW6W&change_payment_method=6270&_wpnonce=8cc025c895'

In the first link there was subscription_renewal parameter in the link. Now there is change_payment_method as parameter in the link. My problem is now, that the 3DS authorization dont work on the 'subscription_renewal' process. It only works in change_payment_method process.

I tried all this in the test store with Stripe test data and not in our live system

In this context, I found another problem.

If you want to change your credit card for an existing subscription and use a credit card with 3DS, the renewal payment does not work.

This was a test transaction:

Screenshot Screenshot direct link: QY16ci.png

In point 1, the payment of the renewal order is attempted with the new credit card data previously entered by the customer. However, in this test case, the customer has already confirmed 3DS when adding the new credit card.

However, the 3DS confirmation used in the subscription payment data is not listed here because it was apparently not saved.

After the payment failed, the customer clicked again on pay and then again entered the credit card data and confirmed 3DS. Then the payment was also approved.

But this means that in the subscription itself you can not change the payment method to a credit card with 3DS, because then the next payment will always fail.

csmcneill commented 1 year ago

As discussed in p1692714215024519-slack-C7U3Y3VMY I am unable to reproduce this issue (with or without a change in a subscription's price). I receive the 3DS prompt when paying via the Always authenticate 3DS card even with the payment URL that does not contain the wc-stripe-confirmation=1 string:

https://[redacted]/checkout/order-pay/11100/?pay_for_order=true&key=[redacted]&subscription_renewal=true
agenceKanvas commented 2 months ago

@csmcneill When you make your tests, do you try to do so with an active subscription, and then try to update the payment ? I've added the card number I use in test mode when I do the test and I don't have the 3Dsecure prompt.

aheckler commented 2 months ago

I just tested this again per my instructions in the description and, for better or worse, both flows now do the same thing: take you to the checkout page but require you to actually click to checkout before the 3DS modal appears.

There's a new problem with the email link though: paying that way shows a WC error that the order is on hold and cannot be paid for. However, the 3DS modal shows over top of it, and if you authorize via the modal, it does end up going through just fine. ¯_(ツ)_/¯