braintree / braintree-android-drop-in

Braintree Drop-In SDK for Android
https://developers.braintreepayments.com/guides/drop-in/android/v2
MIT License
124 stars 79 forks source link

Credit Card that should fail is not failling #71

Closed r9software closed 5 years ago

r9software commented 6 years ago

General information

SDK/Library version: :3.3.0 Environment: SandBox Android 8

Issue description

As a developer I can test with a declined credit card, so that I should be notified my payment was not successful

r9software commented 6 years ago

Tested with https://developers.braintreepayments.com/reference/general/testing/java#unsuccessful-credit-card-verification

jackellenberger commented 6 years ago

Hi @r9software, which credit card test value are you using, and what method are you calling? Are you expecting a rejected transaction (which can be tested by altering the transaction amount) or a rejected verification which can be tested by altering the card number?

If you have a snippet to share that would be helpful for our debugging!

crookedneighbor commented 6 years ago

Going to close this for inactivity.

crookedneighbor commented 6 years ago

Let us know if you need additional assistance.

r9software commented 6 years ago

I have not had chance to test with the Verification process, will give it a try today and post my update

r9software commented 6 years ago

@crookedneighbor this is the credit card 3566002020360505 I'm using the Drop-in UI on Android, after adding this card the drop-in does not show any warning it just doesn't continue with the expected flow of payment. After using this 4000111111111115 when this ticket was created they payment was approved, by now it is not approved but it is not returning or closing the Activity with the Exception included on the result as the Tutorial says, is this something that the server side implementation should handle (card verification is included in the server integration) or is there a way on how the client should verify the card using the drop-in UI? Is this something that the DropIn UI should be doing? https://developers.braintreepayments.com/guides/drop-in/overview/android/v2

crookedneighbor commented 6 years ago

It should only be doing verifications if you are attempting to vault the card. I'll re-open this while we investigate it.

crookedneighbor commented 6 years ago

@r9software Can you confirm that you are attempting to vault those cards?

r9software commented 6 years ago

@crookedneighbor, I'm receiving a nonce value that is sent to the server, but with the cards that should be failing, no message is displayed on the Braintree UI we don't receive any kind of error to show the user that the payment was unsuccessful. I'm not attempting to store to the vault on this point.

Epreuve commented 6 years ago

@r9software The test card numbers you provided only fail when you're performing verifications when vaulting. As such, if you're not storing the cards in the vault, they will not fail and you'll successfully complete a transaction. This is expected and noted in the docs here as mentioned previously.

The Drop-in does not create transactions, and as such will not ever display an error itself, that a transaction failed.

The Drop-in can however, vault cards automatically when you use a client token with a customer ID. When you do this and enable verifications, the test card numbers you noted will fail, and the Drop-in will generate an error as expected.

Again, transactions are not the same as verifications, and the card numbers used to test failed verifications will generate successful transactions. If you'd like to generate a failed transaction, you will need to use a specific amount corresponding to the type of failure you'd like to imitate. You will then need to pass any relevant information from your server back to your app to inform your customer if you wish to do so.

r9software commented 6 years ago

@Epreuve thank you for your explanation. My account has enabled https://articles.braintreepayments.com/control-panel/vault/card-verification also I am using a client token with a customer ID server side sent to the clients. So the expected behavior is that the Drop-in fails. Something that it is not happening right to me. It is happening on iOS however but not on android, that means that my configuration is correct on the server and on the account but something on the Android component is not. I am using the basic configuration of the DROP IN UI https://developers.braintreepayments.com/guides/drop-in/overview/android/v2 // @crookedneighbor

Epreuve commented 6 years ago

@r9software You had mentioned previously that you weren't attempting to vault at this point, which is why I clarified a bit above. As it sounds like you are, would you be able to provide a nonce value that was generated using a card that you expected to be rejected?

Don't worry, the nonce is an arbitrary value that is unusable by any account other than yours, and holds no encrypted or obfuscated information that one could use against you. It would just allow us to take a look at some logs to attempt to identify whats happening here.

r9software commented 6 years ago

I will get back to you with that soon @Epreuve

r9software commented 6 years ago

image It remains on this screen, so I can not get the NONCE value, it is not throwing any error or warning it is not adding the card at all @Epreuve

Epreuve commented 6 years ago

@r9software Running our demo here, I wasn't able to replicate this issue with the same test card value you're using.

If you'd like to share a basic repo that replicates the behavior so we can take a closer look at how you've setup the Drop-in, we'd be happy to do so.

r9software commented 6 years ago

compile 'com.braintreepayments.api:drop-in:3.3.0' compile 'io.card:android-sdk:5.5.1'

My code is pretty simple

