Skip to content

Auth Tab, Close listener functionality #409

Open
kgangineni wants to merge 32 commits intodevelopfrom
closeAuthTab
Open

Auth Tab, Close listener functionality #409
kgangineni wants to merge 32 commits intodevelopfrom
closeAuthTab

Conversation

@kgangineni
Copy link
Collaborator

Summary of changes

  • Introduces auth tab functionality
  • introduces new overloaded function
    kotlinfun start( activity: Activity, request: PayPalWebCheckoutRequest, activityResultLauncher: ActivityResultLauncher<Intent>, callback: PayPalWebStartCallback ) { }
    to pass activityResultLauncher parameter
  • Auth tab is allowed on devices with chrome version 137+ (may be hard to create in emulator but able to do in pixel devices)
  • API works including callback in ActivityLauncher on all chrome versions, it might not have additional security provided auth tab in lower versions of chrome

Checklist

  • Added a changelog entry

Authors

List GitHub usernames for everyone who contributed to this pull request.

sshropshire and others added 24 commits December 8, 2025 11:39
  - Add AuthTabClient to CorePayments for managing auth tab flows
  - Update PayPalWebCheckoutClient to support ActivityResultLauncher
  - Add useAuthTabLauncher toggle in demo app for testing
  - Update browser switch clients to handle auth tab integration
  - Add androidx.browser:auth dependency for auth tab support
- Add AuthTabClientUnitTest to test auth tab launch scenarios
- Extend BrowserSwitchClientUnitTest with activity launcher tests
- Add PayPalWebLauncherUnitTest cases for activity launcher variant
- Test auth tab launch with appLinkUrl and returnUrlScheme
- Test error handling for auth tab launch failures
- Verify correct token types and request codes
@kgangineni kgangineni marked this pull request as ready for review January 16, 2026 18:01
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/paypal/android/corepayments/Address;)Lcom/paypal/android/cardpayments/Card;
public static synthetic fun copy$default (Lcom/paypal/android/cardpayments/Card;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/paypal/android/corepayments/Address;ILjava/lang/Object;)Lcom/paypal/android/cardpayments/Card;
public fun describeContents ()I
public final fun describeContents ()I
Copy link
Collaborator

Choose a reason for hiding this comment

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

In a strict sense, this is technically a breaking change. Is there a way to prevent this change?

composeOptions {
// Ref: https://developer.android.com/jetpack/androidx/releases/compose-kotlin#pre-release_kotlin_compatibility
kotlinCompilerExtensionVersion "1.5.14"
kotlinCompilerExtensionVersion "1.5.15"
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is probably what caused the breaking changes.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure though actually, pure speculation.

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 I think this is because of kotlin version update, this is only for demo app, we don't do api check for demo app

OnLifecycleOwnerResumeEffect {
val intent = context.getActivityOrNull()?.intent
intent?.let { viewModel.completeAuthChallenge(it) }
if (!uiState.useAuthTabLauncher) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

In a fallback scenario where AuthTab is unavailable and a CCT is launch, would useAuthTabLauncher == true prevent the deep link from being captured?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed by adding check for it, good catch

private fun Step2_StartPayPalCheckout(uiState: PayPalUiState, viewModel: PayPalCheckoutViewModel) {
val context = LocalContext.current

val activityResultLauncher = rememberLauncherForActivityResult(
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should probably be hoisted to the top level. The activity result launcher is only registered in Step2. In a cold start scenario, the deep link won't be captured.

// do nothing; wait for user to authenticate PayPal checkout in Chrome Custom Tab
}
if (useAuthTabLauncher && activityResultLauncher != null) {
paypalClient.start(activity, checkoutRequest, activityResultLauncher) { startResult ->
Copy link
Collaborator

Choose a reason for hiding this comment

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

I still feel like we don't need to pass the activity result launcher to PayPalClient. It would clean up the design a lot.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ya, we can definitely achieve it with composable module that's in draft PR, but need to check if we can avoid in non composable scenarios, will try to do on POC next

 - provides Boolean isAuthTabSupported to check if device supports auth tab
 - handle fallback scenarios by using isAuthTabSupported in life cycle methods to avoid race conditions with activityLauncher
- apiDump
- fix static analysis
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