Fix FlowController bypassing mandate display when setupFutureUsage is added#12973
Merged
cttsai-stripe merged 6 commits intoApr 28, 2026
Merged
Conversation
… added When a merchant calls configureWithIntentConfiguration() to add setupFutureUsage after the user has already entered card details, the PaymentSelectionUpdater preserved the card selection — allowing confirm() to proceed without the user ever seeing the mandate text. This adds a check in shouldAskForMandate() that invalidates the card selection when the new metadata would show mandate text but the card was entered without setupFutureUsage awareness. Respects termsDisplay=NEVER for merchants who display mandate externally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Committed-By-Agent: claude
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Committed-By-Agent: claude
…rim KDoc Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Committed-By-Agent: claude
Matches the actual merchant API (deferred intent flow) instead of configureWithPaymentIntent + loader mutation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Committed-By-Agent: claude
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Committed-By-Agent: claude
…date-bypass-on-sfu-update Committed-By-Agent: claude # Conflicts: # CHANGELOG.md
Collaborator
There was a problem hiding this comment.
Does Embedded have a similar issue?
Contributor
Author
There was a problem hiding this comment.
Embedded does not have this issue. DefaultEmbeddedSelectionChooser.hasCompatibleForm() compares form element counts between the previous and new metadata. When SFU is added to a card, CardDefinition.createFormElements() adds a MandateTextElement, making newFormElements.size > previousFormElements.size, so hasCompatibleForm returns false and the selection is invalidated.
It is a less explicit check than what this PR adds to PaymentSelectionUpdater (form element count comparison vs. direct mandate check), but it covers this case.
toluo-stripe
approved these changes
Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a bug where
PaymentSheet.FlowControllerallowsconfirm()to proceed without showing legally required mandate/terms text whensetupFutureUsageis dynamically added viaconfigureWithIntentConfiguration().Jira: RUN_MOBILESDK-5344
Motivation
When a merchant calls
FlowController.configureWithIntentConfiguration()to addsetupFutureUsage = offSessionafter the user has already entered card details, thePaymentSelectionUpdaterpreserved the card selection — allowingconfirm()to proceed without the user ever seeing the mandate text that the SDK itself would display in the card form.iOS correctly clears
paymentOptionin this scenario, forcing the user back through the payment sheet. Android did not.Changes
PaymentSelectionUpdater.kt: AddedneedsMandateDisplayForCard()toshouldAskForMandate(). Invalidates aNew.Cardselection when:hasIntentToSetup && mandateAllowed, orforceSetupFutureUseBehaviorAndNewMandate)setupFutureUsage(user never saw mandate)termsDisplay = NEVER— merchant handles mandate externallyPaymentSelectionUpdaterTest.kt: Added 3 unit tests:termsDisplay = NEVERDefaultFlowControllerTest.kt: Added 1 integration test usingconfigureWithIntentConfigurationto simulate the full merchant reconfiguration flow withDefaultPaymentSelectionUpdater.FakePaymentElementLoader.kt: AddedupdateStripeIntent()for changing the intent between configure calls in tests.Testing
Impact
Merchants using deferred intents who dynamically add
setupFutureUsagewill now have their card selection cleared, requiring the user to re-open the payment sheet and see the mandate text before confirming. Merchants usingtermsDisplay = .never(who display mandate externally) are unaffected.Changelog
FlowControllerwould bypass mandate display whensetupFutureUsagewas added viaconfigureWithIntentConfiguration()after the user had already entered card details.