Skip to main content

Google Pay™ FAQ

Answers to the questions we hear most often about accepting Google Pay™ through Basis Theory.

Setup and Google-side configuration​

Do I need my own Google Pay™ merchant account?​

Yes, for production. Google requires a merchantId from the Google Pay & Wallet Console when the PaymentsClient runs with environment: 'PRODUCTION'. The ID appears in the console once you create your business profile, and production use also requires submitting your integration for review (Publish your integration). The merchantId is only required for a PRODUCTION client (Troubleshooting). Basis Theory does not register merchants or domains with Google on your behalf; both happen in the Google Pay & Wallet Console.

Do I need to register my merchant with Basis Theory?​

Not for the gateway integration described in Accept Google Pay™. Basis Theory only reads a merchant registration when a tokenization request includes merchant_registration_id; requests without it are decrypted with Basis Theory's managed keys, in Test and Production tenants alike. The Create Merchant Registration endpoint and the certificates uploaded under it exist for the own keys flow. A registration created while testing is harmless, but it does nothing until you reference it.

If you do bring your own keys, merchant_identifier must be the merchantId Google issued to you in the Google Pay & Wallet Console, exactly as shown there. The value is verified at your first tokenization request, where a mismatch returns 422.

Do I need a Google merchant ID for each merchant on my platform?​

Not necessarily; this is Google's decision. Every fully qualified domain that calls the Google Pay™ API must be submitted for approval individually, with no wildcards (Google Pay API FAQ). Google states that using a single merchant ID across multiple brands and platforms is supported (Google Pay API FAQ), and asks you to get in touch before submitting more than 50 fully qualified domains, subdomains included (Publish your integration). For supported payment processors, Google offers a hosted checkout solution so their clients skip individual onboarding; it is requested through your Google technical contact (Google Pay API FAQ).

On the Basis Theory side nothing changes: gatewayMerchantId is your tenant ID whether you serve one merchant or thousands, and merchant domains are registered with Google, not with Basis Theory.

What do I put in the tokenization specification?​

Use the gateway integration with Basis Theory as the gateway:

{
"type": "PAYMENT_GATEWAY",
"parameters": {
"gateway": "basistheory",
"gatewayMerchantId": "<YOUR_TENANT_ID>"
}
}

gatewayMerchantId is your Basis Theory tenant ID. It is a different value from merchantInfo.merchantId, which is the identifier Google assigns to your business. If you decrypt with your own keys instead, Google treats you as a DIRECT integration even though Basis Theory performs the decryption with your key: the specification becomes type: 'DIRECT' with protocolVersion: 'ECv2' and the publicKey you registered with Google, and has no gateway or gatewayMerchantId parameters (Payment data cryptography). See Decrypt Google Pay™ Data with Your Own Keys.

Does Google need my PCI attestation?​

Not for the gateway integration. With PAYMENT_GATEWAY and gateway: 'basistheory', Basis Theory holds the decryption keys, and Google asks for PCI documentation only from DIRECT integrations. If you bring your own keys, you are a DIRECT integration and Google's requirements apply to you: PCI DSS compliance, updated PCI documentation and annual encryption key rotation, because you receive payment card information directly (Payment data cryptography). Google's reference states: "To qualify, you must be Payments Card Industry Data Security Standard (PCI DSS) compliant, validated by a Qualified Security Assessor", and "Third parties that supply gateway or processing services on behalf of actual merchants aren't eligible to use the Direct integration" (Request objects). If you provide gateway or processing services to other merchants, use the gateway integration; Google reserves DIRECT for the merchant itself.

Why does Google's payment sheet return an OR_ error?​

Errors with an OR_ prefix are returned by Google's payment sheet. Google lists the codes in its Android Troubleshooting page; the Web Troubleshooting page documents OR_BIBED_15 and otherwise describes the same conditions as messages without codes.

  • OR_BIBED_11: Google defines it as the merchant not having completed registration to use the Google Pay™ API (Android Troubleshooting) and points to requesting production access (Web Troubleshooting). Check that merchantInfo.merchantId is the ID shown in the Google Pay & Wallet Console and that the integration serving the page has been approved for production (Publish your integration). Google's payment sheet never contacts Basis Theory, so nothing in your tenant causes or fixes this error.
  • Other OR_ codes on the Android page include OR_BIBED_06 for an unsupported gateway value or a test-only gateway used in production, and OR_BIBED_07 when, among other causes, no public key is registered for a DIRECT integration (Android Troubleshooting). OR_BIBED_15 means the payment sheet could not load: in an Android app because it uses a WebView (Android Troubleshooting), and on the web usually in non-Chromium browsers without Payment Handler support, or when a Cross-Origin-Opener-Policy header or a delay between the click and loadPaymentData() blocks the pop-up (Web Troubleshooting).
  • Request object errors: transactionInfo.totalPrice is always required, transactionInfo.countryCode is required for transactions processed in the European Economic Area and other regions subject to Strong Customer Authentication and is the country of the acquiring bank, and merchantInfo.merchantName is optional (Request objects).

