Skip to content
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

[Android] Activity single task. Continuing payment from launcher kills DropIn Activity. #163

Open
Cattari opened this issue Mar 16, 2023 · 22 comments
Labels
bug Something isn't working wontfix This will not be worked on

Comments

@Cattari
Copy link

Cattari commented Mar 16, 2023

Hello, guys!

We are facing a problem with our custom bridge solution for RN + adyen-android module (the same version you use here).
That RN uses singleTask launch mode for the MainActivity. In that case, if a user is in the middle of the payment and goes back to the app from the launcher - it kills the DropInActivity and user doesn't finish the payment. It became very painful after Adyen Checkout API v68 when a user is charged right after they finish a transaction on the banking app.

Several issues are also reported in adyen drop-in and adyen 3ds2 component repositories, but they are closed. Here are they:

Adyen/adyen-android#711 (comment)
Adyen/adyen-3ds2-android#17

To Reproduce

Reproduces only for Android.

Steps to reproduce the behavior:

  1. Start DropIn
  2. Start payment by card for example. Enter 5201 2895 0084 3268 3ds2 card from https://docs.adyen.com/development-resources/testing/test-card-numbers
  3. Receive a confirmation window that requires you to move app to the background and then back again to foreground.
  4. Go back to the app via the app launcher.

Expected behavior
5. User sees the DropIn.

Actual behavior
5. User sees the MainActivity, DropIn is killed.

Smartphone (please complete the following information):

  • Device: Any android device
  • OS: Android

Additional context
We want to know if you handled the mentioned issue in this solution for RN. Because it's directly connected to launchMode=singleTask which is used in RN.

@Cattari Cattari added the bug report when a bug report is created label Mar 16, 2023
@descorp
Copy link
Contributor

descorp commented Apr 13, 2023

Hey @Cattari

Thanks for reaching out!

We are aware of this unfortunate behavior.
None of our tests and attempts to resolve it were fruitful.
This is not a problem for native Android but only affects React Native.
The only reference to the problem we were able to find is not fruitful either.

For now, the only advice we have - is always to be prepared for the worst.
In LIVE transactions the "happy flow" with successful redirect may not occur due to numerous factors on both iOS and Android (even on web).
Always treat your transactions as "pending" until webhook with the actual status received.

For example, you can keep track of a payment state: store the flag when 'onSubmit' is called and when your App leaves the foreground, so when the next time the App is open, no redirect is detected and the flag is set - there is a high chance a payment was made and your backend is the only source of truth now.

@descorp descorp added bug Something isn't working wontfix This will not be worked on and removed bug report when a bug report is created labels Apr 17, 2023
@pinpong
Copy link
Contributor

pinpong commented Apr 27, 2023

Indeed this is another blocker.

@Cattari can you please try poc

We need to check if there are some unknown unwanted behaviors e.g. google pay, google login etc.

@Cattari
Copy link
Author

Cattari commented May 2, 2023

hi @pinpong
yeah, we actually tried that before a long time ago
it solves the issue with the payment flow, but it brings a new issue

if universal/deep links are used, they start a new instance (a copy) of the app, and we didn't manage to avoid that.
unfortunately, for us it's an unacceptable behaviour :(

@momentiris
Copy link

We are facing the same issue.
Do you have a proposed workaround?

Thanks

@StefanWallin
Copy link
Contributor

We are aware of this unfortunate behavior. None of our tests and attempts to resolve it were fruitful. This is not a problem for native Android but only affects React Native. The only reference to the problem we were able to find is not fruitful either.

How about if react-native-adyen tried to serialize it's internal state before handing of, and then when resuming restoring from the serialized state or offering the implementing app to try and resume the checkout session?

For now, the only advice we have - is always to be prepared for the worst. In LIVE transactions the "happy flow" with successful redirect may not occur due to numerous factors on both iOS and Android (even on web). Always treat your transactions as "pending" until webhook with the actual status received.

