Open ChielBruin opened 4 months ago
Hey @ChielBruin
Complete the payment using Apple Pay, the drop-in closes
The app is now unresponsive (also the on-success callbacks are never called)
The expected way to dismiss DropIn/Component UI is to call nativeComponent.hide(success)
in successs/failer callback.
Are you using /sessions
or /payments
flow?
Do you receive any callback after click "Pay" in the ApplePay Sheet ?
We use the advanced flow like shown in the README and example app:
class Client {
public async payments(
data: PaymentMethodData,
component: AdyenActionComponent,
_extra: unknown,
): Promise<undefined | PaymentResponse> {
const body = {
...data,
...this.config,
recurringProcessingModel: 'CardOnFile',
channel: Platform.OS === 'ios' ? 'iOS' : 'Android',
};
const response = await this.request(body, '/payments');
if (response.action) {
component.handle(response.action);
return undefined;
} else {
this.handleResponse(response, component);
return response;
}
}
public async paymentsDetails(
data: PaymentDetailsData,
component: AdyenActionComponent,
): Promise<undefined | PaymentResponse> {
const response = await this.request(data, '/payments/details');
this.handleResponse(response, component);
return response;
}
private async request(data: object, path: string): Promise<any> {
const response = await request
.agent()
.post(this.baseUrl + path)
.set('Content-Type', 'application/json')
.send(data)
.ok(() => true);
if (response.status !== Http.OK) {
console.error(response.body);
throw new Error(response.body);
}
return response.body;
}
private handleResponse(
response: PaymentResponse,
component: AdyenActionComponent,
): void {
const success = [
ResultCode.authorised,
ResultCode.received,
ResultCode.pending,
ResultCode.presentToShopper,
].includes(response.resultCode as ResultCode);
component.hide(success);
if (!success) {
throw response;
}
}
}
<AdyenCheckout
config={client.config}
paymentMethods={paymentMethods}
onSubmit={(...args) =>
client
.payments(...args)
.then((response) => {
// Show success/error message
}).catch((ex) => {
// Show error message
})
}
onAdditionalDetails={(...args) =>
client
.paymentsDetails(...args)
.then((response) => {
// Show success/error message
}).catch((ex) => {
// Show error message
})
}
onError={(error, component) => {
component.hide(false);
// Show error message
}}
>
This works perfectly for iDEAL and creditcard payments, but not for Apple Pay.
We do not get any of the callbacks called that I would expect to be called (I even tried the onComplete
that is voucher-only according to the docs). It just logs the error I posted at the top about not being able to replace the drop-in with a different screen.
In your code you are missing component.hide(false);
in case the request
have failed. But overall looks good.
One suggestion - use useCallback. This will make sure only one instance of a function exist.
2024-05-21 13:46:51.077988+0200 X[446:34715] [Presentation] Attempt to present <RCTModalHostViewController: 0x108aa4b30> on <UIViewController: 0x108b17d40> (from <UIViewController: 0x108b17d40>) which is already presenting <Adyen.DropInNavigationController: 0x109957400>.
Seems like something is trying to present RCTModalHostViewController
but do not expect to see our DropInNavigationController
there 🤔
Are you using any 3rd-party libraries for spinner or loading bar during network call, maybe? I wonder if there is something causing re-rendering "behind the scene" 🤔
Could you make a console.log
in here and check if your AdyenCheckout
got re-rendered ?
Thanks for spotting the missing call to hide()
! But sadly that wasn't the issue and converting to using useCallback
didn't solve it either.
I added some logs to see what re-renders are triggered:
AdyenCheckout
both in the cleanup function you linked [3] to and outside of that useEffect
[4] to see if re-renders at allI found that I got message 2 and 4 a couple ms before the "Attempt to present"-error
Regarding other libraries:
Is it possible for you to create a blank app and reproduce this behaviour there?
Hey @ChielBruin, do you still face this issue with the latest releases?
I just tried with version 2.2.0 and still see the same issue
Do you know if other user have gotten ApplePay to work (meaning I probably missed some configuration step somewhere)?
Hey @ChielBruin
It is confirmed to work. At least problem described in this ticket seems unique. Mostly, people struggling with setting up Apple Pay.
I just tried with version 2.2.0 and still see the same issue
I believe this could be a "re-render" issue. Something is mutating state of your "parent" view and it causes recreation of AdyenCheckout
.
Is it possible for you to create a blank app and reproduce this behaviour there? This would allow us to debug and hopfully find a solution.
I've narrowed down the issue to the popups we show upon payment completion using the react-native-modal
library. As soon as I comment out usage of the modal Apple pay works normally, so the issue might be related to this issue with multiple modals.
The weird thing however is that displaying this modal for any other payment method does not result in the app freezing.
ApplePay is a bit unique - it is not a standard UIViewController: it is another window, running in a separate thread, appearing above your screen. With other VC, 3rd party library (we do that, for example) can traverse view hierarchy and present itself on top, but it is not possible with Apple Pay.
Maybe this is what causing this collision on iOS level
Hey @ChielBruin
Any luck?
I have not been able to spend more time on it after I figured out what was causing the issue. It might be worth checking what https://github.com/mkharibalaji/react-native-adyen-payment does differently in their Apple Pay implementation, as we did not see the same issue with multiple modals when using that library. But I am not sure when I can spend time on that due to other priorities
Describe the bug When I complete an Apple Pay payment, the drop-in closes but the app is completely unresponsive. The payment itself did succeed.
To Reproduce Steps to reproduce the behavior:
Expected behavior The app should function normally after completing a payment (which in our case would show a pop-up telling the user that the payment succeeded)
Logs I get the following error messages in my logs:
It seems to fail to overwrite the drop-in in the view stack
Devices:
Additional context The shown behaviour is similar to an issue with integrating Apple Pay that I had in a different library, but they are probably unrelated: https://github.com/mkharibalaji/react-native-adyen-payment/pull/54