DropInRequest dropInRequest = new DropInRequest()
                    .clientToken(response.getToken());
            dropInRequest.amount(String.valueOf(getFee()));
            GooglePaymentRequest googlePaymentRequest = new GooglePaymentRequest()
                    .transactionInfo(TransactionInfo.newBuilder()
                            .setTotalPrice(String.valueOf(getFee()))
                            .setTotalPriceStatus(WalletConstants.TOTAL_PRICE_STATUS_FINAL)
                            .setCurrencyCode("USD")
                            .build());
            dropInRequest.googlePaymentRequest(googlePaymentRequest);
            startActivityForResult(dropInRequest.getIntent(this), DROP_IN_REQUEST);

This is the on Activity Result, which is never called when I use this component and cards that should be failing

 if (requestCode == DROP_IN_REQUEST) {
            if (resultCode == Activity.RESULT_OK) {
                DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
                // use the result to update your UI and send the payment method nonce to your server
                Log.d("Nonce",result.getPaymentMethodNonce().getNonce());
               //some logic
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // the user canceled
                Toast.makeText(this, "You need to do the payment first to continue", Toast.LENGTH_SHORT).show();
            } else {
                // handle errors here, an exception may be available in
                Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
                Log.e("Payment Result", error.getMessage());
            }
        }
quinnjn commented 6 years ago

Hi @r9software,

Your code looks correct to me.

One value that we need for card validation is a CVV. Drop-in is not showing a CVV or Postal code field in the card entry screenshot you posted. Drop-in shows those fields when CVV / Postal Code challenges are requested. Those challenge requests are powered from the control panel. So this indicates that the control panel might not have card verification set correctly.

Or it also could have been a stale caching issue if you turned the value on in the control panel and re-tried before the cache was updated.

Unfortunately this repo's issue forum is not the best equipped to diagnose control panel settings. You'll get more hands on control panel support going through our support contact form.

I would suggest getting in touch with them and if they indicate that your control panel is setup correctly we can re-pick up the issue here.

r9software commented 6 years ago

@quinnjn thank you, I sent them a support ticket, I will clean, delete and rebuilt and see if that helps I know I have activated the validation, but I'm not sure if this is a cache issue, and how to clean or prevent this issue.

quinnjn commented 6 years ago

@r9software I'm going to close this for now, hoping that the support ticket solved your issue! Please comment if you think this should be re-opened

r9software commented 6 years ago

Can someone reopen this issue? According to the Braintree support this was reproducible on their end and will be scalated accordingly since issue as this may be caused by something outside of my fraud prevention tools being enabled

quinnjn commented 5 years ago

@r9software sorry for the long delay. Would you be able to build our Demo app using your client token / tokenization key?

You can hard code a client token here: https://github.com/braintree/braintree-android-drop-in/blob/9a6829c1433ea1b3f39d9d5c7b2f3fe472425d48/Demo/src/main/java/com/braintreepayments/demo/models/ClientToken.java#L11

r9software commented 5 years ago

@quinnjn Of course, I will give it a try in the next couple days

quinnjn commented 5 years ago

@r9software any updates for us?

r9software commented 5 years ago

Sorry I have not touched the project until today, I built the project and ran the app, let me know what else do you need Regards

crookedneighbor commented 5 years ago

Since you don't seem to be running into this issue anymore, I'm going to close this issue. If you're still having issues with it, feel free to comment here and we can re-open it.

liacosgrove commented 4 years ago

Edit: I now realize that this is the Android drop-in support, but this issue doesn't seem to be an Android-specific problem. Please redirect my comment wherever it needs to go, thanks.

This issue still persists as OP originally reported. I'm attempting to implement this in ASP NET Core MVC (C#) on the server, using the Javascript Drop-In client side, and I only get successes for cards which were supposed to fail verification according to your list of test numbers. I understand failed transactions are a different set of tests, and I plan to test them to at least ensure that my error pathway works as expected.

We should be able to test declined cards without vaulting them to ensure non-vaulted one-time payments will behave as expected prior to production. How else are we to expect that non-vaulted cards will be properly declined upon switching to production?

I love the PayPal service your middleware provides, but I just cannot see how we're expected to confidently use this software for cards when you expect us to go to production prior to performing card verification tests on non-vaulted cards. I know that as a personal security measure when I use my own credit card on websites, I never choose to vault my card under their care if I have the option.

Epreuve commented 4 years ago

@liacosgrove I think there's some confusion here. A verification is part of vaulting a card, as it confirms the card is capable of being charged and, in most cases, can confirm other values such as the CVV, postal code, and address match the banks records. No charge is made to the customer (though they might occasionally see a temporary 1$ authorization).

