iZettle / sdk-android

Add card payments from Zettle to your own app
https://developer.zettle.com/docs/android-sdk
24 stars 20 forks source link

How to close CardPaymentActivity after payment fails? #26

Closed pynting closed 2 years ago

pynting commented 3 years ago

First let me say that I have very limited android development experience, but have successfully used the Kotlin template to make a functioning app that suits my needs.. except for one thing:

When a payment is initiated as in the template and completed successfully, the CardPaymentActivity exits and returns to my MainActivity, however when the payment fails or times out, the CardPaymentActivity stays active until I press the return button on screen/back button on my phone.

How can I close the CardPaymentActivity automatically if the payment fails or gets cancelled, so that I can use the onActivityResult function to relaunch a payment request?

I have tried running a timer in my MainActivity that after 60seconds tries to close the CardPaymentActivity with no success using the following approaches:

CardPaymentActivity().onBackPressed() *app crashes

CardPaymentActivity().finish() *nothing happens

Due to my lack of experience working with Android, I am not really sure if this is the right way to go about it (probably not!).

Hopefully there is an easy solution to this problem.

Thanks

jonarderic74 commented 3 years ago

Hello, personnaly, i use findViewById(com.izettle.payments.android.ui.R.id.payment_failure_dismiss) and callOnClick().

pynting commented 3 years ago

Hi jonarderic74, and thanks a lot for you reply! I was not able to get this to work, I maybe would need a more fleshed out example... When I tried to create a variable that held that view the app crashed... How do you know when that view is visible from the MainActivity?

My crude solution that seems to work, but is not at all fool proof, is to have a postDelayed set at 80 seconds, restarting the payment request with a Intent.FLAG_ACTIVITY_NO_HISTORY, so that it kills off any already existing payment requests. This is a crude solution, and can cause problems if people are slow when typing their pin code for example. For now it is probably ok, everyone has contactless cards in my region, and has gotten well accustomed to using it over the last year or so!

jonarderic74 commented 3 years ago

Hello,

You can not do a FindView on a MainActivity for the intent of zettle. The SDK use another activity for the log and another for the payment. So, you need to get the current activity to do a FindView to activate a button (Imageview for the back or Button for the dissmiss).

Waiting a Listen, Handler, or statepayment from the sdk or better soluce, i do a spy for the current activity in a thread. There is 2 activity : 1) Com.izettle.android.auth.OAuthActivity for the logging 2) Com.izettle.payments.android.ui.payment.CardPaymentActivity for all event to the payment. (After it is a Fragment for all event to the payment, so there is no event for activity change) When the activity is CardPaymentActivity your can request a FindViewById to know the event :

pynting commented 3 years ago

Wow, thanks for the comprehensive answer! I will try to work this into my code. Now it is a fragile thing, but somehow works. But I would definitively like it to be more robust. I wish there was an easier way to do this though through the SDK. Maybe integrate some variable you could add to the payment intent builder to have it return automatically and report what happened. It seems it would be a lot more friendly to developers wanting to make something that relies less on interaction from a user on screen, instead of spying on the current activity. But again perhaps this is the way it is supposed to be done in mobile development?

Anyway, thanks again for being so helpful!

bobzettle commented 2 years ago

Hi, this seems to be a feature request for a headless SDK, one without UI for the app holder, and it's not something we have planned for at the moment.

If a transaction fails for any reason it's essential for the app holder to know that the transaction failed, and also to acknowledge that by pressing ok, or back out of the view. You should not try to do a retry of a failed transaction without the app holder invoking it. The SDK also tries to handle retries in a safe way, so to automatically retry a request after failure is rather error prone and can easily cause double charges or other side effects.

And I strongly recommend to not “spy” on the components of SDK since that is internal code that can change with any update and does not offer any migration-information, head op nor guarantees over different Android operating systems. It’s dangerous to assume a constant behaviour from that.