Google Pay and the iDonate SDK

Add the power of Google Pay to the iDonate SDK.

The iDonate SDK supports transactions via Google Pay. The path to a working Google Pay implementation can be long and winding, but this article can help light the way. Before beginning, it can be helpful to re-familiarize yourself with ReCaptcha and the data flow of iDonate SDK Credit Card Transactions.

Keep in mind that the code examples in the first sections of this article have been edited for readability, and are not necessarily working code. There is a section at the bottom of this article that shows the code as it appears in a full, working implementation.

Initialize the Google Pay Client

The first step toward including Google Pay in your SDK implementation is to set the initial configuration data that will be used when we create a new Google Pay Client.

Once we have created the Google Pay Client, we can move on to initialization. The call to initialize can occur any time before the user interaction, but in most cases, we'll encase the initialize call inside an event that occurs when the page is loaded.

First, the function will use the iDonate SDK to add the required scripts to the page. Then, inside the initialization function, we will need to pay attention to two data points: The onClick property within the button variable, and the element ID of the container variable. The onClick property is the function that will occur when the user interacts with the Google Pay button. The element ID should correspond to the DOM element where you'd like the button to appear.

const googlePay = new idonate.GooglePay(googlePayConfig);
const idonateClient = new idonate.client(config.organizationId, {enableSandboxMode:config.enableSandboxMode});

function initGooglePay(){

    idonateClient.GooglePay.injectScript();
    googlePay.getGooglePaymentClient().then((googlePayClient)=>{
          const button = googlePayClient.createButton({
              onClick: handleGooglePay,
              buttonType: "donate"
         });

          const container = document.getElementById('google-pay-container');
         container.appendChild(button);
    });
}

Handling User Interaction

The next step of the process occurs when the user interacts with the Google Pay button. This will call the function we specified in the initialization.

An important detail: The ReCaptcha token must be set before the user interacts with the Google Pay button. Please see this article for a refresher on how to configure ReCaptcha.

This handler function gathers the data that the user has entered into your custom HTML form, creating a transaction data object that can then be passed to the next part of the function, the Google Pay Client's onGooglePaymentButtonClicked function. We use the result of that as the parameter for the next function, which creates a billing data object from the parameter. Using that object, we then call the Google Pay client's CardConnect tokenizer, using the data we just built and the iDonate client's CardConnect Base URL as parameters.

Using the CardConnect token of the result of that function, we then call the Donate function.

function handleGooglePay(){

     let googlePayTransaction = setGooglePayTransactionData();
    googlePay.onGooglePaymentButtonClicked(googlePayTransaction).then((googlePayResult)=>{
          let billingData = createBillingData(googlePayResult);
          return googlePay.tokenizeWithCardConnect(billingData.paymentToken, idonateClient.cardConnectBaseUrl)
    }).then((cardConnectToken)=>{
         donate(cardConnectToken.token);
    }).catch((err)=>{
         displayError(err);
    });
}

Creating the Donation

The next step creates the donation itself within iDonate using Google Pay. Using the payment token passed by the handler function, we create a Payment Method Request object.

From there, we pass that data into the iDonate client's createPaymentMethod function, then, once we're in there, we use that data to create our CreateDonationRequest object, which we then pass to the iDonate Client's createDonation function.

This completes the transaction.

function donate(paymentToken){

     let createPaymentMethodRequest = buildPaymentMethodRequest(paymentToken);
    idonateClient.createPaymentMethod(createPaymentMethodRequest).then((paymentMethodResult)=>{
          const createDonationRequest = buildCreateDonationRequest(paymentMethodResult);
         idonateClient.createDonation(createDonationRequest).then((donationResult)=>{
              displayDonationResult(donationResult);
         });
    }).catch((err)=>{
         displayError(err);
    });
}

Expanded Code Examples

The code above, while syntactically correct, has been edited for readability. Let's go ahead and look at all the parts involved in a full, working Google Pay implementation.

/**

* Google Pay

*/

/**

* CLIENT CONFIGURATION

*/

//iDonate Client Configuration
const config = {
    organizationName: 'iDonate Alternative Payment Methods',
    organizationId: '[your organization id here]',
    paymentGatewayId: '[your cardconnect payment gateway id here]',
    merchantId: '[your cardconnect merchant id here]',
     enableSandboxMode: true, //Test mode active
    recaptchaType: 'organization',
};

//Google Pay Client Configuration
const googlePayConfig = {
    paymentDataRequest:{
         merchantInfo:{
              merchantId: '[your google merchant id here]',
              merchantName: 'Test Organization',
         },
         transactionInfo:{
              totalPrice:0
         }
    },
    paymentOptions:{
         environment: 'TEST'
    },
    cardConnectMerchantId: config.merchantId
};

