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

[NEED ASSIST] Testing the TWINT native integration on iOS #1783

Open
elitalon opened this issue Aug 16, 2024 · 15 comments
Open

[NEED ASSIST] Testing the TWINT native integration on iOS #1783

elitalon opened this issue Aug 16, 2024 · 15 comments

Comments

@elitalon
Copy link

Describe the challenge
I'm trying to test the native integration of TWINT on an iOS app, following the steps in AdyentTwint documentation and targeting Adyen's Test environment.

I have installed TWINT's Configurator app, with the environment set to INT.

Our app is configured with all 50 twint-issuerN schemes and we are launching the drop-in as follows:

import Adyen
import AdyenDropIn
import AdyenTwint

/* … */

let context = try AdyenContext(
    apiContext: .init(environment: .test, clientKey: <redacted>),
    payment: .init(
        amount: .init(value: 0, currencyCode: "CHF", localeIdentifier: nil),
        countryCode: "CH"
    )
)

let configuration = DropInComponent.Configuration(style: /* … */)
configuration.card.showsStorePaymentMethodField = false
configuration.actionComponent.twint = .init(callbackAppScheme: <redacted>)

let dropIn = DropInComponent(
    paymentMethods: paymentMethods, // This is a `PaymentMethods` instance from Adyen SDK
    context: context,
    configuration: configuration
)
dropIn.delegate = self
presentingViewController.present(dropIn.viewController, animated: true)

The problem is that after tapping on the Twint option in the drop-in, I don't think we get the native TWINT integration, but rather a webshop interface:

(1) Selection of TWINT (2) Web interface
IMG_6085 step_02

Is there anything else that needs to be configured?

Documentation update (optional)
The guidelines in AdyentTwint documentation do not mention anything about the need of using TWINT's Configurator app to test the integration during development.

Screenshots
Added above as part of the description of the issue.

@elitalon elitalon changed the title [NEED ASSIST] [NEED ASSIST] Testing the TWINT native integration on iOS Aug 16, 2024
@goergisn
Copy link
Contributor

Hi @elitalon thanks for opening that separate issue.
From what I see the code looks good. You can also double check with the implementation of the Demo App.
I will check internally if there is any additional configuration needed and keep you posted.

@elitalon
Copy link
Author

elitalon commented Sep 11, 2024

@goergisn Do you have any news on this? I checked the demo app and I don't see that we are doing anything significantly different.

I noticed that the documentation says that

After pressing the button on the component, TwintComponent makes a /payments call with subtype: sdk and trigger the flow with retrieving the code through ActionComponent

But if I inspect the requests made by the app, I don't see any trace of that subtype: sdk. Do we need to enable this explicitly?

@goergisn
Copy link
Contributor

Hi @elitalon,

I assume you are using the SPM integration with Advanced Flow (Not the Session integration) right?
If AdyenTwint is available (Which it seems based on your import statement) it should automatically use the "native" integration.
Do you use any 3rd party build tool that might "mess" with included frameworks?


To double check an assumption, could you please add a breakpoint in following places of the Checkout SDK?

The AdyenTwint module contains the TwintSDK and thus should go the route of decoding as a TwintPaymentMethod instead of an AnyPaymentMethod and further build a TwintComponent that automatically sends the subtype: sdk.

Something must go wrong in one of the places.

Screenshot 2024-09-12 at 13 05 55 Screenshot 2024-09-12 at 13 08 06

@nauaros
Copy link
Contributor

nauaros commented Sep 12, 2024

@elitalon

In addition to what @goergisn asked, can you clarify if:

  1. You're using sessions or advanced integration?
  2. Are you referencing TEST or LIVE environment (on Adyen)?

@elitalon
Copy link
Author

@goergisn @nauaros I finally got a chance to look at this in more detail, apologies for the delay in my answer.

We're indeed using the advanced integration with the TEST environment.

As for the breakpoints, I set them in the places indicated and I've seen the following behaviour.

In TwintPaymentMethodDecoder (see the screenshot below), only decode(from:isStored:) -> AnyPaymentMethod is called in the "TWINT branch".

TwintPaymentMethodDecoder

AnyPaymentMethodDecoder

The other method is never called, but I'm not sure that's the expected behaviour.

If I remove the AdyenTwint framework from the project, the second method is called again, just not on the TWINT branch (and thus returning nil).

In ComponentManager (see also the screenshot below), only build(paymentMethod:) -> PaymentComponent? is also called in the "TWINT branch".

ComponentManager

ComponentManager

As far as I know, we don't have any other third-party build tool interfering with frameworks in build phases.