For example, you can keep track of a payment state: store the flag when 'onSubmit' is called and when your App leaves the foreground, so when the next time the App is open, no redirect is detected and the flag is set - there is a high chance a payment was made and your backend is the only source of truth now.

I don't see how Webhooks can solve the fact that for a 3DS OOB challenge, additionalDetails cannot be submitted so our offers are "stuck" in an "open" state.

@descorp
Copy link
Contributor

descorp commented Jan 29, 2024

@StefanWallin

You have posted previously:

A potential workaround would be for us to store data from our api-request in the onSubmit-callback in local storage, then on component rerender upon activity restart, check for that data and somehow be able to call nativeComponent.handle(data), but we don't have access to nativeComponent in that scope.

To be able to do that we would need to be able to check if the adyen drop-in component is active so as to not trigger multiple nativeComponent.handle(data).

in v2 BETA it is possible to call AdyenAction.handle(data) independently from the payment flow. Maybe this will be a workaround 🤔

@StefanWallin
Copy link
Contributor

@descorp Would you consider v2 BETA production ready yet?

@StefanWallin
Copy link
Contributor

And also, my suggestion above is based on the assumption that the adyen-library can resume the session and call the onAdditionalDetails-callback even though it did not receive any additionalDetails from redirectUri, or display the challenge page again (which might have a button from issuer that triggers additionalDetails)

@descorp
Copy link
Contributor

descorp commented Jan 29, 2024

@StefanWallin

We expect it to be stable enough for existing merchant, but can't officially call it one, until we have several brave pilot merchants to go LIVE with it.

It will be published to NPM this week, so you can give it a go.

@StefanWallin
Copy link
Contributor

So after two long days (involving RN 0.73-upgrade with kotlin-migration repercussions) I'm finally at a stage to try this out.

I have managed to narrow down this to happen in the correct moment on the right platform, might have som false positives still, but when I do the AdyenAction.handle(paymentAction) fails and crashes the android app. I might be missing something here.

const onAppStateChange = useCallback(
    (appState: AppStateStatus) => {
      const storedpaymentData = Storage.loadString(TEMP_PAYMENT_DATA_KEY)

      const active = appState === 'active'
      const midProcess = status === 'awaiting3DSecure' && storedpaymentData
      const android = Platform.OS === 'android'

      if (active && midProcess && android) {
        const paymentAction: PaymentAction = JSON.parse(storedpaymentData)
        AdyenAction.handle(paymentAction, adyenConfiguration)
      }
    },
    [status]
  )

The contents of paymentAction is the same that I in my onSubmit-handler in the normal case use to call nativeComponent.handle(paymentAction) with. It's contents look like this:

{
  "paymentData": "Ab0...",
  "paymentMethodType": "scheme",
  "authorisationToken": "Ab0...",
  "subtype": "fingerprint",
  "token": "eyJ...",
  "type": "threeDS2"
}

Am I missing some detail on how you think this could end up working for resuming a 3DS challenge session?

@StefanWallin
Copy link
Contributor

Missed the StackTrace:

