Set up Google Pay™ (API)

Configure Google Pay on your VINR account and integrate directly with the Google Pay JavaScript API.

View as MarkdownInstall skills

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 pathWhat to read instead
VINR hosted checkoutGoogle Pay in hosted checkout — no code required
Payment linksGoogle Pay in payment links — no code required
VINR ElementsGoogle Pay with Elements — minimal setup

Enable Google Pay in the DashboardAsk

  1. Go to Settings → Payment methods in the VINR Dashboard.
  2. 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:

FieldValueDescription
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.
gatewayMerchantIdyour VINR account IDIdentifies 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: { ... }
};
ParameterRecommendedDescription
billingAddressRequiredtrueRequest 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.phoneNumberRequiredtrueAlso request the customer's phone number. VINR sets this to true.
emailRequiredtrueRequest 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

Was this page helpful?
Edit on GitHub

Last updated on

On this page