braintree_android icon indicating copy to clipboard operation
braintree_android copied to clipboard

UserCanceledException is not thrown when the user exits Chrometab web-flow

Open asos-edgeorge opened this issue 1 year ago • 9 comments

Braintree SDK Version

4.36.0

Environment

Both

Android Version & Device

Google Pixel 3a XL - Android 13

Braintree dependencies

  • com.braintreepayments.api:paypal
  • com.braintreepayments.api:local-payment

Describe the bug

When launching a ChromeTab via a method that initiated the browser switch flow (e.g. LocalPaymentClient#approveLocalPayment(FragmentActivity, LocalPaymentResult)), cancelling the browser flow via the device's back button or ChromeTab's 'X' close button does not provide a callback to the app with the expected UserCanceledException on a provided LocalPaymentListener

We believe that in v3 of the SDKs we were able to get a cancellation callback when the user quit at this stage previously

To reproduce

As described, create a basic payment flow in which a listener (e.g. LocalPaymentListener) is set and the onLocalPaymentFailure method logs when a UserCanceledException is returned

When calling a method that initiated the browser switch flow (e.g. LocalPaymentClient#approveLocalPayment(FragmentActivity, LocalPaymentResult)), manually cancel the browser flow via the device's back button or ChromeTab's 'X' close button

Observe no callback is made to the LocalPaymentListener

Expected behavior

When the user dismisses the browser before the e2e flow is complete, we would expect listeners (e.g. LocalPaymentListener) to receive a UserCanceledException via relevant failure methods such as onLocalPaymentFailure

Screenshots

No response

asos-edgeorge avatar Aug 08 '23 11:08 asos-edgeorge

Hi @asos-edgeorge thanks for using the Braintree SDK for Android. A UserCanceledException should be delivered when the merchant app enters the foreground without completing the Local Payment flow.

If possible, can you set a breakpoint here in LocalPaymentClient.java to see if the listener code is being triggered when you execute the steps to reproduce?

sshropshire avatar Aug 08 '23 14:08 sshropshire

@sshropshire Thanks for your quick response

I am seeing some IDE issues in that the sources do not match the bytecode when setting breakpoints in the LocalPaymentClient code, but I am 99.9% sure I am not seeing the listener code at the line you provided being triggered.

asos-edgeorge avatar Aug 09 '23 08:08 asos-edgeorge

Ok what about here in LocalPaymentLifecycleObserver.java? Also can you share how you're instantiating LocalPaymentClient in your host Fragment / Activity, and in which lifecycle method you do so (e.g. onCreate())?

sshropshire avatar Aug 09 '23 14:08 sshropshire

We aren't using a singleton LocalPaymentClient, but instead construct it when it's needed - so it isn't in a lifecycle method

private inline fun withLocalPaymentClient(token: String, block: LocalPaymentClient.(FragmentActivity) -> Any) {
        val fragment = getPaymentFragment()
        val activity = fragment.requireActivity()
        LocalPaymentClient(fragment, fragment.generateBraintreeClient(token)).run {
            block(activity)
        }
    }

We do see the lifecycle methods reporting correctly for LocalPaymentLifecycleObserver and the break point is hit for each lifecycle method

asos-edgeorge avatar Aug 11 '23 12:08 asos-edgeorge

Got it. From my perspective your integration sounds standard. The listener must also be set on LocalPaymentClient in order to receive the result from a browser switch. I would step through in LocalPaymentLifecycleObserver to see if LocalPaymentClient#onBrowserSwitchResult() is called, and to make sure the client notifies its listener via onLocalPaymentSuccess().

sshropshire avatar Aug 11 '23 15:08 sshropshire

Just to update here - I don't believe the callbacks are called, which I suspect is a bug. Would it be possible to be notified when the user exits the ChromeTab in the browser switch flow in a future release?

asos-edgeorge avatar Aug 24 '23 08:08 asos-edgeorge

@asos-edgeorge unfortunately there isn't a way to get a notification for a close event through the Chrome Custom Tabs API that I'm aware of. Is it possible for your app to instantiate the LocalPaymentClient in onCreate() like we mention in our migration guide?

sshropshire avatar Aug 24 '23 19:08 sshropshire

Hey @asos-edgeorge! We just released a beta for the next major version, v5.

In this version, the interface has been updated to give the additional browser switch flexibility. We'd love for you to try out the new version and see if the new integration pattern resolves the original browser switch cancel issue.

v5 Local Payment Migration Guide: https://github.com/braintree/braintree_android/blob/main/v5_MIGRATION_GUIDE.md#local-payment v5 Release: https://github.com/braintree/braintree_android/releases/tag/5.0.0-beta1

tdchow avatar Jul 24 '24 16:07 tdchow