E  FATAL EXCEPTION: main
	Process: se.myapp.app, PID: 4266
	android.view.InflateException: Binary XML file line #53 in se.myapp.app:layout/view_payment_in_progress: Binary XML file line #53 in se.myapp.app:layout/view_payment_in_progress: Error inflating class <unknown>
		Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@18f1660, Dispatchers.Main.immediate]
	Caused by: android.view.InflateException: Binary XML file line #53 in se.myapp.app:layout/view_payment_in_progress: Error inflating class <unknown>
	Caused by: java.lang.reflect.InvocationTargetException
		at java.lang.reflect.Constructor.newInstance0(Native Method)
		at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
		at android.view.LayoutInflater.createView(LayoutInflater.java:852)
		at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
		at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
		at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
		at android.view.LayoutInflater.inflate(LayoutInflater.java:654)
		at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
		at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
		at com.adyen.checkout.ui.core.databinding.ViewPaymentInProgressBinding.inflate(ViewPaymentInProgressBinding.java:58)
		at com.adyen.checkout.ui.core.internal.ui.view.PaymentInProgressView.<init>(PaymentInProgressView.kt:39)
		at com.adyen.checkout.ui.core.internal.ui.view.PaymentInProgressView.<init>(PaymentInProgressView.kt:27)
		at com.adyen.checkout.adyen3ds2.internal.ui.Adyen3DS2ViewProvider.getView(Adyen3DS2ViewProvider.kt:23)
		at com.adyen.checkout.ui.core.AdyenComponentView.loadView(AdyenComponentView.kt:121)
		at com.adyen.checkout.ui.core.AdyenComponentView.access$loadView(AdyenComponentView.kt:48)
		at com.adyen.checkout.ui.core.AdyenComponentView$attach$1.invokeSuspend(AdyenComponentView.kt:104)
		at com.adyen.checkout.ui.core.AdyenComponentView$attach$1.invoke(Unknown Source:8)
		at com.adyen.checkout.ui.core.AdyenComponentView$attach$1.invoke(Unknown Source:4)
		at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:223)
		at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:396)
		at kotlinx.coroutines.flow.StateFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
		at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
		at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
		at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:68)
		at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:373)
		at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
		at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
		at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
		at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
		at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
		at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
		at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
		at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
		at kotlinx.coroutines.flow.FlowKt__CollectKt.launchIn(Collect.kt:49)
		at kotlinx.coroutines.flow.FlowKt.launchIn(Unknown Source:1)
		at com.adyen.checkout.action.core.internal.ui.DefaultGenericActionDelegate.observeViewFlow(DefaultGenericActionDelegate.kt:152)
		at com.adyen.checkout.action.core.internal.ui.DefaultGenericActionDelegate.handleAction(DefaultGenericActionDelegate.kt:122)
		at com.adyen.checkout.action.core.internal.DefaultActionHandlingComponent.handleAction(DefaultActionHandlingComponent.kt:35)
		at com.adyen.checkout.action.core.GenericActionComponent.handleAction(Unknown Source:12)
E  	at com.adyenreactnativesdk.cse.ActionFragment.handle(ActionFragment.kt:64)
		at com.adyenreactnativesdk.cse.ActionFragment.setupComponent(ActionFragment.kt:58)
		at com.adyenreactnativesdk.cse.ActionFragment.onStart(ActionFragment.kt:40)
		at androidx.fragment.app.Fragment.performStart(Fragment.java:3187)
		at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:628)
		at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:290)
		at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943)
		at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1845)
		at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782)
		at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:565)
		at android.os.Handler.handleCallback(Handler.java:938)
		at android.os.Handler.dispatchMessage(Handler.java:99)
		at android.os.Looper.loop(Looper.java:223)
		at android.app.ActivityThread.main(ActivityThread.java:7656)
		at java.lang.reflect.Method.invoke(Native Method)
		at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
		at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
	Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
		at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:247)
		at com.google.android.material.internal.ThemeEnforcement.checkMaterialTheme(ThemeEnforcement.java:216)
		at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:144)
		at com.google.android.material.internal.ThemeEnforcement.obtainStyledAttributes(ThemeEnforcement.java:76)
		at com.google.android.material.button.MaterialButton.<init>(MaterialButton.java:234)
		at com.google.android.material.button.MaterialButton.<init>(MaterialButton.java:225)
		... 56 more

@StefanWallin
Copy link
Contributor

Okay, I solved this style issue with changing the parent of the style my android-app uses, like this:

<resources>
    <!-- Base application theme. -->
-    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
+    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>
</resources>

Now, when I try again, I've changed the code to look like this..

