Google PayTM Resources
To integrate Digital wallets alongside PayFields, you should complete your payment page integration. For more information, go to Configuring your payment page.
To add Hosted Fields to your payment page, complete the following steps:
Create an HTML element with a unique ID for each pay field you want to place on your payment page. Include the following HTML elements.
Note: You can add other HTML elements, but your integration must manage them.
<div id="credit-card">
<div id="card-number"></div>
<div id="card-expiration"></div>
<div id="card-cvv"></div>
<div id="submit"></div>
</div>
<div id="paymentRequestPlainButton"></div>Link our JavaScript library to your payment page. To do so, include the following JavaScript tag in the header of your page.
<script src="https://js.paygateway.com/secure_payment/v1/globalpayments.js"></script>See Step 2 of our Hosted Fields configuration - link our JavaScript library to your payment page. There are no changes required to existing integrations.
See Step 3 of our Hosted Fields configuration - add your credentials to the library.
Google pay requires a Merchant Key.
For PayFields only, you need to provide the API key to obtain tokenized card data that is clear PAN data entered into the page.
For Google Pay, there will need to be a Merchant key added to the configuration for the client. For more information on merchant key, visit:
Image here
The call to configure needs to be updated to include the Merchant Key for Google Pay.
GlobalPayments.configure({
"X-GP-Api-Key": 'be1kB_______tg8gQ2AHg',
"X-GP-Environment": 'test',
"X-GP-Merchant-Key": '123462979645',
'enableAutocomplete': true,
"Authorization": "AuthToken yJhbGciOiJIUY3ODIjo_____MeJf36POk6yJV_adQssw5c"
});See Step 4 of our Hosted Fields configuration - call the UI form and create the pay fields. No changes are required to existing integrations.
See Step 5 of our Hosted Fields configuration - customizing the pay fields on your page. No changes required to existing integrations.
See Step 6 of our Hosted Fields configuration - handle callback function responses. No changes required to existing integrations.
For the HTML element that was created above, you can configure it to process either Google pay, Apple Pay or both payment methods. You also can render two buttons, one for each, and set up each one individually.
We are following the W3C/Mozilla standard for the payment options objects for reference.
URL-based payment method identifiers
These may vary substantially depending on the specifics of the service, and a given processing service may have multiple URLs used, depending on the version of their API, their communication technology, and so forth.
Payments are processed by Google Pay. This is currently supported on Chrome and Chromium-based browsers.
const googlePayOptions = {
supportedMethods: "https://google.com/pay", data: {
environment: 'PRODUCTION',
apiVersion: 2,
apiVersionMinor: 0,
merchantInfo: {
// A merchant ID is available after approval by Google.
// https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist
merchantId: '12345678901234567890',
merchantName: 'Example Merchant'
},
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
allowedCardNetworks: ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
'gateway': 'globalpaymentsinc', // Use this value
'gatewayMerchantId': '{merchant-key}' // Check your MSH/OEV account for this value
}
}
}]
}
}Once the options for the button are known, the setup method can be called with the transaction amounts as well.
PaymentRequest() constructor - Web APIs | MDN
const paymentRequestForm =
GlobalPayments.paymentRequest.setup("#paymentRequestPlainButton", {
total: { label: 'Donation', amount: { currency: 'USD', value: '1.00' } },
}, [applePayOptions, googlePayOptions]);In order to test the integration checklist, you need to obtain a merchant ID from Google for production processing. After completing the registration (view details), you can change the setup data to include your merchant ID and the PRODUCTION environment value.
environment: 'PRODUCTION',
merchantId: '12345678901234567890',While the application is under development, you can use any value for merchant ID and the value of ‘TEST’ for the environment.
environment: 'TEST',
merchantId: '12345678901234567890',Similarly for Apple Pay, you would need to specify a different merchant ID in the Partner Test Environment; PIT/Production have different configuration databases. This value may need to be adjusted for testing
merchantIdentifier: "{apple-pay-merchant-id}",The partners' page is ultimately responsible for displaying the button and deciding how it is drawn. A PayFields client only wires up the event handlers for the page to process payments.
GooglePay styles
The Google pay Button can be rendered using standard CSS and assets provided by Google, or you have the option to include their pay.js script to render the button for you.
Basic example
If you choose to style the button on your own using standard CSS.
HTML
<button type="button"
id="paymentRequestPlainButton"
className="google-pay-button">
<img src="https://pay.google.com/about/static_kcs/images/logos/google-pay-logo.svg"
alt="Google Pay"
className="google-pay-icon" />
</button>CSS
.google-pay-button {
display: inline-flex;
align-items: center;
width: 300px;
justify-content: center;
padding: 10px 24px;
border: none;
border-radius: 0px;
background-color: rgba(255,255,255,0.2);
color: #000;
font-size: 16px;
font-weight: 500;
font-family: 'Roboto', sans-serif;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: background-color 0.3s ease;
}
.google-pay-button:hover {
background-color: #000;
}
.google-pay-button:focus {
outline: none;
box-shadow: 0 0 0 4px rgba(66, 133, 244, 0.4);
}
.google-pay-icon {
height: 24px;
margin-right: 8px;
}Pay.js example
If you choose to use the javascript provided by Google for your website, you’ll need to:
HTML
<!--Optional For Style Use Only-->
<script src="https://pay.google.com/gp/p/js/pay.js"></script>CSS
//Apply Google Pay Styles to Button
const paymentsClient = new google.payments.api.PaymentsClient({
environment: 'TEST' });
const button = paymentsClient.createButton({
buttonColor: 'default',
buttonType: 'checkout',
buttonRadius: 4,
onClick: () => { logToPage("Payment start"); },
allowedPaymentMethods: []
});
document.getElementById('paymentRequestPlainButton').appendChild(button);Google guidelines:
Brand guidelines | Google Pay API
Combined Style
Using Google Pay JS, and the built in CSS available from safari, you can enable the same element for both Google Pay And Apple Pay.
//Determine Which Button to use:
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
//Apply Apple Pay Styles to Button
const button = document.createElement('button');
button.style.appearance = '-apple-pay-button';
button.style.ApplePayButtonType = 'plain';
button.style.ApplePayButtonStyle = 'black';
button.style.width = '300px';
button.style.height = '50px';
document.getElementById('paymentRequestPlainButton').appendChild(button);
} else {
//Apply Google Pay Styles to Button
const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'TEST' });
const button = paymentsClient.createButton({
buttonColor: 'default',
buttonType: 'checkout',
buttonRadius: 4,
onClick: () => { logToPage("Payment start"); },
allowedPaymentMethods: []
});
document.getElementById('paymentRequestPlainButton').appendChild(button);
}After calling setup, the paymentRequestForm Object that is returned should be used to attach to the event handlers for errors, and for the token result.
Please note there is a distinction between the card form events from step 6 and the paymentRequestForm errors.
The objects returned from ui.form, and setup are different, and have different event handlers
cardForm = GlobalPayments.ui.form( ...
cardForm.on("token-success" ...
// As opposed to
paymentRequestForm = GlobalPayments.paymentRequest.setup(...
paymentRequestForm.on("token-success",Processing the request handling payment issues
During the payment request process, it is up to the partner’s page to take the token from the PayFields client, and then use that token for a transaction with the Transactions API.
Once the transaction is completed, it is then necessary to send a notification to the page so that the payment request form closes.
paymentRequestForm.on("token-success", (resp) => {
// Payment data was successfully tokenized
console.log('payment api token is here', resp);
// TODO: POST data to backend for processing
// Mark the payment as `success`, `fail`, or `unknown`
// after processing response is known
GlobalPayments.paymentRequest.complete("success");
});Example:
paymentRequestForm.on("token-success", (resp) => {
// Payment data was successfully tokenized
logToPage("Token obtained...");
logToken(resp);
//SEND to API for processing // - USED HERE FOR EXAMPLE ONLY - KEEP SERVER SIDE!!!! API
SECRETS SHOULD NOT BE EXPOSED
var { headers, payload } = getRequestData(resp, generateAuthToken(apple_encrypted_credential, transaction_api_secret, 'US'));
logToPage("Processing Payment...");
fetch('https://api.test.paygateway.com/transactions/sales', {
headers: new Headers(headers),
body: JSON.stringify(payload),
credentials: 'omit',
method: 'POST'
}).then(resp => {
logToPage("Payment Completed");
//Partial approvals Enabled
if (resp.status == 200 || resp.status == 201|| resp.status == 471|| resp.status == 474) {
GlobalPayments.paymentRequest.complete("success");
logToPage("Payment Success");
}
else {
GlobalPayments.paymentRequest.complete("fail");
logToPage("Payment Declined");
}
return resp.json();
}).then(resp => {
logResult(resp);
return resp;
}).catch(err => {
logToPage('payment error', err);
GlobalPayments.paymentRequest.complete("fail");
});
});Handling tokenization errors
During the request from the client to the backend tokenization flow, if there are any issues with the configuration, credentials or outages, the token-error event will be used to provide the partner’s page with information about the error that occurred.
paymentRequestForm.on("token-error", (resp) => {
console.log('payment api token-error is here', resp);
// TODO: Handle error received during tokenization
});Handling page errors
paymentRequestForm.on("error", (resp) => {
console.log('payment api error is here', resp);
// TODO: Handle Error received during the request process.
});Joining It Together
Simple Example:
<!DOCTYPE html>
<html>
<head>
<title>PayFields Test</title>
</head>
<body>
<script src="https://js.test.paygateway.com/secure_payment/v1/globalpayments.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://pay.google.com/gp/p/js/pay.js"></script><!--Optional For Style Use Only-->
<h1>PayFields Test</h1>
<h3 id="demo-log">Page Not Loaded</h3>
<div id="credit-card">
<div id="card-number"></div>
<div id="card-expiration"></div>
<div id="card-cvv"></div>
<div id="submit"></div>
</div>
<div id="paymentRequestPlainButton"></div>
<p id="token-result">Token Result</p>
<p id="payment-result">Payment Result</p>
<script defer>
//////////////////////////////////////////////////////
//constants
const gp_env = 'test';
const gp_merchant_key = '';
const google_merchant_id = ''; //Obtain from Google Setup
//Must match ID from merchant group/ merchant configuration/ apple certificate
const apple_merchant_id = '';
const apple_encrypted_credential = ''
const tokenization_api_key = '';
const tokenization_api_secret = ''; // USED HERE FOR EXAMPLE ONLY - KEEP SERVER SIDE!!!!
const transaction_api_url = 'https://api.pit.paygateway.com/transactions/sales';
const transaction_api_key = '';
const transaction_api_secret = ''; // USED HERE FOR EXAMPLE ONLY - KEEP SERVER SIDE!!!!
const applePayOptions =
{
supportedMethods: "https://apple.com/apple-pay", data: {
// version: 3,
merchantIdentifier: apple_merchant_id,
merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"],
supportedNetworks: ["amex", "discover", "masterCard", "visa"],
countryCode: "US",
storeDisplayName: "test"
}
};
const googlePayOptions = {
supportedMethods: "https://google.com/pay", data: {
environment: 'TEST',
apiVersion: 2,
apiVersionMinor: 0,
merchantInfo: {
// A merchant ID is available after approval by Google.
// @see {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist}
// merchantId: '12345678901234567890',
merchantName: 'Example Merchant'
},
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
allowedCardNetworks: ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
'gateway': 'globalpaymentsinc',
'gatewayMerchantId': gp_merchant_key
}
}
}]
}
}
//////////////////////////////////////////////////////
//Utility Functions
function logToPage(msg, obj) {
if (obj) {
document.getElementById("demo-log").innerHTML = msg + ' ' + JSON.stringify(obj);
}
else {
document.getElementById("demo-log").innerHTML = msg;
}
}
function logResult(obj) {
document.getElementById("payment-result").innerText = JSON.stringify(obj);
}
function logToken(obj) {
document.getElementById("token-result").innerText = JSON.stringify(obj);
}
// USED HERE FOR EXAMPLE ONLY - KEEP SERVER SIDE!!!!
function generateAuthToken(accountCredential, apiSecret, region) {
if (accountCredential == null || accountCredential == "" || region == null ||
region == "" || apiSecret == null || apiSecret == "") {
throw "MANDATORY INPUT DATA IS EMPTY";
}
try {
var encodedHeaderJSON = encodeURL(generateEncodedJSONHeader());
var encodedPayLoadJSON = encodeURL(generateEncodedPayloadJSON(accountCredential,
region));
var encodedSignature = encodeURL(generateHashSignature(encodedHeaderJSON,
encodedPayLoadJSON, apiSecret));
return encodedHeaderJSON + "." + encodedPayLoadJSON + "." + encodedSignature;
} catch (err) {
var errorMsg = "Error While Generating Auth-Token : " + err;
throw errorMsg;
}
}
// Generates JWT Signature
function generateHashSignature(encodedHeaderJSON, encodedPayLoadJSON, apiSecret) {
var data = encodedHeaderJSON + "." + encodedPayLoadJSON;
var hash = CryptoJS.HmacSHA256(data, apiSecret);
return CryptoJS.enc.Base64.stringify(hash);
}
// Generates JWT Payload
function generateEncodedPayloadJSON(accountCredential, region) {
var payLoadObj = new Object();
payLoadObj.account_credential = accountCredential;
payLoadObj.region = region;
payLoadObj.type = "AuthTokenV2";
payLoadObj.ts = new Date().getTime();
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON
.stringify(payLoadObj)));
}
// Generates JWT Header
function generateEncodedJSONHeader() {
var headerObj = new Object();
headerObj.alg = "HS256";
headerObj.typ = "JWT";
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON
.stringify(headerObj)));
}
function encodeURL(encodedSource) {
//Making Base64 URL Safe
encodedSource = encodedSource.replace(/\+/g, '-');
encodedSource = encodedSource.replace(/\//g, '_');
encodedSource = encodedSource.replace(/=+$/, '');
return encodedSource;
}
function getRequestData(resp, auth_token) {
var payload = {
card: {
temporary_token: resp.temporary_token
},
payment: {
amount: '1.00',
currency_code: '840'
},
transaction: {
country_code: '840',
processing_indicators: {
"allow_duplicate": false
}
}
};
var headers = {
'Content-Type': 'application/json',
'Authorization': 'AuthToken ' + auth_token,
'X-GP-Request-Id': 'TST-' + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/gu, (character) => {
const random = Math.floor(Math.random() * 16);
const value = character === 'x' ? random : (random & 0x3 | 0x8);
return value.toString(16);
}),
'X-GP-Api-Key': transaction_api_key,
'X-GP-Version': '2019-06-27',
};
return { headers: headers, payload: payload };
}
//////////////////////////////////////////////////////
//Integrations Steps -
logToPage("Starting...");
//Determine Which Button to use:
if (window.ApplePaySession && window.ApplePaySession.canMakePayments()) {
//Apply Apple Pay Styles to Button
const button = document.createElement('button');
button.lang = 'en'
button.style.appearance = '-apple-pay-button';
button.style.ApplePayButtonType = 'check-out';
button.style.ApplePayButtonStyle = 'black';
button.style.width = '300px';
button.style.height = '50px';
document.getElementById('paymentRequestPlainButton').appendChild(button);
} else {
//Apply Google Pay Styles to Button
const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'TEST' });
const button = paymentsClient.createButton({
buttonColor: 'default',
buttonType: 'checkout',
buttonRadius: 4,
onClick: () => { logToPage("Payment start"); },
allowedPaymentMethods: []
});
document.getElementById('paymentRequestPlainButton').appendChild(button);
}
//Generate Credentials
var auth_token_1 = generateAuthToken(apple_encrypted_credential, tokenization_api_secret, 'US');
logToPage("Configuring...");
//Apply Credentials to PayFields
GlobalPayments.configure({
"X-GP-Api-Key": tokenization_api_key,
"X-GP-Environment": gp_env,
"X-GP-Merchant-Key": gp_merchant_key,
"Authorization": "AuthToken " + auth_token_1
});
//Render Card Entry Fields
var cardForm = GlobalPayments.ui.form({
fields: {
"card-number": {
target: "#card-number",
placeholder: "**** **** **** ****"
},
"card-expiration": {
target: "#card-expiration",
placeholder: "MM / YYYY"
},
"card-cvv": {
target: "#card-cvv",
placeholder: "***"
},
"submit": {
target: "#submit",
text: "Submit"
}
},
styles: {
// your styles
}
});
// form-level event handlers.
cardForm.ready(function () {
logToPage("Registration of all credit card fields occurred");
});
cardForm.on("token-success", (resp) => {
logToPage("Token obtained...");
logToken(resp);
//SEND to API for processing // - USED HERE FOR EXAMPLE ONLY - KEEP SERVER SIDE!!!! API SECRETS SHOULD NOT BE EXPOSED
var { headers, payload } = getRequestData(resp, generateAuthToken(apple_encrypted_credential, transaction_api_secret, 'US'));
logToPage("Processing Payment...");
fetch(transaction_api_url, {
headers: new Headers(headers),
body: JSON.stringify(payload),
credentials: 'omit',
method: 'POST'
}).then(resp => {
logToPage("Payment Completed");
return resp.json();
}).then(resp => {
logResult(resp);
return resp;
}).catch(err => {
logToPage('payment error', err);
});
});
cardForm.on("token-error", function (resp) {
logToPage('error is here', resp);
// show error to the consumer
});
cardForm.on("error", (resp) => {
logToPage('error is here', resp);
// show error to the consumer
});
// field-level event handlers. example:
cardForm.on("card-number", "register", function () {
logToPage("Registration of Card Number occurred");
});
// Configure Page for Digital Wallets
const paymentRequestForm = GlobalPayments.paymentRequest.setup("#paymentRequestPlainButton", {
total: { label: 'Donation', amount: { currency: 'USD', value: '1.00' } },
}, [applePayOptions, googlePayOptions]);
paymentRequestForm.on("token-success", (resp) => {
// Payment data was successfully tokenized
logToPage("Token obtained...");
logToken(resp);
//SEND to API for processing // - USED HERE FOR EXAMPLE ONLY - KEEP SERVER SIDE!!!! API SECRETS SHOULD NOT BE EXPOSED
var { headers, payload } = getRequestData(resp, generateAuthToken(apple_encrypted_credential, transaction_api_secret, 'US'));
logToPage("Processing Payment...");
fetch(transaction_api_url, {
headers: new Headers(headers),
body: JSON.stringify(payload),
credentials: 'omit',
method: 'POST'
}).then(resp => {
logToPage("Payment Completed");
//Partial approvals Enabled
if (resp.status == 200 || resp.status == 201|| resp.status == 471|| resp.status == 474) {
GlobalPayments.paymentRequest.complete("success");
logToPage("Payment Success");
}
else {
GlobalPayments.paymentRequest.complete("fail");
logToPage("Payment Declined");
}
return resp.json();
}).then(resp => {
logResult(resp);
return resp;
}).catch(err => {
logToPage('payment error', err);
GlobalPayments.paymentRequest.complete("fail");
});
});
paymentRequestForm.on("token-error", (resp) => {
logToPage('payment api token-error is here', resp);
// TODO: Handle error received during tokenization
});
paymentRequestForm.on("error", (resp) => {
logToPage('payment api error is here', resp);
// TODO: Handle Error received during the request process.
});
</script>
</body>
</html>Feature Rich example
https://web.test.paygateway.com/payfields/demo-website/
Note: this page also has sample credentials that can be used in the code above.