What we have though is a post-action build step in the target's scheme to account for a known bug in Xcode:

# https://developer.apple.com/documentation/xcode-release-notes/xcode-12_4-release-notes FB8761306
rm -rf "${TARGET_BUILD_DIR}/${TARGET_NAME}.app"/PlugIns/*.framework

I hope that gives you a hint about what could be wrong.

Thanks!

@elitalon
Copy link
Author

Something I forgot in my previous comment is that these messages also appear in the logs of our app:

objc[4245]: Class TWAppLinkDataValidator is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a61e0) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e060). One of the two will be used. Which one is undefined.
objc[4245]: Class TWAppLinkData is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a6230) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e0b0). One of the two will be used. Which one is undefined.
objc[4245]: Class TWAppChooserNetworking is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a6258) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e0d8). One of the two will be used. Which one is undefined.
objc[4245]: Class TWInstalledAppFetcher is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a62a8) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e128). One of the two will be used. Which one is undefined.
objc[4245]: Class TWError is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a6320) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e1a0). One of the two will be used. Which one is undefined.
objc[4245]: Class TWAppConfiguration is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a6348) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e1c8). One of the two will be used. Which one is undefined.
objc[4245]: Class Twint is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a63c0) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e240). One of the two will be used. Which one is undefined.
objc[4245]: Class TWAppChooserController is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a6410) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e290). One of the two will be used. Which one is undefined.
objc[4245]: Class TWAppLinkDataTransformer is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a6460) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e2e0). One of the two will be used. Which one is undefined.
objc[4245]: Class TWAppLinkToTwintAdapter is implemented in both /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/Datatrans.framework/Datatrans (0x1067a64b0) and /private/var/containers/Bundle/Application/B99E38A7-493B-4A17-BD3D-C002C9FA3A6F/Fairtiq.app/Frameworks/TwintSDK.framework/TwintSDK (0x10517e330). One of the two will be used. Which one is undefined.

Our app also integrates Datatrans' SDK, which includes TwintSDK. However, although not desirable, this shouldn't be a problem because the OS will pick one.

I'm saying this based in our current experience with other frameworks that have worked fine so far. But there's maybe something particular about TwintSDK that invalidates this assumption.

@goergisn
Copy link
Contributor

Hi @elitalon this already helps a lot 👍
We can now confirm that the SDK detects the TwintSDK and goes the right route.

Now we have to make sure that you are sending the correct data to your (proxy) backend so it can send the correct data to the /payments endpoint. You mentioned that you don't see any request from the app containing a subtype: sdk so it might be that there is something off in the way you construct the data sent to the backend.
Is there a way you can provide the request/information you're sending?
(The TwintComponent creates a PaymentComponentData object containing the TwintDetails this object has to be provided as is)

@elitalon
Copy link
Author

Hey @goergisn, I verified the request sent by the app and the subtype field is now being sent to our proxy backend. I wonder what has changed since I open this issue (a month ago 🙈).

In any case we still see the web based UI, not the native one. So we are going to check now how our proxy handles this request. Chances are, Java serialisation is dropping this subtype field during deserialisation because it's not explicitly declared.

I'll keep you posted, thanks a lot for the support so far.

@elitalon
Copy link
Author

@goergisn It looks like the request ends up being deserialised into a StoredPaymentMethodDetails object in our proxy backend implementation. But as far as I can see, this class doesn't contain any subtype member.

Is there anything additional we have to configure so that the correct type (or subtype) gets used?

For reference, we are currently using the version 28.2.0 of the Java API library.

@goergisn
Copy link
Contributor

Hi @elitalon it looks like this is a limitation of the Java API Library do you mind creating an issue there? I will also check with our backend developers to get some more information.

@elitalon
Copy link
Author

@goergisn There you go: Adyen/adyen-java-api-library#1360

@goergisn
Copy link
Contributor

Thank you for reporting and sorry for the inconvenience.
I'll leave the ticket open for visibility as well for now.

@seanlabastille
Copy link

seanlabastille commented Oct 10, 2024

@goergisn I am sorry for hijacking this thread but we have recently become aware of an issue with using the TWINT SDK if the app was built using Xcode 16 (links to the TWINT apps can't be opened).
A fix is expected within the next days, but this means you will probably need to ship an update of your integration before we can fully resolve this.

@nauaros
Copy link
Contributor

nauaros commented Oct 10, 2024

Hi @seanlabastille - Are you building with iOS 18?

@seanlabastille
Copy link

@nauaros We are building with Xcode 16 so the default SDK is iOS 18. A fix from TWINT should be available now.

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

No branches or pull requests

4 participants