-
Notifications
You must be signed in to change notification settings - Fork 68
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
Fix recurring payments on Indian CCs #3011
Fix recurring payments on Indian CCs #3011
Conversation
includes/compat/subscriptions/trait-wc-payment-gateway-wcpay-subscriptions.php
Outdated
Show resolved
Hide resolved
I'm wondering if we should handle the payment intent failed response from Stripe to add another order note and provide some more details on why it failed, to the merchant. For now, Stripe sent us 2 cards that fail with a specific decline code (mentioned in testing instructions). We could handle those 2, but to do that we will need to also update the server to forward the I'll appreciate any thought here. I see it as a bit out of the scope of this PR. Should we implement it here? Create another issue? Or is there a reason to not do this? cc @Automattic/sigma |
65659c7
to
004e1ce
Compare
Another question about order notes involving greater changes and a bit out of the scope in this PR. If the mandate becomes invalid the merchant will see the following error. Looks like we just append the error message from Stripe on subscription payment fails. And not sure if we should improve at least this message to provide more useful information. Something like What do you all think? Should we create another issue for this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested and all working perfectly after we finished debugging, nice work! 👍 I think this is ready to 🚢 once tests are done.
My thoughts on the comments you raised are as follows:
I'm wondering if we should handle the payment intent failed response from Stripe to add another order note and provide some more details on why it failed, to the merchant.
For now, Stripe sent us 2 cards that fail with a specific decline code (mentioned in testing instructions). We could handle those 2, but to do that we will need to also update the server to forward the payment_intent.payment_failed to the client. AFAIK it isn't being forwarded for now.
I'll appreciate any thought here. I see it as a bit out of the scope of this PR. Should we implement it here? Create another issue? Or is there a reason to not do this?
I think it would be great for us to provide a generalised order note for example "A request to authorise this payment failed with the following error code: transaction_not_approved
", but I think given we want to get this fix out, it would be fine to do this in a follow up issue.
I also agree with David about handling the other error message an a more friendly way but again this can be done in a followup issue IMO.
Thanks a lot @dmallory42! I already added tests for the new code and created a follow-up issue (#3075). I think we should ship this ASAP and then improve the order notes to provide better input about failing orders to merchants. |
As mentioned in pc4etw-ky-p2#comment-962, if we want to include this PR in a point release of WCPay 3.1.x, please target |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me! I don't see any differences between this PR and my own PR in woocommerce/woocommerce-gateway-stripe#1981.
@ricardo found an issue in my PR that I think you have to address in this PR as well, but otherwise this is looking good 👌
includes/compat/subscriptions/trait-wc-payment-gateway-wcpay-subscriptions.php
Outdated
Show resolved
Hide resolved
bd5b52d
to
e513ff0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: @ismaeldcom - can you help add changelog entries for readme.txt and changelog.txt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🙂
Found an issue with UPE testing it again today. The mandate options were not added to subscriptions using UPE and a new card. Because we use another process, creating the intent without confirm, where I initially added the new code. For it to work we need to add the To ensure this is properly covered, I'll appreciate a pair of hands testing it. Will be enough to just place a subscription order following the main testing instructions, but using a new card, you just need to remove it if they are already used. Until #3118 got merged, would be better to add something like |
Hey @Automattic/helix! We finally have the PR ready for review. I've made some updates to the code as a lot of things have changed since the initial implementation. I would like to know if we need to consider anything else for WCPay Subscriptions and if there is a way to test manual renewals like in WC Subs. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ismaeldcom first of all - big thanks for working on this one! I know it wasn't an easy one and it was blocked a couple of times, great to see it's ready now 🎉
I followed testing instructions very accurately (classic + UPE). I can confirm that it works as expected: successful and failed renewals for different reasons. I also noticed that after successful renewal another one is scheduled depending on the subscription frequency.
The code is clean and straightforward, documented very well, and covered by tests, I only described a few nitpicks, overall the code is looking great 💪
I know that it's still open whether it needs additional work regarding WCPay Subscriptions, but I am pre-approving the PR and looking forward to feedback from the Helix team.
includes/compat/subscriptions/trait-wc-payment-gateway-wcpay-subscriptions.php
Outdated
Show resolved
Hide resolved
FYI @shendy-a8c - this needs a Helix review, maybe already on your radar? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intended to always pass mandate params (from get_mandate_params_for_order()
and get_mandate_param_for_renewal_order()
) even though payment is using a card not issued by India bank?
I was expecting a check if card is issued by India bank and only then pass the mandate parameters but maybe checking which bank country issues the card isn't possible so we have to always pass mandate params to Stripe and Stripe will return mandate id when we receive the payment_intent.succeeded
webhook event.
includes/compat/subscriptions/trait-wc-payment-gateway-wcpay-subscriptions.php
Show resolved
Hide resolved
includes/compat/subscriptions/trait-wc-payment-gateway-wcpay-subscriptions.php
Show resolved
Hide resolved
Is mandate tied to specific card? If someone knows a mandate id, can they use it to create a payment intent with different card and by pass the needed customer confirmation? |
Instruction to test WCPay Subscription renewal can be found here: PCYsg-DQ4-p2. |
I saw this PR branch was pretty behind |
Will this be addressed, maybe in different PR? If so, please create a separate issue so it is not forgotten. Changing payment method is part of the critical flows (ref) but I bet it won't be detected as bug because GlobalStep likely will test using US card. |
There is no need for $additional_parameters in create_intention
Thanks for the detailed review @shendy-a8c!
As far as I know, the is no way to check if the card is issued by an Indian bank. Although, now that you mention it, we can consider passing them only for orders using INR currency. Stripe will only return a mandate ID for those cases that require it.
The mandate is tied to both the card and subscription. Using an existing mandate ID in an intent with a different card it will fail and show the
Thanks! I'll test it and update the PR accordingly soon.
Sure! 🙂
Yes, I plan to create a followup issue for both of the known issues before merging this. The PR has been blocked for more than a year, and delaying it again to fix those issues could end up in another big refactor due to planned changes in the affected code. I think it's safe to proceed with it, as it will at least allow renewing subscriptions without errors. |
Cool. I was just checking. I don't think there is any change needed here.
I think checking for currency is not ideal because the requirement is on the card itself, ie if it's issued by India bank, despite the currency, right? |
Yep, Stripe mentions |
Hey @shendy-a8c! Now that every comment is resolved, Follow-up issues:
After testing early renewals using WCPay Subscriptions it seems to work as expected. But as it relies on Stripe Billing the mandate is not attached to the intent. So I'm thinking to create another issue to confirm, by asking Stripe first, if we also need to do something in our end for India recurring payments using the Billing API. If you agree with the mentioned idea, would you mind creating the WCPay Subscription issue? I'm sure you have way more knowledge about how it works than me, and could add a better description 🙂 |
Sounds like a plan, @ismaeldcom.
I think 'early renewal' is not the term you meant here. WCPay Subscriptions does not support early renewals (ref). With WooCommerce Subscriptions, early renewal is possible. Early renewal means one (customer or merchant) can renew the subscriptions before the expected renewal date. Testing WCPay Subscriptions with billing clock even though feels like renewing the subscriptions before the expected renewal date, it is not an early renewal because it is just a way to move the time forward artificially.
Any link to the payment intent you tested? It might be because you tested with billing clock.
I like to make sure it's really a problem by testing without billing clock. More details can be found here: pdjTHR-21b-p2. As of this PR, I think it looks good and I think it's a good idea to wrap up and follow up with new issues you created and one that I might create after I can confirm there is a problem with WCPay Subscriptions. |
You're right! I didn't choose the best name here 🙂 I meant what you explained, using the test billing clock.
Sure, here is one example: https://dashboard.stripe.com/test/connect/accounts/acct_1Lwn9BQrnu7Ppo4o/payments/pi_3MByt5Qrnu7Ppo4o1TeYLfEs And yes, I think that's the cause. If I understood the way it works, it creates a test subscription (with a test customer) under the hood. So I think it's expected to not attach the mandate. Thanks approving the PR and organizing the P2 with further testing for WCPay Subscriptions 👍 |
I just created #5311 to fix WCPay Subscriptions renewals with Indian CC. |
Fixes #2935
Changes proposed in this Pull Request
With the new regulations to process recurring payments for cards issued by Indian banks, we need to generate and save a mandate ID, which will be attached to every renewal order.
get_mandate_params_for_order
and call it withinprocess_payment
andprocess_payment_for_order
using$additional_api_parameters
._stripe_mandate_id
.get_mandate_param_for_renewal_order
and call it withinscheduled_subscription_payment
using$additional_api_parameters
.maybe_add_customer_notification_note
and call it withinprocess_payment_for_order
with the new$processing
property.$processing
property toWC_Payments_API_Intention
to be able to accesscustomer_notification
.last_payment_error
instead. Add messages for the new codes, and include the Stripe error message with our default one.Known issues
Error: Only active mandates can be used with PaymentIntents.
mandate.updated
webhook.Testing instructions
Requirements
INR
using Multi-currency or updating your store currency.npm run listen
)₹15,000 INR
and another one over it.WC Subscriptions – Single subscription
woocommerce_scheduled_subscription_payment
.subscription_id
matches the 5 subscriptions you have just created.WC Subscriptions – Multiple subscriptions
4000003560000123
with multiple subscriptions with:woocommerce_scheduled_subscription_payment
.subscription_id
matches the 2 subscriptions you have just created.UPE vs classic checkout
The previous testing instructions should work for both UPE and classic checkout. Please test it using the missing one.
WCPay Subscriptions
Does not apply.
Screenshots
Known issues
Post merge