Resolve these in the Google Pay & Wallet Console and your request objects.

What changes when I move to production?​

On the Google side, follow Publish your integration: get your integration approved, set merchantInfo.merchantId to the merchant ID from the console, and initialize PaymentsClient with environment: 'PRODUCTION'. On the Basis Theory side, switch to a Production tenant: create an application with google-pay:create in that tenant, send tokenization requests with its API key to api.basistheory.com instead of api.test.basistheory.com (Test Tenants), and set gatewayMerchantId to the Production tenant ID. Environment isolation comes from Google's signing keys: a PRODUCTION token cannot be processed by a Test tenant, and a TEST token cannot be processed by a Production tenant. No additional Basis Theory setup is required for the gateway integration. If you decrypt with your own keys, create the merchant registration and upload your certificates in the Production tenant as well.

Tokenization​

Why do I sometimes get a Token Intent and sometimes a Google Pay™ resource?​

The result depends on the authMethod of the card Google returned:

authMethodBasis Theory returnsWhat it holds
PAN_ONLYToken IntentThe funding card (FPAN), with expiration. No cryptogram.
CRYPTOGRAM_3DSGoogle Pay™ resourceA device token (DPAN) with a 3-D Secure cryptogram and, when present, an ECI indicator.

Google documents the two methods and their decrypted fields in Payment data cryptography. Your code must handle both shapes: read google_pay when present, otherwise token_intent. Each has its own id, retrieval endpoint, and proxy expression (google_pay: for the resource, token_intent: for the intent).

Why do desktop and iOS payments never return a device token?​

Device tokens (DPANs) are Android-specific, and desktop web and iOS fall back to PAN_ONLY (Google Pay API FAQ). Include both PAN_ONLY and CRYPTOGRAM_3DS in allowedAuthMethods.

Why does tokenization return 400 or 422?​

A 400 means the request could not be read, protocolVersion is not ECv2, or the decrypted card number or expiration failed validation. Send the contents of paymentData.paymentMethodData.tokenizationData.token as the value of google_payment_data. Google returns that token as a JSON string, so parse it before you build the request body instead of serializing the string a second time, and keep signedKey and signedMessage as the strings Google provided.

A 422 means the token was read but could not be verified or decrypted, has expired (its messageExpiration has passed), references a merchant registration without a valid certificate, decrypted to something other than a card, or uses the BasisTheory test protocol version from a Public application or a Production tenant (see Testing without a Google Pay™ token). A common cause is an environment mismatch: a token from Google's TEST environment must be sent to a Test tenant, and a PRODUCTION token to a Production tenant, because Basis Theory verifies the signature against Google's key set for that environment. A token signed for the other environment is reported as invalid or malformed.

Are the bin and last4 from the original card or the device token?​

It depends on the authMethod:

  • PAN_ONLY: the funding card is tokenized, so bin and last4 reflect the original card (FPAN).
  • CRYPTOGRAM_3DS: a device token is tokenized, so bin and last4 reflect the DPAN, not the original card. The FPAN is not part of the payload Google produces, so Basis Theory never receives it, and the original card's details, for example to match chargeback alerts, cannot be derived from the tokenized data. For display, read the card fields Google returns on your front end; see Can I get the cardholder name or billing address?

Can I get the cardholder name or billing address?​

Not from Basis Theory, which only decrypts the encrypted token. Google returns cardDetails (commonly the last four digits) and cardNetwork as plain fields in paymentMethodData.info, the billing address, including the cardholder's full name in its name field, when you set billingAddressRequired, and the customer's email on the payment response when you set emailRequired (CardInfo, PaymentData). Read those values on your front end.

Why don't I see Google Pay™ resources on the Portal's Tokens page?​

Google Pay™ resources created from CRYPTOGRAM_3DS payments are stored separately from Tokens, so they do not appear in the Portal's Tokens list. Store the id returned at tokenization and use Retrieve to read a resource later. To track resources as they are created, retrieved or deleted, subscribe to the google-pay.* webhook events. Token Intents created from PAN_ONLY payments follow the normal Token Intent lifecycle and become Tokens only when you convert them.