const onAppStateChange = useCallback(
    (appState: AppStateStatus) => {
      const storedpaymentData = Storage.loadString(TEMP_PAYMENT_DATA_KEY)

      const active = appState === 'active'
      const midProcess = status === 'awaiting3DSecure' && storedpaymentData
      const android = Platform.OS === 'android'

      if (active && midProcess && android) {
        const paymentAction: PaymentAction = JSON.parse(storedpaymentData)

        try {
          const data = await AdyenAction.handle(
            paymentAction,
            adyenConfiguration
          )
          console.log('DATA', data)
        } catch (error) {
          console.log('ERROR', JSON.stringify(error, null, 2))
          AdyenAction.hide(false)
        }
      }
    },
    [status]
  )

So this enters the catch-clause which spits the following into the terminal:

ERROR {
  "nativeStackAndroid": [
    {
      "lineNumber": 298,
      "file": "DefaultAdyen3DS2Delegate.kt",
      "methodName": "submitFingerprintAutomatically",
      "class": "com.adyen.checkout.adyen3ds2.internal.ui.DefaultAdyen3DS2Delegate"
    },
    {
      "lineNumber": 67,
      "file": "DefaultAdyen3DS2Delegate.kt",
      "methodName": "access$submitFingerprintAutomatically",
      "class": "com.adyen.checkout.adyen3ds2.internal.ui.DefaultAdyen3DS2Delegate"
    },
    {
      "lineNumber": 15,
      "file": null,
      "methodName": "invokeSuspend",
      "class": "com.adyen.checkout.adyen3ds2.internal.ui.DefaultAdyen3DS2Delegate$submitFingerprintAutomatically$1"
    },
    {
      "lineNumber": 33,
      "file": "ContinuationImpl.kt",
      "methodName": "resumeWith",
      "class": "kotlin.coroutines.jvm.internal.BaseContinuationImpl"
    },
    {
      "lineNumber": 104,
      "file": "DispatchedTask.kt",
      "methodName": "run",
      "class": "kotlinx.coroutines.DispatchedTask"
    },
    {
      "lineNumber": 584,
      "file": "CoroutineScheduler.kt",
      "methodName": "runSafely",
      "class": "kotlinx.coroutines.scheduling.CoroutineScheduler"
    },
    {
      "lineNumber": 793,
      "file": "CoroutineScheduler.kt",
      "methodName": "executeTask",
      "class": "kotlinx.coroutines.scheduling.CoroutineScheduler$Worker"
    },
    {
      "lineNumber": 697,
      "file": "CoroutineScheduler.kt",
      "methodName": "runWorker",
      "class": "kotlinx.coroutines.scheduling.CoroutineScheduler$Worker"
    },
    {
      "lineNumber": 684,
      "file": "CoroutineScheduler.kt",
      "methodName": "run",
      "class": "kotlinx.coroutines.scheduling.CoroutineScheduler$Worker"
    }
  ],
  "userInfo": null,
  "message": "Unable to submit fingerprint",
  "code": "actionError"
}

Other notes

Screen.Recording.2024-02-01.at.06.45.01.mov
  • In the video the component stays open, but I've now realized I can close it with AdyenAction.hide(false).
  • In the video you might notice, and this might be on purpose, but you cannot see the entire card entry form "attached" to the top of the keyboard which it used to do, instead the form field you are on is the only visible one.

One effect of this is that you have to know to hit the blue key on the keyboard to go to the next field instead of clicking the next field.

  • Also, why don't the user get moved to the expiry-field after completing the card number field like they get moved from expiry to cvv-field?

@StefanWallin
Copy link
Contributor

@descorp If it wasn't clear I'm at the end of my understanding here. Is it supposed to be possible to resume a 3DS-challenge in this way?

@descorp
Copy link
Contributor

descorp commented Feb 5, 2024

Hey @StefanWallin

Am I missing some detail on how you think this could end up working for resuming a 3DS challenge session?

Sorry you have to go thought all of this research all by yourself 💚

This approach would perfectly works with redirect action, but for Native 3DS - it is not supported out of the box.
Each 3DS transaction is unique and when you use the previous action - our backend returns an error cause this request was already made.

There was potential workaround on API v66, I am verifying if it is possible to do on modern v69+ versions..


I confirmed that "old way" is possible on any modern API version.
I'll do some tests locally and will get back to you if it turns out to be successful.

@StefanWallin
Copy link
Contributor

How did your testing go?

@descorp
Copy link
Contributor

descorp commented Feb 19, 2024

Hey @StefanWallin

Unfortunately it is not possible. 3DS flow is "one-time" thing by design.
The only 100% solution here is to rely on web-hooks.

@StefanWallin
Copy link
Contributor

@descorp, okay. that's unfortunate but understandable. I guess we might have to keep poking at this from the activity-perspective.

  1. It's unclear to us how web-hooks would help our case out here since the data from the 3DS-verification will not be passed to us. Can you explain in more detail what web-hook we should look at to get this working?
  2. Another thing that could potentially solve this as I undestand, would be to enable adyen-react-native to pass along the configuration parameter configuration.actionComponent.threeDS.requestorAppURL which needs to be a universal link if I understand it correctly. Will track this separately in issue Add support for configuring ThreeDSRequestorAppURL #374

@descorp
Copy link
Contributor

descorp commented Feb 19, 2024

Hey @StefanWallin

  1. Web-hook is an ultimate source of truth about transaction state. Rule of thumb here - always consider the transaction as "pending" until it is concluded by the shopper (happy flow, canceled, component error) or webhook(broken redirect, delays, "icon click" or any other unexpected behavior). This means that your UI should be transparent with shoppers about the current status. It could be helpful to check with the shopper about their experience - whether they completed the payment or not.

  2. requestorAppURL is just an alternative for "Custom URL Scheme" to return to the app - in latest 3DS2 specification only "https" protocol is allowed. It have the same problems, since shopper still can abandon payment flow or redirect can be broken.

@descorp
Copy link
Contributor

descorp commented Feb 19, 2024

The good news is that now we have the ability to setOnRedirectListener on the Native side to notify about shopper being redirected to an external app/browser.

This callback for ReactNative code is in our backlog.

@stuartmcvean
Copy link

Is there any workaround for this? Does this mean that for Android there is no way to successfully make a payment with 3DS2.2 App<>App redirection? So you get redirected from our apps 3DS screen to the authenticator app (banking app) then when they are redirected back to our app with a deeplink, they will be unable to finish the payment?

@descorp
Copy link
Contributor

descorp commented May 27, 2024

@stuartmcvean

On v2.0.0-rc1 we have provided threeDS2.requestorAppUrl configuration that should help with this.
Keep in mind that this feature depend on issuer bank and platform.

We are interested in any feedback you may have on this to improve the flow.

@StefanWallin
Copy link
Contributor

Continuing to try to achieve a smooth flow for our customers, as outlined in the image below.

Webhooks

I've looked at webhooks and none of them seem to be able salvage the fact that the ChallengeResult have been submitted to backend, but additionalDetails callback has not been triggered and won't be so the offer will continue to stay in status Open. If I've overlooked anything here, please inform me :)

setOnRedirectListener

@descorp you stated:

The good news is that now we have the ability to setOnRedirectListener on the Native side to notify about shopper being redirected to an external app/browser.

What's the idea behind that. Can that help in this case?


Background on testing

All of my tests in this post have been carried out on ThreeDS2 version 2.2 with AdyenReactNative on version 2.2.0, and against swedish banks in the Live environment because https://docs.adyen.com/development-resources/testing/3d-secure-2-authentication/ OOB-test cards does not trigger these incompatibilities.

(100% of our swedish customers have a mandated OOB-validation flow with 3rd party which is not merchant, not adyen, not card issuing bank. It's an ID-provider called BankID(BLUE APP BELOW))

305983678-499e6f94-4b30-410e-8161-f673e1a3c0e4

iOS FUTURE-flow and TODAY-flow

Chosen flow depends mostly on bank.

  • With threeDS2.requestorAppUrl set to a scheme-url this works flawlessly on iOS
  • With threeDS2.requestorAppUrl set to a Universal Link this works flawlessly on iOS

Android FUTURE-flow from image above:

With threeDS2.requestorAppUrl set to the result of AdyenDropIn.getReturnURL() this works almost like a charm on Android with banks that support redirection correctly (sometimes it just errors though) if we also set taskAffinity on .MainActivity in AndroidManifest.xml as such:

  ...
  android:launchMode="singleTask"
  android:taskAffinity=""
  ...

Without taskAffinity:

We get redirect errors for banks supporting the redirect flow.

error attribute in onError callback:

{
  "errorCode": "unknown",
  "description": "[Ljava.lang.StackTraceElement;@9517ba6",
  "message": "Error parsing redirect result, could not find any query parameters"
}

LogCat Stacktrace

mWNT: t=0xb3379b20 mBlastBufferQueue=0xb2b49100 fn= 3 mRenderHdrSdrRatio=1.0 caller= android.view.ViewRootImpl$8.onFrameDraw:13841 android.view.ThreadedRenderer$1.onFrameDraw:792 <bottom of call stack> 

With taskAffinity = ""

  • With threeDS2.requestorAppUrl set to a valid Android App Link the user lands in the Browser "Samsung Internet" after Succeeding the ThreeDs2 ChallengeResponse with a button to open the app(see image below).

If that button is pressed: the app is launched to the same RN-screen but the dropin-dialog is gone. I'm guessing that the adyen-react-native code is not setup to trigger on intent opening from Android App Link.

If not clicking the button, but trying to navigate back manually:
Now, a couple of different things arise. The merchant app now have multiple tasks active (.MainActivity & some sort of Adyen ThreeDS2 challenge activity).

If opening Adyen ThreeDS2 challenge activity from app switcher, hitting "I've verified elsewhere." that activity will "close" but still reside in launcher as blank activity and the user has again the choice to open from launcher or use task switcher.

If opening from launcher, same issue as stated in first post in this issue.

  • If using app switcher (again! sic!) and choosing the correct(sic!) task(.MainActivity) from merchant app, there is a possibility that the payment method has been added.
  • It does not work launching app from launcher to switch back to the merchant app(step 5), (this bug)

Android TODAY-flow** from image above

However, for banks that do not support redirection but require OOB-validation-app to merchant-app manual navigation we still have the issue that leaving the merchant app with -component in "start"-mode and returning from OOB-validation

With taskAffinity = ""

When in step 5, manually navigating back through app switcher and hitting "I've verified elsewhere." that activity will "close" but still reside in launcher as blank activity and the user has again the choice to open from launcher or use task switcher.

  • If using app switcher (again! sic!) and choosing the correct(sic!) task(.MainActivity) from merchant app, there is a possibility that the payment method has been added.
  • It does not work launching app from launcher to switch back to the merchant app(step 5), (this bug)

Without taskAffinity:

  • It works fine with using the appswitcher to switch back to the merchant app (step 5)
  • It does not work launching app from launcher to switch back to the merchant app(step 5), (this bug)

Screenshots

Dual activity App Switcher Android App Link (autoverify) trapped by samsung internet
Not normal for our app, in all other cases our app is single activity (android:launchMode="singleTask" as stated in AndroidManifest.xml) Note the small App-icon top right next to the refresh circular arrow.
IMG_4489 Screenshot_20241011_143429_Samsung Internet

Suggestion

It would be great if we could as merchants to be able to call a resume-function resume('dropin') similar to the start-function start('dropin') or your library try to resume by yourself when the adyen-activity have been canceled mid-challenge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

6 participants