Google Pay
Overview
Accept Google Pay with Forter in three steps:
- Configure the Google Pay button to tokenize with the forter gateway.
- Send the encrypted Google Pay token to the Forter Tokenization API. Forter returns Forter tokens.
- Send the Forter tokens to your PSP through the Detokenization Proxy.
Forter verifies and decrypts the Google Pay token inside its PCI environment. Your servers never see the card number or the cryptogram.
sequenceDiagram
participant B as Browser
participant G as Google Pay
participant M as Merchant backend
participant T as Forter Tokenization API
participant P as Forter Detokenization Proxy
participant S as PSP
B->>G: loadPaymentData()
G-->>B: encrypted payment token
B->>M: payment token
M->>T: POST /v1/wallet/tokenize-google-pay
T-->>M: googlePayDeviceDataToken, paymentCredentialsToken
M->>P: PSP request with placeholders + token headers
P->>S: PSP request with card data
S-->>M: authorization resultPrerequisites
- Forter Tokenization API credentials (site_id and site_secret). See Tokenization API.
- Detokenization Proxy set up, including Forter's CA certificate. See Detokenization Proxy.
- A Google Pay integration that follows Google's Google Pay API documentation, including the Google Pay & Wallet Console registration that Google requires before you go live.
Environments
Forter decides which Google environment a token belongs to from your Forter site, not from the token:
Google Pay environment | Forter site | Tokenization API base URL |
|---|---|---|
TEST | Sandbox (test) site | https://pci-tokenization-sandbox.checkouttools.com/v1/ |
PRODUCTION | Production site | https://pci.checkouttools.com/v1/ |
If the Google environment doesn't match the site type, the token is rejected with Invalid Google Pay token.
Step 1: Configure the Google Pay button
Use PAYMENT_GATEWAY tokenization with gateway forter. Set gatewayMerchantId to your Forter site_id, the same value you use as your Tokenization API username. If they don't match, Forter rejects the token.
const paymentDataRequest = {
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [
{
type: "CARD",
parameters: {
allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
allowedCardNetworks: ["VISA", "MASTERCARD", "AMEX", "DISCOVER"],
},
tokenizationSpecification: {
type: "PAYMENT_GATEWAY",
parameters: {
gateway: "forter",
gatewayMerchantId: "<your Forter site_id>",
},
},
},
],
merchantInfo: {
merchantName: "Example Merchant",
merchantId: "<your Google merchant ID>", // required by Google in PRODUCTION
},
transactionInfo: {
totalPriceStatus: "FINAL",
totalPrice: "10.00",
currencyCode: "USD",
},
};Forter supports the CARD payment method only, with the following auth methods:
Auth method | What Google returns |
|---|---|
CRYPTOGRAM_3DS | A device-bound token (DPAN) with a cryptogram and, in some cases, an ECI. |
PAN_ONLY | The card number saved to the shopper's Google account (FPAN), with no cryptogram. |
Step 2: Tokenize the Google Pay token
Never call this endpoint from the browser or a mobile app. Your site_secret must stay on your servers. Send the Google Pay token from the browser to your own backend, and call Forter from there.
In the browser, pass paymentMethodData.tokenizationData.token to your backend unchanged:
const paymentData = await paymentsClient.loadPaymentData(paymentDataRequest);
await fetch("/api/google-pay/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: paymentData.paymentMethodData.tokenizationData.token }),
});From your backend, call the Tokenization API with HTTP Basic authentication:
const res = await fetch("https://pci-tokenization-sandbox.checkouttools.com/v1/wallet/tokenize-google-pay", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Basic " + Buffer.from(`${SITE_ID}:${SITE_SECRET}`).toString("base64"),
},
body: JSON.stringify({
payload: { token: tokenFromBrowser },
}),
});
const tokens = await res.json();Request body
Field | Type | Required | Description |
|---|---|---|---|
payload.token | string or object | Yes | The value of paymentMethodData.tokenizationData.token. Send the string as-is (recommended). The parsed JSON object is also accepted. |
Response
200: CRYPTOGRAM_3DS
{
"googlePayDeviceDataToken": "<device data token>",
"paymentCredentialsToken": "<payment credentials token>"
}200: PAN_ONLY (no paymentCredentialsToken)
{
"googlePayDeviceDataToken": "<device data token>"
}Token | Contains | Lifetime |
|---|---|---|
googlePayDeviceDataToken | Card number (DPAN or FPAN), expiration date, auth method, card network | Same as a Forter multi-use token |
paymentCredentialsToken | Cryptogram and ECI (CRYPTOGRAM_3DS only) | 24 hours. Use it for a single authorization. |
Tokens are scoped to the site that created them. Use them only with the same site's credentials.
Step 3: Authorize through the Detokenization Proxy
Send your PSP request through the Detokenization Proxy. Add the Google Pay token headers and put placeholders where your PSP expects the card data. The proxy replaces the placeholders with the decrypted values before it forwards the request to your PSP.
Headers
Header | Value |
|---|---|
forter-google-pay-device-data-token | googlePayDeviceDataToken. Always required. |
forter-google-pay-payment-credentials-token | paymentCredentialsToken. Send it for CRYPTOGRAM_3DS only. |
Placeholders
Placeholder | Description |
|---|---|
{{google_pay_device_account_number}} | The card number: the DPAN for CRYPTOGRAM_3DS, or the FPAN for PAN_ONLY. |
{{google_pay_cryptogram}} | The cryptogram. Requires the payment credentials token. |
{{google_pay_eci}} | The ECI. Requires the payment credentials token. |
{{google_pay_expiration_m}} | The expiration month as a single-digit number (e.g., 3). |
{{google_pay_expiration_mm}} | The expiration month as a two-digit number (e.g., 03). |
{{google_pay_expiration_yy}} | The expiration year as a two-digit number (e.g., 28). |
{{google_pay_expiration_yyyy}} | The expiration year as a four-digit number (e.g., 2028). |
{{google_pay_auth_method}} | PAN_ONLY or CRYPTOGRAM_3DS. |
{{google_pay_card_network}} | The card network reported by Google (e.g., VISA). |
Example
The PSP endpoint and body below are illustrative. Use your PSP's API and field names.
// Trust Forter's proxy CA before the app starts:
// export NODE_EXTRA_CA_CERTS=[your CA certificate file path]
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const proxyAgent = new HttpsProxyAgent("https://pci-proxy-sandbox.checkouttools.com", {
headers: {
"proxy-authorization": `Basic ${Buffer.from(`${SITE_ID}:${SITE_SECRET}`).toString("base64")}`,
"forter-google-pay-device-data-token": tokens.googlePayDeviceDataToken,
// CRYPTOGRAM_3DS only
"forter-google-pay-payment-credentials-token": tokens.paymentCredentialsToken,
},
});
await axios.post(
"https://api.example-psp.com/v1/payments",
{
orderId: "123456",
amount: { value: 1000, currency: "USD" },
card: {
number: "{{google_pay_device_account_number}}",
expMonth: "{{google_pay_expiration_mm}}",
expYear: "{{google_pay_expiration_yyyy}}",
},
wallet: {
type: "GOOGLE_PAY",
cryptogram: "{{google_pay_cryptogram}}",
eci: "{{google_pay_eci}}",
},
},
{
httpsAgent: proxyAgent,
proxy: false,
headers: { Authorization: "Bearer <PSP API key>" },
},
);For PAN_ONLY, send only the forter-google-pay-device-data-token header and leave out {{google_pay_cryptogram}} and {{google_pay_eci}}.
Errors
Tokenization API
The Tokenization API returns HTTP 400 with { "message": "..." } when it rejects a request:
Message | Cause |
|---|---|
Invalid Google Pay token | Forter couldn't verify or decrypt the token, or the token is malformed. Check that you send tokenizationData.token unchanged and that the Google environment matches your site type. |
Unsupported Google Pay payment method | The payment method isn't CARD. |
Unsupported Google Pay auth method | The auth method isn't PAN_ONLY or CRYPTOGRAM_3DS. |
Google Pay token was issued for a different merchant | gatewayMerchantId doesn't match the site_id you authenticated with. |
Detokenization Proxy
Google Pay errors use the proxy's standard error status codes.
556: validation error
Message | Cause |
|---|---|
Google Pay requires device data token | The payment credentials header was sent without the device data header. |
Ambiguous token details: Google Pay tokens cannot be combined with other tokens | Google Pay headers were sent together with other Forter token or alias headers. |
Google Pay cryptogram placeholders require payment credentials token | The body uses {{google_pay_cryptogram}} or {{google_pay_eci}} without the payment credentials header. This always happens with PAN_ONLY. |
555: token not found
Message | Cause |
|---|---|
Google Pay device data token is required | No device data token header was sent. |
Google Pay device data token not found | The token doesn't exist, belongs to another site, or has expired. |
Google Pay payment credentials token not found | The token doesn't exist, belongs to another site, or is more than 24 hours old. |
Google Pay tokens are swapped: device data token and payment credentials token headers are reversed | The two token headers were swapped, or a payment credentials token was sent alone in the device data header. |
If a token is missing or expired, don't retry. Ask the shopper to pay with Google Pay again and tokenize the new token.