Skip to content

[Link OTP in WalletsButton] Resend code logic #10929

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

Merged
merged 26 commits into from
Jun 10, 2025

Conversation

carlosmuvi-stripe
Copy link
Collaborator

@carlosmuvi-stripe carlosmuvi-stripe commented Jun 9, 2025

Summary

  • Adds resend code button in inline OTP
  • Uses linkGate to enable inline OTP instead of directly checking the fflag.
record_2fa_resend.mp4

Testing

  • Added tests
  • Modified tests
  • Manually verified

@carlosmuvi-stripe carlosmuvi-stripe changed the base branch from master to carlosmuvi/embedded-otp-2-complete-verification June 9, 2025 15:15
Copy link
Contributor

github-actions bot commented Jun 9, 2025

Diffuse output:

OLD: identity-example-release-base.apk (signature: V1, V2)
NEW: identity-example-release-pr.apk (signature: V1, V2)

          │          compressed          │         uncompressed         
          ├───────────┬───────────┬──────┼───────────┬───────────┬──────
 APK      │ old       │ new       │ diff │ old       │ new       │ diff 
──────────┼───────────┼───────────┼──────┼───────────┼───────────┼──────
      dex │   2.1 MiB │   2.1 MiB │  0 B │   4.3 MiB │   4.3 MiB │  0 B 
     arsc │     1 MiB │     1 MiB │  0 B │     1 MiB │     1 MiB │  0 B 
 manifest │   2.3 KiB │   2.3 KiB │  0 B │     8 KiB │     8 KiB │  0 B 
      res │ 302.9 KiB │ 302.9 KiB │  0 B │   457 KiB │   457 KiB │  0 B 
   native │   6.2 MiB │   6.2 MiB │  0 B │  15.8 MiB │  15.8 MiB │  0 B 
    asset │   7.7 KiB │   7.7 KiB │  0 B │   7.4 KiB │   7.4 KiB │  0 B 
    other │  95.7 KiB │  95.7 KiB │ -1 B │ 183.5 KiB │ 183.5 KiB │  0 B 
──────────┼───────────┼───────────┼──────┼───────────┼───────────┼──────
    total │   9.8 MiB │   9.8 MiB │ -1 B │  21.8 MiB │  21.8 MiB │  0 B 

 DEX     │ old   │ new   │ diff      
─────────┼───────┼───────┼───────────
   files │     1 │     1 │ 0         
 strings │ 20663 │ 20663 │ 0 (+0 -0) 
   types │  6492 │  6492 │ 0 (+0 -0) 
 classes │  5258 │  5258 │ 0 (+0 -0) 
 methods │ 31487 │ 31487 │ 0 (+0 -0) 
  fields │ 18210 │ 18210 │ 0 (+0 -0) 

 ARSC    │ old  │ new  │ diff 
─────────┼──────┼──────┼──────
 configs │  164 │  164 │  0   
 entries │ 3646 │ 3646 │  0
APK
   compressed    │   uncompressed   │                                           
──────────┬──────┼───────────┬──────┤                                           
 size     │ diff │ size      │ diff │ path                                      
──────────┼──────┼───────────┼──────┼───────────────────────────────────────────
    269 B │ -3 B │     120 B │  0 B │ ∆ META-INF/version-control-info.textproto 
 29.2 KiB │ +3 B │  64.6 KiB │  0 B │ ∆ META-INF/CERT.SF                        
 25.9 KiB │ -3 B │  64.5 KiB │  0 B │ ∆ META-INF/MANIFEST.MF                    
  1.2 KiB │ +2 B │   1.2 KiB │  0 B │ ∆ META-INF/CERT.RSA                       
──────────┼──────┼───────────┼──────┼───────────────────────────────────────────
 56.5 KiB │ -1 B │ 130.5 KiB │  0 B │ (total)

@carlosmuvi-stripe carlosmuvi-stripe force-pushed the carlosmuvi/embedded-otp-3-resend branch from edd2759 to 8fe186a Compare June 9, 2025 15:37
Base automatically changed from carlosmuvi/embedded-otp-2-complete-verification to master June 9, 2025 16:12
…arlosmuvi/embedded-otp-3-resend

# Conflicts:
#	paymentsheet/src/main/java/com/stripe/android/link/verification/DefaultLinkInlineInteractor.kt
…-otp-3-resend

# Conflicts:
#	paymentsheet/src/main/java/com/stripe/android/link/verification/DefaultLinkInlineInteractor.kt
#	paymentsheet/src/test/java/com/stripe/android/link/verification/DefaultLinkInlineInteractorTest.kt
@carlosmuvi-stripe carlosmuvi-stripe changed the title [Link OTP in WalletsButton] Resend code. [Link OTP in WalletsButton] Resend code logic Jun 9, 2025
Comment on lines +40 to +44
override val useInlineOtpInWalletButtons: Boolean
get() {
return FeatureFlags.showInlineOtpInWalletButtons.isEnabled && useNativeLink
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Using LinkGate to also avoid showing the inline 2FA on non-native-link scenarios.

Comment on lines +68 to +71
OTPSection(
verificationState = verificationState,
otpElement = otpElement
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no new code, just extracted to method + added the resend code button.

Comment on lines +140 to +153
private fun update2FAState(
block: (VerificationViewState) -> VerificationViewState,
) {
val currentState = state.value.verificationState
if (currentState is Render2FA) {
val newState = currentState.copy(viewState = block(currentState.viewState))
updateState { it.copy(verificationState = newState) }
} else {
logger.error(
"Expected Render2FA state but found ${currentState::class.simpleName}. Resetting to RenderButton."
)
updateState { it.copy(verificationState = VerificationState.RenderButton) }
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

extracted this update logic to a method as it's reused on several places.

@carlosmuvi-stripe carlosmuvi-stripe marked this pull request as ready for review June 9, 2025 16:50
@carlosmuvi-stripe carlosmuvi-stripe requested review from a team as code owners June 9, 2025 16:50
val currentState = state.value.verificationState
if (currentState is Render2FA) {
val linkAccountManager = currentState.linkAccountManager()
val result = linkAccountManager.startVerification()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we show the loading indicator for a minimum amount of time, so that it's obvious that a new code is being sent?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think we should be good here:

  • The loading shows while the verification API call takes place. We also show a toast when the verification completes.
  • This is the pattern on other OTP instances

We can potentially ad a delay after startVerification to hold the state change a bit, but feels wrong.

Attached a video of how it looks today on a real device.

loading_2fa.mp4

@@ -22,15 +28,18 @@ internal class WalletButtonsContent(
@Composable
fun Content() {
val state by interactor.state.collectAsState()
val context = LocalContext.current
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Let's move this into ResendCodeNotificationEffect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@carlosmuvi-stripe carlosmuvi-stripe merged commit 6be34e3 into master Jun 10, 2025
13 checks passed
@carlosmuvi-stripe carlosmuvi-stripe deleted the carlosmuvi/embedded-otp-3-resend branch June 10, 2025 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants