Set up Google Pay™ (API)
Configure Google Pay on your VINR account and integrate directly with the Google Pay JavaScript API.
This page covers the direct API integration using the Google Pay JavaScript API in your own checkout UI. If you use a different integration path you may not need any of this code:
| Integration path | What to read instead |
|---|---|
| VINR hosted checkout | Google Pay in hosted checkout — no code required |
| Payment links | Google Pay in payment links — no code required |
| VINR Elements | Google Pay with Elements — minimal setup |
To use Google Pay, you must accept the Google Pay API Terms of Service and must comply with the Google Pay API Acceptable Use Policy. See also the Google Pay Web developer documentation, Web integration checklist, and Web Brand Guidelines.
Enable Google Pay in the DashboardAsk
- Go to Settings → Payment methods in the VINR Dashboard.
- Toggle Google Pay to enabled.
The integration below identifies you with two VINR values in the Google Pay request — the gateway ID vinrpay and your VINR account ID (see Tokenization specification). Your VINR secret key is needed only server-side, when you create the payment.
IntegrationAsk
1. Configure the payment request
Set allowedAuthMethods to the methods enabled on your VINR merchant account. Most accounts support both — see Authentication methods for what each method means and how to request a configuration change.
VINR supports Visa and Mastercard for Google Pay. Set allowedCardNetworks to ['MASTERCARD', 'VISA'] — other networks are not supported and including them causes the token to be rejected at checkout.
const googlePayClient = new google.payments.api.PaymentsClient({
environment: 'PRODUCTION', // use 'TEST' in sandbox
});
const paymentDataRequest = {
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ['CRYPTOGRAM_3DS', 'PAN_ONLY'], // match your merchant account config
allowedCardNetworks: ['MASTERCARD', 'VISA'], // match your enabled networks
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'vinrpay', // VINR's Google-registered gateway ID — constant
gatewayMerchantId: 'YOUR_VINR_ACCOUNT_ID', // your VINR account ID — not your API key
},
},
}],
merchantInfo: {
merchantName: 'Your Business Name',
},
transactionInfo: {
totalPriceStatus: 'FINAL',
totalPrice: '45.00',
currencyCode: 'EUR',
countryCode: 'BG',
},
};The request above is the minimal configuration. To also collect the billing address and customer email — which VINR includes with the payment — add the parameters shown under Billing address below.
Tokenization specification
The tokenizationSpecification object tells Google how to encrypt the payment token so that VINR can decrypt it. Set these values exactly:
| Field | Value | Description |
|---|---|---|
type | 'PAYMENT_GATEWAY' | Google encrypts the token for VINR (your gateway) to decrypt. Do not use 'DIRECT' — that requires merchant-side PCI DSS validation. |
gateway | 'vinrpay' | VINR's gateway ID, registered with Google. This is a constant — use it verbatim. |
gatewayMerchantId | your VINR account ID | Identifies which VINR merchant account receives the payment. Assigned by VINR and available in the Dashboard — this is not your API key. |
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'vinrpay',
gatewayMerchantId: 'YOUR_VINR_ACCOUNT_ID',
},
}Do not confuse gatewayMerchantId with merchantInfo.merchantId. gatewayMerchantId is your VINR account ID (assigned by VINR). merchantInfo.merchantId is your Google-assigned merchant ID — VINR provisions this for you during onboarding and you'll find it in the VINR Dashboard; it is required only in the PRODUCTION environment. Mixing up these two values is the most common cause of invalid_token errors in production — see the Go-live checklist.
2. Check readiness and render the button
Only render the button after isReadyToPay returns true. Call loadPaymentData synchronously in the click handler so the browser does not block the payment sheet as a pop-up.
googlePayClient.isReadyToPay({
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: paymentDataRequest.allowedPaymentMethods,
}).then(response => {
if (response.result) {
const button = googlePayClient.createButton({
onClick: () => googlePayClient.loadPaymentData(paymentDataRequest)
.then(paymentData => sendTokenToServer(paymentData))
.catch(err => {
if (err.statusCode !== 'CANCELED') {
document.getElementById('error-message').textContent = err.message || 'Payment failed';
}
}),
});
document.getElementById('google-pay-button').appendChild(button);
}
});3. Send the token to your server
Extract the encrypted token from paymentData.paymentMethodData.tokenizationData.token and POST it to your backend. As Google's documentation states, if you are using gateway tokenization, pass this token to your server without modification — do not decode, re-encode, strip, or log it.
async function sendTokenToServer(paymentData) {
// paymentData → paymentMethodData → tokenizationData → token
const token = paymentData.paymentMethodData.tokenizationData.token;
const response = await fetch('/your-checkout-endpoint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ googlePayToken: token, amount: 4500, currency: 'EUR' }),
});
if (!response.ok) {
const { message } = await response.json();
throw new Error(message || 'Payment failed');
}
return response.json();
}4. Submit the token to VINR
From your backend, submit the Google Pay token to a VINR payment intent. This is a two-step, server-to-server flow: create the intent, then process it with the encrypted token. Your X-Api-Key is sent only from your server, never the browser.
The base URL below is the sandbox API (https://edge.dev.briklabs.io). Switch to your VINR production API base when you go live. amount is in the currency's minor units (4500 = €45.00).
# 1. Create a payment intent — returns its id
curl --request POST \
--url https://edge.dev.briklabs.io/checkout/intent \
--header 'X-Api-Key: YOUR_VINR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"amount": 4500,
"currency": "EUR",
"customer": { "customerId": "cust_123", "email": "jane@example.com", "name": "Jane Doe" },
"configId": "YOUR_CHECKOUT_CONFIG_ID"
}'
# → { "id": "INTENT_ID", "amount": 4500, "currency": "EUR", ... }# 2. Process the intent with the Google Pay token — pass it unmodified
curl --request POST \
--url https://edge.dev.briklabs.io/checkout/intent/INTENT_ID/process \
--header 'X-Api-Key: YOUR_VINR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"paymentMethod": {
"type": "googlePay",
"googlePay": { "encryptedToken": "GOOGLE_PAY_TOKEN" }
},
"billingDetails": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+35988123456",
"address": {
"line1": "1 Vitosha Blvd",
"city": "Sofia",
"postalCode": "1000",
"country": "BG"
}
},
"contactInfo": { "email": "jane@example.com" }
}'GOOGLE_PAY_TOKEN is the value of paymentData.paymentMethodData.tokenizationData.token from Step 3 — sent through unaltered. VINR decrypts it, identifies the credential type (PAN_ONLY or CRYPTOGRAM_3DS), and applies the appropriate risk and 3DS handling automatically.
5. Handle the 3D Secure challenge (if required)
If the process response contains nextAction.type === "challenge", a 3D Secure step-up is required. This is expected for PAN_ONLY credentials — VINR routes them through its 3DS engine automatically (see Authentication methods).
When the shopper completes the challenge, the card issuer's ACS redirects their browser back to a VINR-hosted page — not a URL on your own domain. If you are integrating directly against the Google Pay API on your own checkout page (rather than using VINR's hosted checkout or Elements), you cannot currently host your own challenge-completion page or receive this redirect on your domain. Contact your VINR account manager before relying on this flow for a fully custom integration.
Once the challenge completes, confirm the payment with the threeDSServerTransID returned in nextAction:
curl --request POST \
--url https://edge.dev.briklabs.io/checkout/intent/INTENT_ID/confirm \
--header 'X-Api-Key: YOUR_VINR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{ "threeDSServerTransID": "VALUE_FROM_nextAction" }'Always confirm the final payment state from the payment.completed webhook on your server, not the client-side response — the customer's browser may close before the redirect returns.
Billing addressAsk
VINR's hosted checkout requests a full billing address (with phone number) and the customer's email, and we recommend you do the same so you can supply complete billing details when you submit the payment. Set billingAddressRequired: true with format: 'FULL' on the card parameters, and emailRequired: true at the top level of the request. For more details, see Google's BillingAddressParameters reference:
const paymentDataRequest = {
apiVersion: 2,
apiVersionMinor: 0,
emailRequired: true, // request the customer's email (top-level field)
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ['CRYPTOGRAM_3DS', 'PAN_ONLY'],
allowedCardNetworks: ['MASTERCARD', 'VISA'],
billingAddressRequired: true,
billingAddressParameters: {
format: 'FULL', // 'FULL' (full street address) or 'MIN' (name, country, postal code)
phoneNumberRequired: true,
},
},
// tokenizationSpecification: { ... } // see Tokenization specification above
}],
// merchantInfo, transactionInfo: { ... }
};| Parameter | Recommended | Description |
|---|---|---|
billingAddressRequired | true | Request a billing address. VINR's checkout sets this to true. |
billingAddressParameters.format | 'FULL' | 'FULL' returns the full street address; 'MIN' returns only name, country code, and postal code. VINR uses 'FULL'. |
billingAddressParameters.phoneNumberRequired | true | Also request the customer's phone number. VINR sets this to true. |
emailRequired | true | Request the customer's email. Set on the PaymentDataRequest itself — not inside billingAddressParameters. |
When these are set, the billing address is returned on the Google Pay response at paymentData.paymentMethodData.info.billingAddress and the email at paymentData.email. Pass these along as the billing details when you submit the payment to VINR.
Button guidelinesAsk
Google enforces brand guidelines for the payment button. Use only the approved button styles and do not modify the Google Pay logo. The createButton API returns a pre-styled, compliant button automatically. See Button guidelines and the Google Pay Web Brand Guidelines.
See alsoAsk
Authentication methods
CRYPTOGRAM_3DS vs PAN_ONLY: how VINR handles each and per-merchant configuration.
Test & go live
Test your integration and submit for production approval.
Google Pay overview
How Google Pay works with VINR.
Last updated on