Skip to main content

Google Pay

Google Pay integration lets customers pay with cards stored in their Google account. The payment takes place natively in the browser or app, without requiring them to enter card details.

How it works

POST/api/v1_0/cards/payment/{transactionId}/pay/google-payFull contract: xPayToken, deviceInfo, and error codes.Full contract in the API Reference

Step 1: Register the payment

Register the transaction as usual:

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/register \
-H "Content-Type: application/json" \
-d '{
"transactionType": "transfers",
"service": "abc123",
"value": "49.99",
"url_success": "https://myshop.example/success",
"url_fail": "https://myshop.example/failure",
"url_ipn": "https://myshop.example/api/ipn",
"checksum": "..."
}'

Save the transactionId from the response.

Step 2: Configure the Google Pay button

Add the Google Pay API script and configure the button on your website:

<script src="https://pay.google.com/gp/p/js/pay.js"></script>
<div id="google-pay-button"></div>

JavaScript configuration

// Google Pay configuration
const googlePayConfig = {
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [
{
type: 'CARD',
parameters: {
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
allowedCardNetworks: ['VISA', 'MASTERCARD'],
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'aciworldwide',
gatewayMerchantId: 'YOUR_MERCHANT_ID', // ID provided by dpay support
},
},
},
],
};

// Payment request configuration
const paymentDataRequest = {
...googlePayConfig,
transactionInfo: {
totalPriceStatus: 'FINAL',
totalPrice: '49.99',
currencyCode: 'PLN',
countryCode: 'PL',
},
merchantInfo: {
merchantName: 'My Shop',
merchantId: 'BCR2DN4T...', // Your Google Merchant ID
},
};

Initialize and display the button

let paymentsClient;

async function initGooglePay() {
paymentsClient = new google.payments.api.PaymentsClient({
environment: 'PRODUCTION', // or 'TEST' for testing
});

// Check whether Google Pay is available
const isReadyToPay = await paymentsClient.isReadyToPay(googlePayConfig);

if (isReadyToPay.result) {
const button = paymentsClient.createButton({
onClick: onGooglePayClicked,
buttonColor: 'black',
buttonType: 'pay',
buttonLocale: 'pl',
});
document.getElementById('google-pay-button').appendChild(button);
}
}

async function onGooglePayClicked() {
try {
const paymentData = await paymentsClient.loadPaymentData(paymentDataRequest);
await processGooglePayPayment(paymentData);
} catch (error) {
console.error('Google Pay error:', error);
}
}

// Initialize after the page loads
google.payments.api.PaymentsClient && initGooglePay();

Step 3: Send the token to dpay.pl

After the customer approves the payment in Google Pay, send the token you received to dpay.pl. Base64-encode the paymentMethodData.tokenizationData.token value from the Google Pay response and pass it as xPayToken.

POST https://api-payments.dpay.pl/api/v1_0/cards/payment/{transactionId}/pay/google-pay
Content-Type: application/json

Request parameters

{
"email": "customer@example.com",
"channelId": 31,
"xPayType": "GOOGLE_PAY",
"xPayToken": "<Base64(token from paymentMethodData.tokenizationData.token)>",
"deviceInfo": {
"browserAcceptHeader": "application/json,text/plain,*/*",
"browserJavaEnabled": "false",
"browserLanguage": "pl-PL",
"browserColorDepth": 24,
"browserScreenHeight": 1080,
"browserScreenWidth": 1920,
"browserTZ": -60,
"browserUserAgent": "Mozilla/5.0 ...",
"systemFamily": "Win32",
"geoLocalization": "52.2297,21.0122",
"deviceID": "device-unique-id",
"applicationName": "Netscape"
}
}

Required fields: xPayType, xPayToken, and deviceInfo (all fields shown in the example, including systemFamily, geoLocalization, deviceID, and applicationName; omitting any of them returns HTTP 422). The channelId field is optional. See the full deviceInfo specification in the API reference.

JavaScript—process the payment

async function processGooglePayPayment(paymentData) {
const transactionId = '...'; // From Step 1

// All deviceInfo fields are required—omitting any of them returns HTTP 422.
const deviceInfo = {
browserAcceptHeader: 'application/json,text/plain,*/*',
browserJavaEnabled: navigator.javaEnabled?.() ? 'true' : 'false',
browserLanguage: navigator.language || 'pl-PL',
browserColorDepth: screen.colorDepth,
browserScreenHeight: screen.height,
browserScreenWidth: screen.width,
browserTZ: new Date().getTimezoneOffset(),
browserUserAgent: navigator.userAgent,
systemFamily: navigator.platform || 'Unknown',
geoLocalization: 'unknown', // e.g. coordinates from the Geolocation API, with customer consent
deviceID: 'device-unique-id',
applicationName: navigator.appName || 'Netscape',
};

// The Google Pay token must be Base64-encoded.
// The backend adds channelId and forwards the request to dpay.
const xPayToken = btoa(paymentData.paymentMethodData.tokenizationData.token);

// /api/pay/google-pay is an endpoint on YOUR backend (example name).
// Do not call dpay directly from the browser because channelId is stored in the server configuration.
const response = await fetch(`/api/pay/google-pay`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
transactionId,
email: paymentData.email,
xPayToken,
deviceInfo,
}),
});

const result = await response.json();

if (!result.success) {
alert('Payment error: ' + result.message);
return;
}

// For Google Pay, the response always has redirectType: 'SUCCESS', or the payment is declined.
// Authorization, including 3DS, takes place in the customer's Google Pay wallet.
window.location.href = '/success';
}

Server (Node.js)—proxy to dpay.pl

app.post('/api/pay/google-pay', async (req, res) => {
const { transactionId, email, xPayToken, deviceInfo } = req.body;

const response = await axios.post(
`https://api-payments.dpay.pl/api/v1_0/cards/payment/${transactionId}/pay/google-pay`,
{
email,
channelId: process.env.DPAY_CARD_CHANNEL_ID,
xPayType: 'GOOGLE_PAY',
xPayToken,
deviceInfo,
}
);

res.json(response.data);
});

API response

Every response includes the success, status, and message fields. On success, message is a {redirectText, redirectType} object; on error, it is a text message.

3D Secure

With Google Pay, authorization (including a possible 3DS challenge) happens in the customer's Google wallet before the token is sent to dpay. For a successful transaction, the dpay endpoint always returns redirectType: "SUCCESS"; otherwise, it returns an error. It never returns FORM or an additional 3DS challenge.

Success—payment completed

{
"success": true,
"status": "success",
"message": {
"redirectText": "",
"redirectType": "SUCCESS"
}
}

Error

{
"success": false,
"status": "error",
"message": "Error during payment creation"
}

Testing in sandbox mode

In dpay.pl test mode, you do not need to configure a Google Pay sheet. Instead of a wallet token, pass one of the special test values in the xPayToken field:

TokenScenario
TEST_SUCCESSPayment completed successfully
TEST_SUCCESS_DELAYEDSuccess after a longer wait
TEST_DECLINETransaction declined
TEST_INSUFFICIENTInsufficient funds
TEST_TIMEOUTTimeout
TEST_ERRORSystem error

Example test request:

curl -X POST https://api-payments.dpay.pl/api/v1_0/cards/payment/{transactionId}/pay/google-pay \
-H "Content-Type: application/json" \
-d '{
"channelId": 31,
"xPayType": "GOOGLE_PAY",
"xPayToken": "TEST_SUCCESS",
"deviceInfo": {
"browserAcceptHeader": "application/json",
"browserJavaEnabled": "false",
"browserLanguage": "pl-PL",
"browserColorDepth": 24,
"browserScreenHeight": 1080,
"browserScreenWidth": 1920,
"browserTZ": 0,
"browserUserAgent": "Mozilla/5.0",
"systemFamily": "Win32",
"geoLocalization": "52.2297,21.0122",
"deviceID": "test-device",
"applicationName": "Netscape"
}
}'

The complete list of test tokens is available on the Test environment page.

Requirements
  • Your website must be available over HTTPS
  • You must have a verified Google Merchant ID (for production)
  • Your domain must be registered in the Google Pay & Wallet Console