-
Notifications
You must be signed in to change notification settings - Fork 207
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 duplicate emails and order notes when processing setup intent requests #3421
Conversation
@@ -795,11 +795,13 @@ private function process_payment_with_deferred_intent( int $order_id ) { | |||
$this->update_saved_payment_method( $payment_method_id, $order ); | |||
} | |||
|
|||
// Lock the order before we create and confirm the payment/setup intents to prevent Stripe sending the success webhook before this request is completed. | |||
$this->lock_order_payment( $order ); |
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.
Hey @Mayisha, in the changes you made in #3331, the lock was added after the validate_minimum_order_amount()
call and so I've been trying to test and break this PR to see if there's any issues with it being before validate_minimum_order_amount()
.
When I tested with a $0.40 product, the lock gets added even though there's a checkout error, but I haven't been able to break it because when I add 2 of these to meet the minimum amount, the checkout is then successful.
I wanted to ping you on this issue to ask if you discovered any issues with this?
The alternative was to either add two calls to lock_order_payment()
for both payment/setup intent calls or move the validate_minimum_order_amount()
higher up in the process_payment_with_deferred_intent()
function 🤔
Let me know if you had any thoughts :)
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.
You are right Matt. I intended to add the lock right before processing the intent if it passes validate_minimum_order_amount
.
However, I also could not break it and the checkout was successful on second attempt (when I increased the number of items or add a shipping charge).
What happens here is, on the first attempt an order is created and the order status is failed
. On the second attempt a new order gets created then successfully gets processed and so the lock on the first order does not hamper the checkout.
In the database, the transient of the first failed orders remain.
It is alright in my opinion as the transient will be cleared once it reaches the expiration time.
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.
Thanks @mattallan for working on this. Reproducing this issue was difficult and you did a great job there.
The changes look good to me 🎉
- In
develop
branch I can reproduce the double note/email issue for a subscription product having free trial. - In this branch, I do not get any duplicate notes or emails neither for a regular product nor for a subscription product having free trial.
Note: Remember to add the changelog entry also in readme.txt
👀
Hello, I am still having issues with this. I have the most recent version. Is there anything I need to update? |
@dwh10045 we had the same issue and decided to use 8.6.1 as 7.x doesn't have this commit. So far just one order came through without duplicates. |
Hi @dwh10045 Please share which version of the Stripe plugin you are using and the payment methods used in the affected orders. |
Fixes #3414
Changes proposed in this Pull Request:
In #3331 (shipped in 6.6.1) we added
lock_order_payment()
andunlock_order_payment()
to the start and end of ourprocess_payment_with_deferred_intent()
function to fix an issue with duplicate order notes and order emails being sent.Because the
lock_order_payment()
was only added inside the$payment_needed
condition, the bug was unfortunately still present for our setup intent requests (i.e. Subscriptions with no initial payment).To fix this, I've moved the lock to be outside of the
$payment_needed
condition but still before the payment and setup intents are created/confirmed. This will cause our webhook handler to exit early (code ref) while the order is locked and letprocess_payment_with_deferred_intent()
finish processing the payment and marking the order as processing/completed.To help visualise the issue, here's a very rough timeline of how the duplicate customer emails & order notes issue occurs:
Testing instructions
Important
To replicate this issue you need to have the
setup_intent.succeeded
webhook processed at the same time thatprocess_payment_with_deferred_intent()
is still processing the payment for the current order.Specifically, we want the order to still have a "pending" status when an instance is fetched in our webhook handling code.
Since we cannot easily control when Stripe sends the webhook, I was able to consistently replicate this by adding a
sleep(2);
just before$order->payment_complete();
in ourprocess_payment_with_deferred_intent()
(here in the code)How does this happen?
It's hard to pin-point exactly how this would happen however, Stripe controls when the webhooks are sent and there's a lot of processing between sending our intent requests -> receiving the response -> completing the payment/checkout process.
This means if there's any unexpected lag or delays (i.e. slow DB reads, slow API request, slow third party code), it could cause both the webhook handling and process payment functions to have a pending order and try to mark it as completed at the same time, resulting in duplicate emails and order notes.
develop
complete the checkout using the standard4242424242424242
cardchangelog.txt
andreadme.txt
(or does not apply)Post merge