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

Drop in Android screen loading without any feedback of dropin (Android Only) #565

Open
badredaha opened this issue Jan 1, 2025 · 20 comments
Labels
question Further information is requested

Comments

@badredaha
Copy link

Describe the bug
The Drop-in is started, and I enter the card information. After pressing the “Pay” button in the Drop-in, I observe the following behavior in the debug process:
1. The call to our API is made.
2. I receive the response, either indicating success or an error.
3. Despite receiving the response, the loading view remains visible and does not disappear.

Smartphone (please complete the following information):

  • Device: Emulator Or Device Android SDK 30
@badredaha badredaha added the bug report when a bug report is created label Jan 1, 2025
@descorp
Copy link
Contributor

descorp commented Jan 2, 2025

Hey @badredaha

Could you provide more info:

  1. The call to our API is made.

Is it a \payments call?

  1. I receive the response, either indicating success or an error.

Do you mean network response from your backend API, right?

Despite receiving the response, the loading view remains visible and does not disappear.

How is this behaviour different from iOS?

@descorp descorp added question Further information is requested and removed bug report when a bug report is created labels Jan 2, 2025
@badredaha
Copy link
Author

Hi @descorp
Hope you are good :)
For iOS for now no problem. For Android the spinner loading and when I make the app in background and I return the spinner is hiding :/ and all works good.
What do you think ? Thread UI ? I tried a lot setTimeout nothing work (the only hack work is go background and return forgroud).

@descorp
Copy link
Contributor

descorp commented Jan 7, 2025

@badredaha

How is you onSubmit looks like?
Do you call component.hide(response.result); when you have outcome from backend?

@badredaha
Copy link
Author

@descorp the problem is when the drop-in is shown and I call my API with async to fetch data the return seem to be blocked ! I can see that I get response from my monitoring network (Reactotron or Flipper) but my app don't receive a response!

For iOS it's works good (until now) the same code :/

@badredaha
Copy link
Author

@descorp we are a Little bit blocked

@descorp
Copy link
Contributor

descorp commented Jan 9, 2025

Sorry @badredaha

I am not sure if this is related to the SDK.
Could be unhandled exception or unexpected backend response on your network layer?

Could you determine what line of code is causing "hanging"?

@badredaha
Copy link
Author

Hello @descorp
Mainly is the async function with await ? this why I'm asking if I need add something to manager the UI Thread (For iOS the same code works good)

I found a hack, In Submit I call component.hide(true/or false) and I can manage the response returned from the API no problem! but It's weird and not stable :/

@descorp
Copy link
Contributor

descorp commented Jan 9, 2025

Not sure if I follow you. How is your onSubmit looks like? With and without the "hack" ?

@badredaha
Copy link
Author

badredaha commented Jan 9, 2025

Yes @descorp

AdyenCheckout

<AdyenCheckout
        paymentMethods={adyenPaymentMethodsResponse}
        config={setupAdyenConfiguration(
          getTotalAmountToPay(amount)
          appSettingsReducer.currency
        )}
        onComplete={(data, component) => {
          useCallback(() => {
            handleOnCompleteAdyenPayment(data, component);
          }, []);
        }}
        onError={(error, component) => {
          useCallback(() => {
            handleErrorAdyenPayment(error, component);
          }, []);
        }}
        onSubmit={onSubmitRequest}
      >

onSubmitRequest Method

const onSubmitRequest = useCallback(
    async (data: PaymentMethodData, component: AdyenActionComponent) => {
      const inputsBookingProcess = prepareInputsCheckoutPaymentProcess(
        data,
        component
      );
      try {
        startCheckoutPaymentProcess(inputsBookingProcess, {
          onError: (error) => {
            component.hide(false);
            Logger.error("Error on payment", error);
            showError();
          },
          onSuccess: (data: MbBookingProcessType) => {
            component.hide(true);
            goToPaymentConfirmation(data.confirmationNumber);
          },
          onChallenge: (data) => {
            component.handle(data);
            Logger.error("onChallenge Data", data);
          },
        });
      } catch (error) {
        Logger.error("Unhandled error on payment", error);
        showError();
      }
    },
    []
  );

