Search code examples
javascriptpayment-gatewaybraintreegoogle-pay

How to test google pay 3d secure flow


Currently i am using braintree to integrate google pay. I have done all the code changes required. I have already joined test card group provided by google for testing.
But i need to test flow for 3d secure cards. Currently all the cards in test card suit are not 3d secure. How can i test this flow ? When i try to add cards from braintree or other sources, it gives me error with code OR-CCSEH-21.

Tried joining test card group by google. But it does not include any card with 3d secure.

I am using custom integration for google pay in braintree.


Solution

  • In order to trigger 3DS for non tokenized Google Pay cards if you use their custom integration you can follow this guide. The following code triggers a 3DS challenge flow for me:

    var button = document.querySelector('#submit-button');
    var paymentsClient = new google.payments.api.PaymentsClient({
      environment: 'TEST'
    });
    
    var threeDSecure;
    
    braintree.client.create(
      {
        authorization: 'abcd1234' // <-- needs a client token! (Tokenization keys can't be used)
      },
      function (clientErr, clientInstance) {
        braintree.googlePayment.create(
          {
            client: clientInstance,
            googlePayVersion: 2,
            googleMerchantId: 'merchant-id-from-google', // Optional in sandbox; if set in sandbox, this value must be a valid production Google Merchant ID
          },
          function (googlePaymentErr, googlePaymentInstance) {
            braintree.threeDSecure.create(
              {
                version: 2, // Will use 3DS2 whenever possible
                client: clientInstance,
              },
              function (threeDSecureErr, threeDSecureInstance) {
                if (threeDSecureErr) {
                  // Handle error in 3D Secure component creation
                  return;
                }
                threeDSecure = threeDSecureInstance;
              }
            );
    
            paymentsClient
              .isReadyToPay({
                apiVersion: 2,
                apiVersionMinor: 0,
                allowedPaymentMethods:
                  googlePaymentInstance.createPaymentDataRequest()
                    .allowedPaymentMethods,
              })
              .then(function (response) {
                if (response.result) {
                  button.addEventListener('click', function (event) {
                    event.preventDefault();
    
                    var paymentDataRequest =
                      googlePaymentInstance.createPaymentDataRequest({
                        transactionInfo: {
                          currencyCode: 'USD',
                          totalPriceStatus: 'FINAL',
                          totalPrice: '100.00', // Your amount
                        },
                      });
    
                    var cardPaymentMethod =
                      paymentDataRequest.allowedPaymentMethods[0];
                    cardPaymentMethod.parameters.billingAddressRequired = true;
                    cardPaymentMethod.parameters.billingAddressParameters = {
                      format: 'FULL',
                      phoneNumberRequired: true,
                    };
    
                    paymentsClient
                      .loadPaymentData(paymentDataRequest)
                      .then(function (paymentData) {
                        googlePaymentInstance.parseResponse(
                          paymentData,
                          function (err, result) {
                            if (err) {
                              // handle error
                              console.log(err);
                            }
    
                            // 3DS challenge when not NT
                            if (result.details.isNetworkTokenized === false) {
                              threeDSecure.verifyCard(
                                {
                                  amount: '100.00',
                                  nonce: result.nonce,
                                  bin: result.details.bin,
                                  onLookupComplete: (data, next) => {
                                    // use 'data' here, then call 'next()'
                                    next();
                                  },
                                },
                                function (err, response) {
                                  if (err) {
                                    // handle error
                                    return;
                                  }
                                  var lsShifted = response.liabilityShifted;
                                  var lsPossible = response.liabilityShiftPossible;
    
                                  // 3DS 'enriched' Google Pay nonce
                                  //to send to your server for the actual authorization
                                  console.log(response.nonce);
                                }
                              );
                            }
                          }
                        );
                      })
                      .catch(function (err) {
                        // handle error
                        console.log(err);
                      });
                  });
                }
              })
              .catch(function (err) {
                // handle error
                console.log(err);
              });
          }
        );
      }
    );