If you're not vaulting a payment method nonce, and simply passing it to your server to be used in a transaction, there's no need to perform a verification. The transaction performs those same checks, but results in a charge.

The test card numbers for verification failures will never fail when attempting a transaction, they're not intended to. To simulate a failed transaction, you must specify certain amounts, CVVs, or postal codes as noted in our dev docs.

If you have further questions, please contact Braintree Support so they can help you work out your testing story.

liacosgrove commented 4 years ago

There are a number of folks then who've been confused over this phenomenon through the years: https://stackoverflow.com/questions/46257226/braintree-unsuccessful-credit-card-verification-is-not-working-for-my-code https://stackoverflow.com/questions/37712059/braintree-dropinui-gateway-rejection-card-verification-not-failing-when-creating https://wordpress.org/support/topic/invalid-card-numbers-accepted-using-the-sandbox/

I know what I'm experiencing, as did these^ other developers. I want to receive a separate failure for card verification in my testing environment. It should not rely on vaulting, or attempting to vault, the card.

As a separate-yet-related phenomenon: Your Drop-In UI is not set to request CVV by default which is fine for our use, but if it means that excluding this field by default allows fraud where shady folks can simply use a generated luhn number that will always succeed because it's part of a transaction -- then that is a security issue. It's very possible that it's not actually security issue when we flip on the switch to go live, but it IS a security issue when the only perspective I have at the moment is my development environment.

When developers see that your default-configured software offering provides the means to process cards, then they see you also offer separate test numbers for different failure types, they expect them to work with very little fiddling. I didn't mind turning on the card verification in my control panel, that's fine. I still don't mind enabling the CVV field if it will get me where I need to be with these verifications. But please know we're not all payment security engineers here who automatically understand the nuances which you have the luxury of taking for granted.

Most of us simply want to know that it failed in a specific way on your end, so we can report an even simpler failure message to our user. It's not far-fetched for developers to do this, as the impetus is on the user to research why their card failed. We see Braintree as a subsidiary of PayPal, and we take for granted that they know how to process credit cards as well as PayPal. PayPal at least used to allow for guest checkouts without even an account or vaulting of any data.

Epreuve commented 4 years ago

It has come up before as a point of confusion, which is why we've added notes to the testing docs to clarify.

It's a bit unclear what you mean when you say you want to receive a separate failure for card verification, and then go on to say it should not rely on vaulting as the concept of vaulting is why one would usually want to verify a card. You perform a verification to confirm the card meets criteria without creating a transaction, and if so, save it to the vault for future use. You would not perform a verification before a transaction unless you were vaulting, it's redundant. If you're instead referring to something like 3D Secure, that's a different matter entirely.

If you do not want to vault the card, simply creating a transaction is sufficient. You can still utilize fraud tools with transactions, such as CVV & postal code checks, and will receive processor declines should one occur. You do not need to vault a card to do this, just generate a nonce on the client, and send it to your server for use in a Transaction.Sale() call.

The Drop-in dynamically presents CVV and postal code fields based on your fraud tools settings. If they are not present, you likely do not have them enabled on your sandbox.

liacosgrove commented 4 years ago

I read your testing docs and am still experiencing this problem, because the problem exists either in your software, at your verification server, or both. If I create a transaction with your test credit card numbers which are supposed to fail because the number itself is supposed to be invalid, the transaction still succeeds. How do I know? Because the transaction amount appears in my sandbox dashboard.

You just said: "If you do not want to vault the card, simply creating a transaction is sufficient." ...this is clearly not sufficient for testing, as at least in the development environment it's not yielding the error that I - and all those other developers I linked - expect to see.

At this point I really don't even care if the error is separate from any other error as long as a presumably invalid card number cannot be used to complete a transaction. However I'm only getting successes like everyone else who's gotten this far.

If you're asking me: Why would someone want an invalid credit card number to fail as part of a transaction when you're not vaulting the card? ...then the reason should be obvious. An invalid credit card shouldn't be allowed to go through, irrespective of the purchase amount attempted, in any payment transaction.

I don't care about enabling CVV right now, and will only do it if my firm wishes it or if it's required for card verification on your end. If it's simply a separate fraud-prevention tool unrelated to all of this, then we can exclude it from our discussion.

JadaVonRuth commented 2 years ago

I am having similar issues, from documentation and samples provided it is not clear AT ALL how it should be done to make it safe when everything passes successfully despite it should not (at least in sandbox).

sshropshire commented 2 years ago

@JadaVonRuth thanks for using the Braintree SDK for Android. Can you create a new GH issue detailing the observed incorrect behavior of the SDK and provide steps to reproduce so we can take a look?