startCheckoutPaymentProcess

export function startCheckoutPaymentProcess(
  processRequestInput: MbBookingProcessRequestInputType,
  result?: CheckoutPaymentResult
) {
  mutationBookingProcess(processRequestInput)
    .then((response) => {
      const error = handlePaymentErrors(response.error);
      if (error) {
        result?.onError(error);
        return;
      }
      const checkoutPaymentResponse = response.data.bookingProcess;

      if (
        checkoutPaymentResponse?.status === CreateBookingStatus.ActionRequired
      ) {
        result?.onChallenge(checkoutPaymentResponse.adyenAction);
        return;
      }

      if (checkoutPaymentResponse?.status === CreateBookingStatus.Success) {

        const checkoutSuccessResponse = {
          confirmationNumber: checkoutPaymentResponse?.confirmationNumber,
          transactionId: checkoutPaymentResponse?.transactionId,
        };

        result?.onSuccess(checkoutSuccessResponse);
        return;
      }

      result?.onError(getDefaultError());
    })
    .catch((error) => {
      result?.onError(handlePaymentErrors(error) ?? getDefaultError());
    });}

@descorp
Copy link
Contributor

descorp commented Jan 10, 2025

At first glance, the code looks fine.

Is this before "hack" or after?

@badredaha
Copy link
Author

Yes before! the Hack is when the submit call, I force component.hide(true)! and when I get the response from API the call is triggered.

@descorp
Copy link
Contributor

descorp commented Jan 10, 2025

Dismissing component prematurely is a bad idea if you are planing to use any payment method that requires actions (3DS2, redirects etc.)

Just to clarify:

Can you provide a logger inside mutationBookingProcess(processRequestInput) and check if your code go inside .then((response) => { ... } or .catch((error) => { ... } ?

@badredaha
Copy link
Author

The is the issue ... its not called! like the Adyen Thread UI block !

@badredaha
Copy link
Author

Hello @descorp,
Hope all good.
any news ?

@descorp
Copy link
Contributor

descorp commented Jan 13, 2025

Hey @badredaha

Have you checked inside of mutationBookingProcess ? What line there is the last one to be executed?

@badredaha
Copy link
Author

Hey @descorp
Its block in this line ( async function mutation)! The same code work good in iOS!
This why I'm asking maybe something to add:

  • Coroutines/Thread Kotlin/Java ?
  • Manifest? mayeb android:launchMode="singleTop" or android:launchMode="singleTask"

@descorp
Copy link
Contributor

descorp commented Jan 14, 2025

Hey @badredaha

What version of Adyen React Native you are using?


Its block in this line ( async function mutation)! The same code work good in iOS!

Despite receiving the response, the loading view remains visible and does not disappear.

but my app don't receive a response!

I am a bit confused which one is it.
If network request is made, then either blocking happens somewhere inside of mutationBookingProcess method, or it throws exception.

Looking at your code I have noticed that catch block is not calling component.hide("false")

     catch (error) {
        Logger.error("Unhandled error on payment", error);
        showError();
     }

Could that be a reason?

@badredaha
Copy link
Author

badredaha commented Jan 14, 2025

Hi @descorp

We use "@adyen/react-native": "^2.5.0"

Looking at your code I have noticed that catch block is not calling component.hide("false")

No change :/

@descorp
Copy link
Contributor

descorp commented Jan 14, 2025

hm..

Coroutines/Thread Kotlin/Java ?

It could be possible, but we need a way to reproduce this behavior. Could you create a blank app that we can debug?

Please send it to [email protected] to avoid sharing any sensitive information. Don't forget to mention this issue in your email.

Additionally, it would be helpful if you could include a recording of your app along with the logs from Android Studio and Metro.

@badredaha
Copy link
Author

Yes, I will do this and get you notified. Best regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants