Skip to content
New issue

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

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

Already on GitHub? # to your account

[IPP/POS] Automatically Cancel Payment Intents #13719

Draft
wants to merge 6 commits into
base: trunk
Choose a base branch
from

Conversation

malinajirka
Copy link
Contributor

@malinajirka malinajirka commented Mar 11, 2025

Closes: #13593

Description

Note: The code complexity introduced in this PR is IMO not worth merging, especially considering it doesn't solve all the edge-cases. I'm creating the PR so we can discuss it and document the decision, however, I'd personally vote for leaving the code as is (prior this PR). cc @kidinov @samiuelson @AnirudhBhat in case you believe this PR is still worth merging or if you believe we should continue looking into this.

This PR adds an additional safety measure to ensure the app doesn't leave Payment Intents in an uncaptured state (on hold state) - this is not a critical issue, since the payment authorization expires after a few days and the Payment Intent gets cancelled automatically.

We added a basic safety measure a few weeks ago in this PR which prevents users from leaving the payment flow by tapping on the back button. However, this solution doesn't cover edge cases and is dependent on the implementation of the client app which could potentially bite us in the future. The goal of this PR is to ensure this issue is solved even if the client app doesn't suppress the back button.

This PR doesn't completely solve the problem since we are not cancelling Payment Intents in the Requires Capture state, since the Stripe SDK doesn't change the status of the Payment Intent after it's successfully captured -> this is understandable, since capturing payment intent doesn't involve communication with the SDK at all, the app communicates only with the Woo site and the site communicates with Stripe's backend. We could potentially try to cancel PI in the Requires capture state and rely on the fact that completed payments can't be cancelled, however, this doesn't work either, since Stripe refunds the payment in such case which is likely not what we want.

Bottom line is, that I believe preventing users from pressing the back is a good enough solution and it's likely not worth further effort to try to fix this in the CardReaderModule layer.

Steps to reproduce

Revert changes done in this PR to ensure you can easily reproduce the issue.

  1. Enter POS
  2. Add a product to the cart
  3. Tap on Checkout
  4. Tap your card on the reader
  5. Press back during the processing payment step
  6. Look at Stripe's dashboard and notice there are two records for this order - completed and incomplete/uncaptured.

Testing information

  • Test all scenarios that come to mind, including re-enabling the back-button to easily test various cancellation scenarios.

The tests that have been performed

I have tested many different scenarios

  • Tapping the back button during the processing payment step and then tapping again and letting the flow complete => the PI gets cancelled correctly and new PI completes successfully.
  • Using live card to simulate an error and then retrying using the test card => the same PI is re-used and completes successfully.
  • Tapping the back button during the capturing step and then tapping again and letting the flow complete => WooPayments correctly detects that the payment is already paid and user is not double-charged.

Images/gif

  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

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:

  • The PR is small and has a clear, single focus, or a valid explanation is provided in the description. If needed, please request to split it into smaller PRs.
  • Ensure Adequate Unit Test Coverage: The changes are reasonably covered by unit tests or an explanation is provided in the PR description.
  • Manual Testing: The author listed all the tests they ran, including smoke tests when needed (e.g., for refactorings). The reviewer confirmed that the PR works as expected on big (tablet) and small (phone) in case of UI changes, and no regressions are added.
3593

@dangermattic
Copy link
Collaborator

1 Message
📖 This PR is still a Draft: some checks will be skipped.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Collaborator

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App Name WooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commit3cde3ca
Direct Downloadwoocommerce-wear-prototype-build-pr13719-3cde3ca.apk

paymentIntent.status == PaymentIntentStatus.REQUIRES_CONFIRMATION
if (paymentIntent.status != PaymentIntentStatus.SUCCEEDED &&
paymentIntent.status != PaymentIntentStatus.CANCELED &&
paymentIntent.status != PaymentIntentStatus.REQUIRES_CAPTURE
Copy link
Contributor Author

Choose a reason for hiding this comment

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

📓 Previously, we were whitelisting statuses that should be cancelled. I believe this is not correct and we should attempt to cancel all nonfinal statuses. Ideally even Requires capture, however, this one is more tricky as mentioned in the description of this PR.

}
}
} finally {
if (!eligibleForRetry) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea here is that if the PaymentIntent can be used for retries => we shouldn't cancel it as we'd break the retry logic, but we should cancel all other non-final payment intents.

@wpmobilebot
Copy link
Collaborator

📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App Name WooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commit3cde3ca
Direct Downloadwoocommerce-prototype-build-pr13719-3cde3ca.apk

@malinajirka malinajirka changed the title Automatically Cancel Payment Intents [IPP/POS] Automatically Cancel Payment Intents Mar 31, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Woo POS] Payment Intent Is Not Cancelled On Back Press
3 participants