Which permissions do I need?​

OperationPermissionApplication type
Tokenize a paymentgoogle-pay:createPublic or Private
Retrieve with masked card datagoogle-pay:readPrivate
Retrieve with full card datagoogle-pay:revealPrivate
Manage merchant registrations and certificatesgoogle-pay:manageManagement
Delete a resourcegoogle-pay:deletePrivate

Token Intents created from PAN_ONLY payments use the Token Intent permissions.

Testing​

How do I test with Google's test cards?​

With environment: 'TEST', Google's payment sheet shows its test card suite; join the Google Pay test card suite group with the Google account on your test device to see it (Test card suite). Google states that its mock test cards cover PAN_ONLY, that device tokens are available only on Android devices, that production cards used in the test environment return placeholder data, and that tokens from test cards can produce errors at a processor. Send TEST tokens to a Basis Theory Test tenant on api.test.basistheory.com. To exercise the CRYPTOGRAM_3DS path, run the test card suite on an Android device, where Google returns device tokens, or let a Private application in a Test tenant create a resource with known values as described in Testing without a Google Pay™ token.

Charging​

Does a funding-card payment need 3DS or a CVV?​

You need 3DS where your market requires it, and there is no CVV to send. Google states that card payloads consisting of a PAN require 3-D Secure through your own or a PSP-provided solution, while tokenized payloads need no additional authentication (Google Pay API FAQ). The decrypted PAN_ONLY data contains the card number and expiration only; there is no CVV (Payment data cryptography). Basis Theory's 3DS accepts a token_intent_id of a card Token Intent, so you can authenticate the Token Intent before charging it.

How do I charge a device-token payment?​

For a CRYPTOGRAM_3DS result, forward the DPAN, expiration, cryptogram and ECI indicator to your processor's network-token or wallet fields through the Proxy, as shown in Processing the Google Pay™ Payment Data. The tokenization response does not include the cryptogram; the ECI indicator, when Google supplies one, is returned under details.eci_indicator. Both are available from Retrieve under authentication and through the google_pay: proxy expression.

Can I use Google Pay™ for subscriptions or other merchant-initiated payments?​

Yes. Google supports recurring billing, tied to the payment method it returns, when you follow the card networks' rules for merchant-initiated transactions and disclose the terms to the customer in your checkout (Google Pay API FAQ). For PAN_ONLY, convert the Token Intent to a Token before it expires and charge it as a stored card; the converted card token is eligible for Account Updater. For CRYPTOGRAM_3DS, store the resource and run later charges as merchant-initiated transactions on the DPAN without a cryptogram, through your processor's merchant-initiated flow. Basis Theory does not receive device-token lifecycle updates from Google, so a revoked or replaced device token is not reflected on the resource; treat a decline on a stored device token as a signal to collect the payment method again.

Why does charging a repeat customer fail with a 404 on the Token Intent?​

Token Intents expire after 24 hours by default, after which the Token Intent returns 404 and proxy expressions that reference it fail. If you want to charge a PAN_ONLY payment again later, convert the Token Intent to a Token before it expires.

Your own encryption keys​

Can Basis Theory decrypt with keys I already registered with Google?​

Yes. Register a merchant with your Google merchant ID, upload your private key as a password-protected PKCS#12 file, and pass merchant_registration_id on tokenization requests. Basis Theory stores up to two certificates per registration so you can rotate without downtime; delete one before uploading a third. In the Google payment request, use a DIRECT tokenization specification with protocolVersion: 'ECv2' and the publicKey registered with Google; there is no gatewayMerchantId. Follow Decrypt Google Pay™ Data with Your Own Keys. The managed gateway integration keeps working in the same tenant for requests without merchant_registration_id.

What am I responsible for when I bring my own keys?​

Google treats you as a DIRECT integration even though Basis Theory performs the decryption with your key: you must meet Google's PCI requirements (see Does Google need my PCI attestation?), rotate your encryption keys once a year and submit updated PCI documentation in the Google Pay & Wallet Console, and keep the old private key available for decryption for eight days after you remove the old public key (Payment data cryptography). In Basis Theory terms, upload the new key to your merchant registration before you remove the old public key from Google, and delete the old key from the registration only after those eight days; the registration holds two keys for this purpose. Basis Theory verifies a Test tenant's tokens against Google's test signing keys and a Production tenant's tokens against Google's production keys, so keep your Google environment and Basis Theory tenant aligned.