-
Notifications
You must be signed in to change notification settings - Fork 111
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
Always mark failed order as pending before re-attempting a payment #14746
base: trunk
Are you sure you want to change the base?
Always mark failed order as pending before re-attempting a payment #14746
Conversation
📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.
|
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.
Had some questions about the order status update, but testing on an iPhone device worked so didn't want to block the PR.
Re-collect order (Scenario already works on 21.3)
For two WPCOM test stores with WC 9.5.1 and WooPayments 8.6.1, I didn't receive an email from failed payments on iPad 10th gen iOS 18.0 simulator. But when testing on iPhone device worked, not sure why 😅 Both with simulated card reader.
Just curious, how is email sent from core, it probably costs something to send email?
let action = OrderAction.updateOrderStatus(siteID: order.siteID, | ||
orderID: order.orderID, | ||
status: .pending, onCompletion: { _ in }) | ||
stores.dispatch(action) |
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.
❓ do we need to wait for the async order status update to complete before the next step in order payment collection for the email feature to work consistently? Probably no issues in good network conditions, but there might be edge cases like if this API request fails or takes longer than the next payment steps. On the other hand, if we wait for this order status remote update, it adds to the total time to process a payment.
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.
After taking a look at the OrderACtion.updateOrderStatus
implementation, it looks like it's just a local update in storage (and the return value seems misleading with the old status but this is unrelated to the PR). How does this have the effect remotely to trigger the order status pending -> failed actions on the server side, is the order updated remotely somewhere else? If so, maybe a comment is helpful for future developers to know how this order status update takes effect.
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.
Of course, it's not ideal to make such a change from the client side and likely we should consider looking for backend solutions as well 🤔 .
If Woo mobile is the only client of the payments/orders/orderID/capture_terminal_payment
endpoint (or another endpoint made for payment), I think we can add the order status update there.
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.
After taking a look at the OrderACtion.updateOrderStatus implementation, it looks like it's just a local update in storage (and the return value seems misleading with the old status but this is unrelated to the PR
This action calls func updateOrder(siteID: Int64, orderID: Int64, status: OrderStatusEnum, onCompletion: @escaping (Error?) -> Void)
method which does call remote.
However, I agree that it should be done clearer.
Probably no issues in good network conditions, but there might be edge cases like if this API request fails or takes longer than the next payment steps. On the other hand, if we wait for this order status remote update, it adds to the total time to process a payment.
It's true, and yes, I don't want to be making the request even slower.
If Woo mobile is the only client of the payments/orders/orderID/capture_terminal_payment endpoint (or another endpoint made for payment), I think we can add the order status update there.
That's a good idea and I would prefer that. I will not merge this PR for now and explore this option.
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.
We're not calling our API for the failed payment, only Stripe API.
But I think there's more more options to explore:
Could payment gateways trigger woocommerce_order_status_failed_notification
which is used to send emails during the repeated payment failure. The more I look at these local changes, the more I dislike them.
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.
I opened up this topic pcreKM-3aC-p2#comment-4213 here. Maybe it could be improved together with other necessary improvements.
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.
Another potential solution is to set the order to pending while checking order eligibility. That allows to wait for completion while integrating within already existing request and not prolonging the payment:
I'll leave it at that for now.
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.
Another potential solution is to set the order to pending while checking order eligibility. That allows to wait for completion while integrating within already existing request and not prolonging the payment:
Yea, setting the order status as pending at the beginning of the payment could work, can double-check with the team just to make sure there are no side effects as lots of actions and filters depend on the order status. In the commit it looks like we can replace the remote order retrieval with the remote order status update, so performance wise it's likely similar to before.
@@ -361,6 +361,75 @@ final class CollectOrderPaymentUseCaseTests: XCTestCase { | |||
// Then | |||
XCTAssertEqual(mockPaymentOrchestrator.spyChannel, .pos) | |||
} | |||
|
|||
func test_collectPayment_when_order_failed_then_marked_as_pending() async throws { |
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 for adding the test cases!
Generated by 🚫 Danger |
Version |
Description
From WooCommerce 8.6+ order is set to failed when card_present payment payment fails. It triggers a chain reaction on WooCommerce, which performs actions when the status changes to failed, most importantly sending email receipts.
However, if we make another failed payment on an order with an already failed status, the actions are no longer triggered.
In #14475, I made a change that sets order to pending when re-collecting the payment from Order Details view. It covers most of the scenarios but not all. It didn't take into account payment retries or later introduced a fallback payment method.
On the web, setting order status to pending is the first action when processing payment.
Of course, it's not ideal to make such a change from the client side and likely we should consider looking for backend solutions as well 🤔 .
Steps to reproduce
Retrying the same payment won't generate an email for another reason pcreKM-3aC-p2. However, this fix should allow repeated payment to work once the backend is improved.
For now, using a fallback payment method flow allows to test a specific scenario.
Re-collect order (Scenario already works on 21.3)
Fallback payment method flow (Scenario doesn't work on 21.3)
Testing information
Tested on iPhone 14 Pro 17.7
This change only affects failed orders which are only set to failed from WooCommerce 8.6. It won't affect all the other existing flows.
RELEASE-NOTES.txt
if necessary.Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement: