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

Swish payment method always triggers an error on mobile #1712

Closed
rvdsteege opened this issue Aug 26, 2022 · 10 comments
Closed

Swish payment method always triggers an error on mobile #1712

rvdsteege opened this issue Aug 26, 2022 · 10 comments

Comments

@rvdsteege
Copy link

rvdsteege commented Aug 26, 2022

Describe the bug
When an error occurs in drop-in, our Pronamic Pay plugin for WordPress redirects to a failed payment page. The payment status then gets updated accordingly and the error is logged.

For the Swish payment method, this seems to result in an unreasonable amount of failed payments (60% according to client) with the following error message:

swish App was not found

This error seems to be triggered by redirectToApp() of the QR loader:

public redirectToApp = (url, fallback = () => {}) => {
setTimeout(() => {
// Redirect to the APP failed
this.props.onError(new AdyenCheckoutError('ERROR', `${this.props.type} App was not found`));
fallback();
}, 25);
window.location.assign(url);
};

We're thinking the really short timeout of 25 ms might be the culprit. In a test similar to redirectToApp(), it seems that even the simplest redirect will trigger the error, even though the redirect works perfectly fine:

<script>
setTimeout( function() {
	console.log( "Unable to redirect" );
}, 25 );

window.location.assign( 'https://www.adyen.com/' );
</script>

In the case of Swish, the URL being redirected to uses the custom protocol swish:// to open their app. This means that the browser might also asks for confirmation before opening the Swish app, which will take a little longer to confirm. It is impossible to confirm that this fast.

To Reproduce
Steps to reproduce the behavior:

  1. on mobile, select Swish in drop-in
  2. click the button to continue payment
  3. the onError method of the checkout configuration is called with a AdyenCheckoutError

Expected behavior
The drop-in should not trigger an error if the Swish app can be opened. Also, if we would want to leave the QR code shown on mobile when the app is not installed (for example to use an other device to scan the QR code), there is no way to distinguish between a real error (like when the payment expires after 3 minutes in https://github.com/Adyen/adyen-web/blob/v5.23.0/packages/lib/src/components/internal/QRLoader/QRLoader.tsx#L94-L98) and the case that the app could not be opened. If the PayPal popup is cancelled for example, we do not redirect to our failed payment page:

Smartphone (please complete the following information):
I have tested on at least the following device, but assume it affects others too.

  • Device: iPhone
  • OS: iOS
  • Browser: Safari
  • Version: 15.6
@rvdsteege
Copy link
Author

@sponglord have you been able to check this issue?

@remcotolsma
Copy link

I alerted Adyen to this issue at https://www.adyen.help/hc/en-us/requests/new?ticket_form_id=360000690879.

Hello Adyen team,

Can someone look at #1712 and comment on that? Thanks in advance.

Remco Tolsma
Pronamic


www adyen help_hc_en-us_requests_new_ticket_form_id=360000690879


Your request is logged with Ticket ID #3308212 and will be reviewed by our support staff. We typically respond to tickets within 24 business hours, however one of our agents will try to get back to you as soon as possible.

Hopefully we can send our joint customer an update on this issue soon.

@ribeiroguilherme
Copy link
Contributor

Hey @rvdsteege ,

Thanks for the detailed description. We agree that indeed 25 ms seems too little for the mobile device to properly open the app, and unfortunately there is no exact science about the duration of the timeout to wait for the app to kicks in.

I created a fix increasing the timeout to 1 second, which should hopefully cover all the cases for different devices/operational systems (Android/iOS). This fix should be released early next week.

I will leave this Github issue open for now, so we can follow up on it and you can let us know if that fixed your problem!
Cheers

@rvdsteege
Copy link
Author

Thank you for the update, @ribeiroguilherme. However, I don't think slightly increasing the timeout in #1755 will make much difference: it will still trigger the checkout error when it shouldn't.

I made a quick screen recording to illustrate the issue. For demonstration purposes, the page in the video turns red when the error would normally be triggered (after 1s). Note that the error gets triggered even though I'm actually opening the Swish app — as requested by drop-in.

swish-error-triggered.mov

@remcotolsma
Copy link

Based on https://stackoverflow.com/questions/24779312/simplest-cross-browser-check-if-protocol-handler-is-registered you may also have to conclude that there is no reliable way to determine whether an app could be found / opened.

Note that as at February 2020, there doesn't seem to be a working way to do this. Only considering Chrome, neither the solution from @kororo or @habsq work at the moment. The reason is that what we're trying to achieve by checking if a URL protocol handler exists is actually considered as being a security risk by some people.

So my advice is to not persevere in trying to get this to work.

https://www.fortinet.com/blog/threat-research/leaking-browser-url-protocol-handlers

It therefore does not seem correct to me to trigger this error after a certain time:

public redirectToApp = (url, fallback = () => {}) => {
setTimeout(() => {
// Redirect to the APP failed
this.props.onError(new AdyenCheckoutError('ERROR', `${this.props.type} App was not found`));
fallback();
}, 25);
window.location.assign(url);
};

I don't think you can ever know for sure if the app was indeed not found. This whole implementation needs to be different/better?

@ribeiroguilherme
Copy link
Contributor

Thanks for the input guys.

I spent some time investigating this issue and indeed seems like we can't know for sure if the app is available or not in the device. We need to rethink a bit about this current implementation, but it seems that triggering onError isn't ideal for this use case. I will align internally with the team and we will discuss how to move forward.

In the meantime, I suggest to ignore the error on yours onError callback implementation if the error message is swish App was not found - that should do the trick for now. I will keep this thread updated with the progress of this problem.

@DavidVujic
Copy link
Contributor

Hey all 👋

We also experience the Swish issues, and I have made a Pull Request that might solve it. Got any feedback? #1764

@DavidVujic
Copy link
Contributor

We've just deployed our app using the latest version and I can confirm that the Swish-trigger-error problem is solved 😄

@ribeiroguilherme
Copy link
Contributor

Thanks for raising this issue guys. The fix is available on the 5.27.0 .

@rvdsteege
Copy link
Author

Thank you @DavidVujic and @ribeiroguilherme — we'll update the Adyen integration in our plugin!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants