-
Notifications
You must be signed in to change notification settings - Fork 33
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
Comments
Hey @Cattari Thanks for reaching out! We are aware of this unfortunate behavior. For now, the only advice we have - is always to be prepared for the worst. 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. |
hi @pinpong if universal/deep links are used, they start a new instance (a copy) of the app, and we didn't manage to avoid that. |
We are facing the same issue. Thanks |
How about if
I don't see how Webhooks can solve the fact that for a 3DS OOB challenge, |
You have posted previously:
in v2 BETA it is possible to call |
@descorp Would you consider v2 BETA production ready yet? |
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) |
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. |
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 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 {
"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? |
Missed the StackTrace:
|
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 notesScreen.Recording.2024-02-01.at.06.45.01.mov
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.
|
@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? |
Hey @StefanWallin
Sorry you have to go thought all of this research all by yourself 💚 This approach would perfectly works with 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. |
How did your testing go? |
Hey @StefanWallin Unfortunately it is not possible. 3DS flow is "one-time" thing by design. |
@descorp, okay. that's unfortunate but understandable. I guess we might have to keep poking at this from the activity-perspective.
|
Hey @StefanWallin
|
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. |
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? |
On We are interested in any feedback you may have on this to improve the flow. |
Continuing to try to achieve a smooth flow for our customers, as outlined in the image below. WebhooksI'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:
What's the idea behind that. Can that help in this case? Background on testingAll 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)) iOS FUTURE-flow and TODAY-flowChosen flow depends mostly on bank.
Android FUTURE-flow from image above:With
Without taskAffinity:We get redirect errors for banks supporting the redirect flow.
{
"errorCode": "unknown",
"description": "[Ljava.lang.StackTraceElement;@9517ba6",
"message": "Error parsing redirect result, could not find any query parameters"
} LogCat Stacktrace
With taskAffinity = ""
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: 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.
Android TODAY-flow** from image aboveHowever, 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.
Without taskAffinity:
ScreenshotsSuggestionIt would be great if we could as merchants to be able to call a resume-function |
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:
Expected behavior
5. User sees the DropIn.
Actual behavior
5. User sees the MainActivity, DropIn is killed.
Smartphone (please complete the following information):
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.
The text was updated successfully, but these errors were encountered: