braintree / braintree-web-drop-in

Braintree Drop-in for the web
MIT License
200 stars 126 forks source link

transaction.sale() calls fail with "Authentication Required" with authenticated payment methods #714

Closed ex5 closed 3 years ago

ex5 commented 3 years ago

General information

Issue description

We are having an issue with 3DS implementation for a platform that uses recurring transactions (no Braintree subscriptions) and DropIn UI. The 3DS in DropIn UI appears to work, a couple of customers reported that they've passed through authentication without any errors, however sale() calls using payment methods created with the nonces returned by DropIn still fail with "Authentication Required".

The way it's implemented is as follows:

  1. A client token is generated for a customer ID;
  2. DropIn UI is initialised with threeDSecure: true;
  3. A payment_method_nonce, device_data and "verify_card": True are passed to payment_method.create and payment method token is stored;
  4. The stored payment token is later used to transact a sale, with an assumption that an enriched nonce has been associated with this payment token, if 3DS was required.

However, transactions are still failing with "Authentication Required" for some EU-based customers even though they've passed the authentication process successfully. Please advise on why the 3DS enriched nonces appear to be lost and how can this be fixed on our side.

hollabaq86 commented 3 years ago

👋 @anka-sirota please contact Support, they will assist in troubleshooting this issue with you.

introvert commented 2 years ago

Were you able to figure this one out? We are experiencing the same issue @ex5

ex5 commented 2 years ago

@introvert Braintree support had eventually helped with figuring this out, yes. The gist of it was that we had implemented recurring transactions incorrectly.

The fix was passing verify_card: false when payment method is created to stop 3DS authentication from being consumed, extracting that authentication and storing it, in case first recurring transaction happens in absence of the customer, and then passing that authentication with a source: recurring_first sale() call and source: recurring for subsequent transactions with the same payment method.

This is based on the following suggestion offered by support:

If you do have a recurring model outside of Braintree's recurring billing engine, you would follow the steps above, but add the transaction_source option set to recurring_first in that initial customer present transaction. For subsequent transactions you would pass the transaction source option as recurring. Exceptions would apply for recurring transactions using a payment method that has been vaulted prior to September 14, 2019. ... It sounds like you need to be able to provide SCA for transactions that are initiated when the customer is not present, is that correct? If so, I'd like to recommend a potential flow.

  • Tokenize customer's payment information, generating a payment method nonce
  • Pass that nonce to verifyCard, receiving back a 3DS-enriched nonce. You'll then want to query that nonce and save the three_d_secure_info.three_d_secure_authentication_id from the result in a local database.
  • Vault payment method using 3DS nonce, being sure not to use Card Verification (alternatively, pass verify_card as false in your PaymentMethod: Create request.) This is to prevent the SCA acquired in the previous step from being consumed in an authorization.
  • When the customer's order to ready to be charged, your integration can make a Transaction: Sale request, specifying the three_d_secure_authentication_id from your local database and the appropriate transaction_source. This ensures that SCA is presented at authorization and 3DS information is populated on the Transaction.

This flow is especially useful because it allows you to store and provide SCA on a future transaction for up to 90 days. ... The three_d_secure_authentication_id value is single use, meaning it should only be passed on the recurring_first transaction. Any subsequent recurring or unscheduled transactions would then be out of scope of PSD2 and that three_d_secure_authentication_id is no longer needed on these calls.