/**

* LOCAL DATA

*/

let recaptchaToken = null;

let
billingContact = {
    firstName: '',
    lastName: '',
    email: '',
};

let billingAddress = {
    address1: '',
    city: '',
    state: '',
    zip: '',
    country: '',
};

/**

* CLIENT INITIALIZATIONS

*/

const idonateClient = new idonate.client(
    config.organizationId,
    {
         enableSandboxMode:config.enableSandboxMode,
    }
);

const googlePay = new idonate.GooglePay(googlePayConfig);

/**

* AUTOMATIC FUNCTIONS

*/

$(document).ready(function(){
     //Initialize the Google Pay client
    initGooglePay();
});

/**

* DISCRETE FUNCTIONS

*/

//Initialize Google Pay
function initGooglePay(){

     //Easy way to set/configure Google Pay scripts/environment
     idonate.GooglePay.injectScript();

     //Assign interaction behavior to the Google Pay client.
    googlePay.getGooglePaymentClient().then(googlePayClient => {

          //Create Google Pay button
          const button = googlePayClient.createButton({
              onClick: handleGooglePay,
              buttonType: "donate"
          });

          //Append Google Pay button to DOM element
          const container = document.getElementById('gp-section');
         container.appendChild(button);
    })
}

//Handle Google Pay
function handleGooglePay(){
     //Assign gift amount from DOM element
     googlePayConfig.paymentDataRequest.transactionInfo.totalPrice = $('#gift-amount').val();

     //Assign salutation from DOM element
     const salutation = $('#salutation-select').val();

     //Create transaction data
    googlePay.onGooglePaymentButtonClicked(googlePayConfig.paymentDataRequest.transactionInfo).then(googlePayResult => {

          //Create payment token from parameter's token
          const paymentToken = googlePayResult.paymentMethodData.tokenizationData.token;

          //Create billing data from parameter's billing address
          const googlePayBillingData = googlePayResult.paymentMethodData.info.billingAddress;

          //Create first/last name from parameter's name using an iDonate client function
          const nameObj = idonate.util.splitName(googlePayBillingData.name);

          //Create contact info inside billingContact
         billingContact.salutation = salutation;
         billingContact.firstName = nameObj.firstName;
         billingContact.lastName = nameObj.lastName;
          billingContact.email = googlePayResult.email;

          //Create address info inside billingAddress
         billingAddress.address1 = googlePayBillingData.address1;
         billingAddress.city = googlePayBillingData.locality;
         billingAddress.state = googlePayBillingData.administrativeArea;
         billingAddress.country = googlePayBillingData.countryCode;
          billingAddress.zip = googlePayBillingData.postalCode;

          //Pass the result of the Google Pay client's CardConnect tokenizer to next phase
          return googlePay.tokenizeWithCardConnect(paymentToken, idonateClient.cardConnectBaseUrl)

    }).then(cardConnectToken => {
          //Use the result of the cardconnect tokenizer to call the donate function
         donate(cardConnectToken.token);
    }).catch(err => {
          //Catch and handle any error
         console.error(err);
    });
}

function donate(paymentToken){
     //Payload, part 1: CreatePaymentMethodRequest object type
     const createPaymentMethodRequest = {
         paymentGatewayId: config.paymentGatewayId,
         paymentMethodType: 'google_pay',
         paymentMethodToken: paymentToken,
         contact: billingContact,
         address: billingAddress,
         recaptchaToken: recaptchaToken,
         recaptchaType: config.recaptchaType
     };

     //Create payment method using the iDonate client, then use that to create a donation request
    idonateClient.createPaymentMethod(createPaymentMethodRequest).then(
         (paymentMethodResult) => {
               //Payload, part 2: CreateDonationRequest object type
               const createDonationRequest = {
                    paymentGatewayId: config.paymentGatewayId,
                    recurringFrequency: 'once',
                    paymentMethodId: paymentMethodResult.paymentMethodId,
                    paymentAmount: googlePayConfig.paymentDataRequest.transactionInfo.totalPrice,
                    customerMeta:{},
                    billingContact: billingContact,
                    billingAddress: billingAddress,
                    recaptchaToken: recaptchaToken,
                    recaptchaType: config.recaptchaType,
               };


               //iDonate client submits donation request.
              idonateClient.createDonation(createDonationRequest).then((donationResult) => {
                    console.log(donationResult);
              })
         }).catch((err) => {
              console.error(err);
    });
}