Developer Guidelines
1. Introduction
This guide provides detailed instructions on integrating Google Pay™ for web and in-app applications. Google Pay is a digital wallet that streamlines card payments, enabling swift and effortless transactions without the need to repeatedly input card information. Google securely stores the card data. This option is compatible with all devices (mobile phones and computers), irrespective of the operating system and web browser.
2. Register with Google
You’ll need to register as a Google Pay merchant using the Google Pay Business Console. You will be given a Google merchant identifier which you will need to provide to us when you are boarded:
1. If your business profile has never registered on Google, you will need to create one:
3. Web App Integration
3.1 Web App Implementation
- Merchant ID (You will have it after you create your Business Profile at Google Pay Business Console. See "Your Merchant ID is HERE")
- Merchant Key (The Merchant Key should have been provided by Bonum PSP)
- Demo Web App Source google-pay-example-v1.0.0.zip (Source files should have been provided by Bonum PSP)
For website integration with the Google Pay method, follow these references:
1. Google Pay Web developer documentation
2. Google Pay Web integration checklist
3. Google Pay Web Brand Guidelines
Note:
if you provide Google Pay as a payment method to your customers, you must use the official Google Pay logo and button assets in compliance with Google Pay Google Pay Web Brand Guidelines, without modifications to the Google Pay asset colors, proportions, or appearance.
Our implementation with Google Pay simplifies your ability to provide Google Pay as a payment option to your customers.
You must additionally complete the following essential step to enable Google Pay functionality:
- Adhere to Google policies: all merchants are required to follow the Google Pay and Wallet API's Acceptable Use Policy and accept the terms defined in the Google Pay API Terms of Service.
The gateway parameter in the script should have the constant value of "bonumpsp", according to the example below:
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'bonumpsp', // This is Bonum's Gateway ID.
gatewayMerchantId: 'BCR2DN7TVGEYH4JB' //Replace with your Merchant ID.
}
}
Please be aware that Bonum, as the processor of Google Pay payments, facilitates the handling of payment card type issued by MasterCard organization. This necessitates configuring the Google script as follows:
parameters: {
allowedAuthMethods: ['CRYPTOGRAM_3DS'], //We support CRYPTOGRAM_3DS auth method
allowedCardNetworks: ['MASTERCARD'] //Currently we support Mastercard
},
As a response, Google will provide the PaymentData item, wherein the paymentMethodData.tokenizationData.token field will include encrypted Google Pay Token (a string of characters). Your front-end web app will need to send this token with your order_id, amount and currency_code to your back-end server:
"token": "{\"signature\":\"MESDDFCr5Hsu+h4jDGdo1pRbmhgHWBuLLvkrBXK+Ahdhh3hhdhhs+HDKKSduueuust388d\\u003d\",\"intermediateSigningKey\":{\"signedKey\":\"{\\\"keyValue\\\":\\\"HSHF5shhdCfaa3995f3ccc+ivsddabQ\\\\u003d\\\\u003d\\\",\\\"keyExpiration\\\":\\\"1762383604000\\\"}\",\"signatures\":[\"MEUCIBBLQ8Gn/+1IXD8BEZ0S30sD0GeCSsfoGsLiyTtH3RWdAiEAvPhPUPjdzXSVVZ72I21Exu9zakHP700NlLdtYKY6So4\\u003d\"]},\"protocolVersion\":\"ECv2\",\"signedMessage\":\"{\\\"encryptedMessage\\\":\\\"DgorZjE21nXjNObra/xxxxxxAAXXAXXXXXXT8X/u/Djqp+AdFM\\\\u003d\\\",\\\"ephemeralPublicKey\\\":\\\"BO/oauy773u3jj3+vDjuauuahyhe772jjca\\\\u003d\\\",\\\"tag\\\":\\\"J4no/tst663hbdhhshs73najja+EHYg\\\\u003d\\\"}\"}"
If a billing address is required for Google Pay, ensure that you include required parameters. For more details, see BillingAddressParameters.
Billing address request example:
"allowedPaymentMethods": [
{
"type": "CARD",
"parameters": {
"billingAddressRequired": true,
"billingAddressParameters": {
"phoneNumberRequired": true,
"format": "MIN"
},
"allowedCardNetworks": [...],
"allowedAuthMethods": [...]
},
"tokenizationSpecification": {...}
},
]"
Google Pay > PSP > Demo Web App Source
- index.html - The frontend with the Google Pay button and JavaScript integration.
- server.js - The backend server (Node.js with Express) that handles Google Pay merchant payment processing.
- package.json - Lists dependencies needed for your backend (e.g., express, node-fetch).
- package-lock.json - Automatically generated to lock dependency versions.
Web App > Frontend Integration
// Google Pay integration
const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'TEST' });
// TEST is for Sandbox environment
// PRODUCTION is for prod environment
const baseRequest = {
apiVersion: 2,
apiVersionMinor: 0
};
function getPaymentDataRequest() {
const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0).toFixed(2);
return Object.assign({}, baseRequest, {
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ['CRYPTOGRAM_3DS'],
allowedCardNetworks: ['MASTERCARD']
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'bonumpsp', // Set Bonum's gateway ID: bonumpsp
gatewayMerchantId: 'BCR2DN7TVGEYH4JB' //Replace with your Merchant ID.
}
}
}],
merchantInfo: {
merchantName: 'Set Your Business Name here', //Replace with Your Business Name.
merchantId: 'BCR2DN7TVGEYH4JB' //Replace with your Merchant ID.
},
transactionInfo: {
totalPriceStatus: 'FINAL',
totalPrice: total,
currencyCode: 'MNT' //Currency code
}
});
}
function onGooglePayButtonClicked() {
const request = getPaymentDataRequest();
paymentsClient.loadPaymentData(request).then(function(paymentData) {
console.log('Payment token:', paymentData.paymentMethodData.tokenizationData.token);
alert('Payment token received! Send it to your Back here.');
sendPaymentData(paymentData.paymentMethodData.tokenizationData.token, request.transactionInfo.totalPrice, request.transactionInfo.currencyCode);
}).catch(function(err) {
console.error(err);
});
}
function sendPaymentData(token, totalPrice, currencyCode) {
try {
//frontend will send token to its backend. merchant can customize to their needs.
const response = await fetch('http://localhost:3000/api/send/payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, orderId: 'REPLACE_ORDER_ID_HERE', amount: totalPrice, currencyCode: currencyCode}),
});
const result = await response.json();
// Return transaction state to Google Pay
return {
transactionState: result.transactionState,
error: result.transactionState === 'ERROR' ? {
reason: 'PAYMENT_AUTHORIZATION',
message: result.details.message,
intent: 'PAYMENT_AUTHORIZATION'
} : undefined
};
} catch (error) {
console.error('Error processing payment:', error);
alert('Unexpected error occurred while processing payment.');
// Return transaction state to Google Pay
return {
transactionState: 'ERROR',
error: result.transactionState === 'ERROR' ? {
reason: 'PAYMENT_AUTHORIZATION',
message: result.details.message,
intent: 'PAYMENT_AUTHORIZATION'
} : undefined
};
}
}
Web App > The backend Integration
Note: Handle payment authorization and process the payment.
Replace “REPLACE_YOUR_MERCHANT_KEY"with your merchant
key.
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const cors = require('cors');
const app = express();
const PORT = 3000;
// Allow specific origins (replace `http://example.com` with your frontend's URL)
app.use(cors({
origin: 'https://testpsp.bonum.mn', // Allow this specific origin for TEST
//origin: 'https://psp.bonum.mn', // Allow this specific origin for PROD
}));
// Middleware: Parses incoming JSON request bodies
app.use(bodyParser.json());
/**
* Endpoint to process payment authorization.
* The client sends a token and an orderId, which are forwarded to the PSP (Payment Service Provider).
*/
app.post('/api/send/payment', async (req, res) => {
const { token, orderId, amount, currencyCode } = req.body;
// Step 1: Validate incoming request data
if (!token || !orderId || !amount || !currencyCode) {
return res.status(400).json({
success: false,
message: 'Missing token, orderId, amount or currencyCode',
});
}
try {
// Step 2: Forward the payment data to the PSP
const response = await axios.post(
'https://testpsp.bonum.mn/api/payment/process/google', // Bonum PSP Test endpoint
//'https://psp.bonum.mn/api/payment/process/google', // Bonum PSP Production endpoint
{
token, // Payment token received from Google Pay
order_id: orderId, // Merchant invoice/order id
amount: amount, // Amount
currency_code: currencyCode, // MNT, USD ...etc Currency code
},
{
headers: {
'Content-Type': 'application/json',
'x-merchant-key': 'REPLACE_YOUR_MERCHANT_KEY', // Replace with your actual merchant key
},
}
);
console.log('resp', response.data);
// Map PSP response to Google Pay transactionState
let transactionState = 'ERROR';
if (response.data.success) {
transactionState = 'SUCCESS';
}
res.json({
transactionState,
details: {
orderId: response.data.orderId,
message: response.data.desc,
code: response.data.status_code
}
});
} catch (error) {
console.error('Error processing payment:', error.message);
// Step 4: Handle errors from the PSP or network issues
if (error.response) {
// Errors returned directly by the PSP
res.json({
transactionState,
details: {
orderId: error.response.data.orderId,
message: error.response.data.desc,
code: error.response.data.status_code
}
});
}
// Step 5: Handle unexpected or generic errors (network, server, etc.)
res.json({
transactionState,
details: {
orderId,
code: 500
message: 'Unexpected error occurred while processing payment.',
}
});
}
});
// Start the Express server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Web App > The backend integration
Note: You can use the /api/payment-log/read API for handling any
payment failure cases.
Replace
“REPLACE_YOUR_MERCHANT_KEY"
with your merchant key.
This API call should be executed on your backend.
func checkPaymentByOrderId(orderId: String) {
let manager = AFHTTPSessionManager()
manager.requestSerializer = AFJSONRequestSerializer()
manager.responseSerializer = AFJSONResponseSerializer()
manager.responseSerializer.acceptableContentTypes = manager.responseSerializer.acceptableContentTypes?.union(["application/json"])
//TODO: set Merchant Key here. Bonum will provide Merchant Key.
manager.requestSerializer.setValue("SET-YOUR-MERCHANT-KEY-HERE", forHTTPHeaderField: "x-merchant-key")
//Demo URL. Note: This URL charges the bank transaction. Please use small amount when you test
var urlString = "https://testpsp.bonum.mn/api/payment-log/read"
//Production URL. When you push your Build to the production
//var urlString = "https://psp.bonum.mn/api/payment-log/read"
urlString = urlString + "?order_id=" + orderId
// Convert the JSON object to a JSON string
print("API Url: \(urlString)")
manager.get(urlString,
parameters: nil,
headers: nil, progress: { progress in
print("Download progress: \(progress.totalUnitCount)")
}, success: { task, responseObject in
print("Transactions for Order ID: \(orderId)")
print("GET response: \(responseObject ?? "No response")")
}, failure: { task, error in
print("Error on GET request: \(error.localizedDescription)")
})
}
Web App > The backend integration
Note:
"success": false
indicates that the transaction failed for some reason.
Note:
"success": true
indicates that the transaction was processed successfully.
[
{
"merchant_order_id": "9876543",
"amount": 5000,
"success": false,
"createdAt": "2025-01-24T03:22:03.135Z"
},
{
"merchant_order_id": "9876543",
"amount": 5000,
"success": true,
"createdAt": "2025-01-24T03:22:03.135Z"
}
]
3.2 Submit Your Web App for Google Review
Your integration must be completed within your Sandbox/Test environment. And you need to prepare below screenshots of your web app for Google Review:
1. Item selection
2. Pre-purchase screen
3. Payment method screen
4. Google Pay API payment screen
5. Post-purchase screen
Go to Google Pay Business Console and login with your credentials.
1. Select "Google Pay API", scroll down and click "Add a website" in "Add an integration" section:
2. Enter your domain, choose "Gateway" from "Integration Type" and upload your screenshots:
3. After uploading your screenshots, click "Save" and you will be able to submit for the review:
4. Submit for review:
After submition, the reviewing process will take 2-3 business days. If your submition gets approved by Google, you will be able to integrate your app in the production environment.
4. Android App Integration
4.1 Android App Implementation
- Merchant ID (You will have it after you create your Business Profile at Google Pay Business Console. See "Your Merchant ID is HERE")
- Merchant Key (The Merchant Key should have been provided by Bonum PSP)
- Demo Flutter App Source google-pay-example-v1.0.0.zip (Source files should have been provided by Bonum PSP)
For Android app integration with the Google Pay method, follow these references:
1. Google Pay Android developer documentation
2. Google Pay Android integration checklist
3. Google Pay Android brand guidelines
Note:
if you provide Google Pay as a payment method to your customers, you must use the official Google Pay logo and button assets in compliance with Google Pay Google Pay Android brand guidelines, without modifications to the Google Pay asset colors, proportions, or appearance.
Our implementation with Google Pay simplifies your ability to provide Google Pay as a payment option to your customers.
You must additionally complete the following essential step to enable Google Pay functionality:
The gateway parameter in the script should have the constant value of "bonumpsp", according to the example below:
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'bonumpsp', // This is Bonum's Gateway ID.
gatewayMerchantId: 'BCR2DN7TVGEYH4JB' //Replace with your Merchant ID.
}
}
Please be aware that Bonum, as the processor of Google Pay payments, facilitates the handling of payment card type issued by MasterCard organization. This necessitates configuring the Google script as follows:
parameters: {
allowedAuthMethods: ['CRYPTOGRAM_3DS'], //We support CRYPTOGRAM_3DS auth method
allowedCardNetworks: ['MASTERCARD'] //Currently we support Mastercard
},
As a response, Google will provide the PaymentData item, wherein the paymentMethodData.tokenizationData.token field will include encrypted Google Pay Token (a string of characters). Your Android app will need to send this token with your order_id, amount and currency_code to your back-end server. And your back-end server should send the payload to our end-point "/api/payment/process/google" as described above:
"token": "{\"signature\":\"MESDDFCr5Hsu+h4jDGdo1pRbmhgHWBuLLvkrBXK+Ahdhh3hhdhhs+HDKKSduueuust388d\\u003d\",\"intermediateSigningKey\":{\"signedKey\":\"{\\\"keyValue\\\":\\\"HSHF5shhdCfaa3995f3ccc+ivsddabQ\\\\u003d\\\\u003d\\\",\\\"keyExpiration\\\":\\\"1762383604000\\\"}\",\"signatures\":[\"MEUCIBBLQ8Gn/+1IXD8BEZ0S30sD0GeCSsfoGsLiyTtH3RWdAiEAvPhPUPjdzXSVVZ72I21Exu9zakHP700NlLdtYKY6So4\\u003d\"]},\"protocolVersion\":\"ECv2\",\"signedMessage\":\"{\\\"encryptedMessage\\\":\\\"DgorZjE21nXjNObra/xxxxxxAAXXAXXXXXXT8X/u/Djqp+AdFM\\\\u003d\\\",\\\"ephemeralPublicKey\\\":\\\"BO/oauy773u3jj3+vDjuauuahyhe772jjca\\\\u003d\\\",\\\"tag\\\":\\\"J4no/tst663hbdhhshs73najja+EHYg\\\\u003d\\\"}\"}"
If a billing address is required for Google Pay, ensure that you include required parameters. For more details, see BillingAddressParameters.
Billing address request example:
"allowedPaymentMethods": [
{
"type": "CARD",
"parameters": {
"billingAddressRequired": true,
"billingAddressParameters": {
"phoneNumberRequired": true,
"format": "MIN"
},
"allowedCardNetworks": [...],
"allowedAuthMethods": [...]
},
"tokenizationSpecification": {...}
},
]"
4.2 Submit Your Android App for Google Review
Your integration must be completed within your Sandbox/Test environment. And you need to prepare below screenshots of your Android app for Google Review:
1. Item selection
2. Pre-purchase screen
3. Payment method screen
4. Google Pay API payment screen
5. Post-purchase screen
Go to Google Pay Business Console and login with your credentials.
1. Select "Google Pay API", choose your app to integrate and click "Add" of integration screenshots:
2. Choose "Gateway" from "Integration Type" and upload your screenshots:
3. After uploading your screenshots, click "Save" and "Submit":
After submition, the reviewing process will take 2-3 business days. If your submition gets approved by Google, you will be able to integrate your app in the production environment.
5. SUPPORT & CONTACT
If you need further assistance, please contact our team:
- Email:
[email protected]
- Phone: +976 7200-5000