Closed soarb closed 1 year ago
Hey @soarb thanks for this. I'll follow up and will report back once I have more information.
Hey @sshropshire ... have you managed to find out any more information about this issue?
I'm being asked to release a new version of our App but am a little concerned that this is going to start affecting an increasing number of Android users (if their card is stored in their Wallet). I can't think of a work around as it all hinges on this isNetworkTokenized fn call :(
So far, this is all I can determine @sshropshire.
When constructing an instance of GooglePayCardNonce from the json returned by the Google Payment sheet, the code attempts to grab the token payload i.e.,
JSONObject tokenPayload = new JSONObject(inputJson
.getJSONObject("paymentMethodData")
.getJSONObject("tokenizationData")
.getString("token"));
According to Google's docs this is not guaranteed to be present?
I don't know enough about the whole Google Payments API but this can either be a PAYMENT_GATEWAY or a DIRECT generated payment method token.
We've managed to capture and log the token in our Sandbox environment which always returns false for isNetworkTokenized.
We can only conclude that the property is either present for this card we're using and always false, or that it's not present at all.
Is there some interaction between yourselves and Google when the user has selected a payment method from the Google Payment Sheet?
We'd love to try and supply more information, but of course we can't run a debug build in a Production environment as Google require a signed APK, therefore we cannot inspect the contents of this token with the payment method added via the Google Wallet (which should return true) vs the same payment method added via the Google Pay website.
Cheers
Benj
We've managed to capture and log the token in our Sandbox environment which always returns false for isNetworkTokenized.
Hi @soarb - have you been seeing this issue in production at all, or only sandbox?
Hi @scannillo.
It's in Production which is why we're holding back from releasing the Android version of our App. We have three customers with valid cards. All are registered in the Google Wallet app and unfortunately isNetworkTokenized always returns false rather than true, which means we try and apply 3DS2 which fails as described in the Braintree documentation.
Hi @sshropshire, @scannillo. Having edited my previous comment we're finding ourselves in a very inconsistent situation with Google Pay where cards are registered via the Wallet.
We did spot some instances where isNetworkTokenized was correctly returning true and I need to come clean as I wasn't handling this case correctly in our App. This is in the process of being rectified so in these cases we won't apply 3DS verification.
However, today again, with the same payment method added to the Wallet for some reason we cannot get anything other than false from the isNetworkTokenized property.
We're going slightly crazy here trying to come up with a fixed process which demonstrates both isNetworkTokenized false and isNetworkTokenized true - which we thought we had, now we're not so sure and cannot understand what's changed.
We are in the process of putting some logs together for you which include timestamps, the payment method token/nonce and more importantly the isNetworkTokenized value along with how the payment method is registered with Google Pay.
We're hoping this may shed some more light as to what might be going on!
Thanks for your continued support,
Benj
Hi @soarb - it looks like you've already reached out to Braintree Support who we are working with internally.
Yes - getting us those values would help us immensely. Timestamps, payment method nonce strings, and associated isNetworkTokenized
values will help our team that owns the underlying API that the SDK bubbles up investigate the issue.
👋 @soarb totally understand how frustrating it can be to pinpoint the root of an issue like this. For a little background, our API determines isNetworkTokenized
status from Google, which is why Support is asking for more specifics.
I'm going to close this issue because Support is working with you directly and are best equipped to help investigate API issues. The Drop-In is simply operating off of the status we receive from our API, so there's no real action to be taken by our team (though please be assured we are in active conversations with our colleagues in Support and our API engineering teams to assist where needed).
However, there's one other thing that's sticking out to me in my troubleshooting brain. You mention in the original issue:
In all cases logging the result of the isNetworkTokenzied() method on the GooglePayCardNonce instance returned to us after calling GooglePayClient's requestPayment method is always false which means we always request 3D secure authentication.
I know this is going to sound crazy, but I've seen it before where folks think they're logging a value and somehow the logging part of their code is getting it wrong. To rule this out as a potential cause, you may want to also call PaymentMethodNonce:Find on your server-side and check the is_network_tokenized
status as well just as a clarity check for this investigation. I know that can be a bit of work on your side, so please take this with a grain of salt. I'm just trying to think of all possible roots for this issue since we haven't received similar reports from other merchants. If you do decide to try this route for your investigation, go ahead and let Support know; don't feel obligated to update this issue. Thanks!
@scannillo, @hollabaq86 - thank you both for your continued support - I'll submit those logs via Braintree Support now and I hope it might help work out what's happening! :) (I'll also see if we can get some time to double check the network_tokenized status on the server too)
Ok, @sshropshire, @scannillo and @hollabaq86 I'm hoping we can re-open this issue as I can re-create it 100% of the time on our app.
tl;dr
If the user switches to Google Pay via the drop-in, then the dropInResult we get back has a nonce ready to charge the customer with, BUT isNetworkTokenized is false therefore the payment fails as we apply additional 3DS validation.
If we open the Google Payment sheet directly using the GooglePayClient and set a listener, the PaymentMethodNonce we receive in our listener's onGooglePaySuccess method is correct i.e., isNetworkTokenized is true therefore we do NOT apply any 3DS checks.
I just want to stress that this is with my mastercard on production and I can recreate this 100% of the time.
If the Google Payment sheet is triggered by the drop-in, isNetworkTokenized is false which is incorrect.
If the Google Payment sheet is triggered by our App (using the same GooglePayClient and registering a listener) the isNetworkTokenized result is true which is correct so somewhere this information appears to be dropped?
Cheers
Benj
@soarb thanks for catching this! It turns out isNetworkTokenized
was missing from the Parcelable
implementation. The property itself was introduced long after the module was created, and it being a boolean
property allows it to slip through the cracks as a default false
value when parceled through an Activity
result.
After reading your description of the behavior that became clear. We are also in the process of migrating to Kotlin. In the future, we'll be moving to Parcelize to prevent issues like this from happening.
@soarb this should now be resolved in 6.9.0!
Brilliant! Thanks @sshropshire. I'll update my wrapper library and get this into our App asap.
Integration Details (please complete the following information):
Describe the bug We have identified an issue with a number of customers attempting to pay by Google Pay, where the card payment method has been added via the Google Wallet app.
According to the docs, we should be able to check whether the card has been network tokenised or not. This helps us to avoid any errors when incorrectly attempting to use 3DS with a network tokenised card.
In all cases logging the result of the isNetworkTokenzied() method on the GooglePayCardNonce instance returned to us after calling GooglePayClient's requestPayment method is always false which means we always request 3D secure authentication.
This of course results in the following error:-
"cannot 3d secure a non-credit card payment instrument"
If the exact same payment method is registered via https://pay.google.com/gp/w/home/paymentmethods i.e., via the user's Google account, not via the Wallet App on the device, then payments succeed.
To Reproduce
This for me on my S10 was not reproducible. However for 3 of our customers we managed to sit down with, removing the payment via the Google Pay Wallet App and registering it via https://pay.google.com/gp/w/home/paymentmethods worked. Removing the payment method and re-registering it via the Google Wallet app always failed because isNetworkTokenized() incorrectly returns false and we apply 3DS to the transaction.
Expected behavior
isNetworkTokenized returns true for network tokenized cards.