Decrypt Google Pay™ Data with Your Own Keys
While our managed certificates offer the fastest integration path for new merchants, you may prefer to manage your own configuration—particularly if you are migrating an established Google Pay™ setup. Choosing to bring your own processing keys, rather than relying on our default managed encryption, ensures seamless continuity with your existing cryptographic assets.
By managing your own keys with Basis Theory, you retain full control over the decryption and tokenization of Google Pay™ payment data. This "Bring Your Own Key" approach allows you to align your integration with Google’s recommended security model while maintaining the flexibility to own your data and switch processors without friction.
This guide demonstrates how to generate, configure, and use your own Google Pay™ encryption keys to securely decrypt and tokenize payment data.
Getting Started
To get started, you will need to create a Basis Theory Account and a TEST Tenant.
Understanding Google Pay™ Encryption
Unlike standard card processing, Google Pay™ encrypts payment data on the device before it reaches your server. To decrypt this data, you need a private key that corresponds to a public key registered with Google.
- Merchant Onboarding: You generate a public/private key pair and provide the public key to Google.
- Encryption: When a customer pays, Google encrypts the data using your public key.
- Decryption: You use the corresponding private key—configured in Basis Theory—to decrypt and securely tokenize the data.
To follow this guide, you will need:
- Google Pay™ Merchant Account: You must be registered as a merchant with Google.
- Local Private Key: You should already have a public key registered with Google Pay™ and the corresponding private key available locally.
Implementation: Preparing Your Keys
Basis Theory requires your keys to be in a specific format to securely process them. You must convert your private key into a password-protected, Base64-encoded PKCS#12 (.p12) file.
The following steps assume your private key is currently available as a Base64-encoded DER (PKCS#8) key.
1. Ensure the Private Key Is in PEM Format
If your private key is in PKCS#8 DER (Base64) format, you must first decode it and convert it to PEM format.
Run the following commands to decode and convert the key:
# Decode the Base64 key
base64 -D -i privateKey.der.b64 -o privateKey.der
# Convert from DER to PEM
openssl pkcs8 \
-inform DER \
-outform PEM \
-in privateKey.der \
-nocrypt \
-out privateKey.pem
Verify the key is correct by checking for the ASN1 OID:
openssl ec -in privateKey.pem -text -noout | grep ASN1
2. Create an X.509 Certificate Google Pay™ requires an X.509 certificate cryptographically bound to your private key.
Note: This guide uses a self-signed certificate as an example, but Google Pay™ accepts any valid X.509 certificate properly associated with your private key.
Generate the certificate using your private key:
openssl req -new -x509 \
-key privateKey.pem \
-out certificate.pem \
-days 3650 \
-subj "/C=US/O=Google Pay/CN=Payment Processor"
3. Create an Encrypted PKCS#12 File
Combine your private key and certificate into a single PKCS#12 archive. You must use encryption settings compatible with both Google Pay™ and Basis Theory (AES-256-CBC with PBKDF2).
openssl pkcs12 -export \
-inkey privateKey.pem \
-in certificate.pem \
-out googlepay.p12 \
-name "googlepay-processor" \
-certpbe AES-256-CBC \
-keypbe AES-256-CBC \
-macalg SHA256 \
-iter 2048
Important: When prompted, enter a strong password. You will need to provide this password to Basis Theory to allow the platform to decrypt the certificate data.
4. Base64 Encode the File
Finally, encode the .p12 file into a single-line Base64 string to prepare it for the API
base64 -i googlepay.p12 | tr -d '\n' > googlepay.p12.base64
5. Upload to Basis Theory Once you have the encoded string and your password:
- Create a Google Pay™ merchant registration via the Basis Theory API.
- Upload the
googlepay.p12.base64content as the merchant_certificate. - Provide the password used to protect the
.p12file.
5.1 Create your merchant registration
A merchant represents your Google Pay™ merchant identifier and serves as the root configuration for certificates and tokenization.
Request
- cURL
- Node
- C#
- Python
curl --request POST \
--url https://api.basistheory.com/google-pay/merchant-registration \
--header 'BT-API-KEY: <API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"merchant_identifier": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}'
await client.googlePay.merchant.create();
await client.GooglePay.Merchant.CreateAsync(new GooglePayMerchantRegisterRequest());
client.google_pay.merchant.create()
5.2 Upload your merchant registration certificates
Once a merchant is registered, merchant-owned encryption certificates can be associated with it and will be used to decrypt and tokenize Google Pay™ payment data during tokenization requests.
Request
- cURL
- Node
- C#
- Python
curl --request POST \
--url https://api.basistheory.com/google-pay/merchant-registration/3c367ed4-678d-4b98-9cec-d7eaa0f0c26e/certificates \
--header 'BT-API-KEY: <API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"merchant_certificate_data": "MIIHgjCCBmqgAwIBAgIIZ... (Base64 encoded .p12)",
"merchant_certificate_password": "super_secure_password_123!"
}'
await client.googlePay.merchant.certificates.create("merchantId", request: GooglePayMerchantCertificatesRegisterRequest = {})
await client.GooglePay.Merchant.Certificates.CreateAsync("merchantId",
new GooglePayMerchantCertificatesRegisterRequest()
);
client.client.google_pay.merchant.certificates.create(
merchant_id="merchantId",
merchant_certificate_data=""
)
Request Parameters
| Attribute | Required | Description |
|---|---|---|
merchant_certificate_data | true | A base64-encoded, encrypted P12 file containing both the certificate and the private key used to encrypt payment data for the merchant. |
merchant_certificate_password | true | The password used to decrypt the merchant_certificate_data. AES-256-CBC with PBKDF2 is used to decrypt the certificate data. |
Detailed API steps for this upload can be found in the Google Pay™ API documentation.
Usage: Decrypting Tokens
Once your keys are registered, you must explicitly tell Basis Theory to use them during transactions.
If you haven't already set up the Google Pay™ button on your site, follow the Rendering the Google Pay Button section first, then return here to decrypt and tokenize payment data with your own encryption keys.
Tokenization
When the user completes a payment and you receive the encrypted payload from Google, pass the merchant_registration_id with your tokenization request.
Basis Theory will use the corresponding private key stored in your registration to decrypt the payment data using AES-256-CBC encryption and tokenize it.
Request
- cURL
- Node
- C#
- Python
curl --request POST \
--url https://api.basistheory.com/google-pay \
--header 'BT-API-KEY: <API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"expires_at": "2030-12-25T23:59:59Z",
"google_payment_data": {
"protocolVersion": "ECv2",
"signature": "MEQCIH6Q4... (Base64 signature)",
"intermediateSigningKey": {
"signedKey": "{\"keyValue\":\"MFkwE...\",\"keyExpiration\":\"1600000000000\"}",
"signatures": [
"MEYCIQ... (Base64 signature 1)",
"MEUCIQ... (Base64 signature 2)"
]
},
"signedMessage": "{\"encryptedMessage\": \"Zw7p...\", \"ephemeralPublicKey\": \"BKk...\", \"tag\": \"A3c...\"}"
},
"merchant_registration_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}'
await client.googlePay.create();
await client.GooglePay.CreateAsync(new GooglePayCreateRequest());
client.google_pay.create()
Request Parameters
| Attribute | Required | Description |
|---|---|---|
expires_at | false | An optional expiration date for the token. If blank, no expiration date is set for the token. |
google_payment_data | true | The Google Pay™ resource. |
merchant_registration_id | false | The unique identifier of the merchant registration created through the Basis Theory Merchant API. |
Detailed API steps for tokenization can be found in the Google Pay™ API documentation.
Preparing for Production
This checklist will guide you through the critical steps required to move your Google Pay™ integration into production. Since you are using a Direct integration (managing your own Google Pay™ Merchant ID and encryption keys), you must complete specific verification steps directly with Google before you can process live payments.
Request Production Access from Google
Unlike the test environment, you cannot simply switch a flag to go live. You must be explicitly approved by Google.
-
Complete your Business Profile: Ensure all details in the Google Pay™ & Wallet Console are accurate.
-
Submit for Approval: Navigate to the "Integration" tab in the Google Console and submit your integration for review. You will likely need to provide:
- Screenshots of your buy flow.
- A list of the domains where the Google Pay™ button will appear.
- Wait for "Production" Status: Do not attempt to process real payments until your status in the Google Console changes from "Test" to "Production."
Update Your Client Configuration
Once approved, you must update your frontend (Web or Android) configuration to reflect your live credentials.
- Environment: Change the environment from TEST to PRODUCTION.
- Merchant ID: Update the merchantInfo.merchantId field with your production Google Merchant ID.
- Gateway Parameters: Ensure your gatewayMerchantId matches the Basis Theory
merchant_registration_idthat corresponds to your production keys.
Establish a Key Rotation Plan
Because you are managing your own encryption keys for a Direct integration, you are responsible for key rotation.
- Google's Requirement: Google recommends rotating your encryption keys at least annually.
- No Downtime: You can register multiple active keys with Google and Basis Theory simultaneously. We recommend adding a new key before removing the old one to ensure zero downtime during the transition.
Test with a Real or Test Card
Before processing live customer data, verify your integration end-to-end.
-
Test Cards: Google Pay™ provides a suite of test card numbers that allow you to simulate various transaction scenarios in their test environment. In case you want to whitelist a test card please contact Basis Theory's support team on our Community or via email at support@basistheory.com to have the card added to your Tenant.
-
Real Transactions: For final production verification, we recommend performing a low-value transaction using a real credit card saved in your Google Wallet to ensure the decryption flow works with live keys.
-
Verify Decryption: Ensure that Basis Theory successfully decrypts the payload using your registered private key and returns a tokenized resource.
Final Notes
Integration Type & Compliance
By bringing your own keys, you are effectively using a Direct integration model with Google Pay. While Basis Theory handles the heavy lifting of PCI-compliant decryption and storage, Google views you as the entity responsible for the encryption keys. Ensure you maintain compliance with Google's Acceptable Use Policy and branding guidelines.
Troubleshooting
If you receive decryption errors in production:
- Check Key Mismatches: Ensure the public key you uploaded to the Google Pay™ Console matches the private key you uploaded to the Basis Theory Merchant Registration.
- Verify Merchant Registration ID: Confirm that the
merchant_registration_idpassed in your payload matches exactly what is registered in the Google Console. - Google Pay™ button configuration: Not all cards in your users' wallets may be compatible with the card networks and authentication methods you configure for the Google Pay™ button — only cards matching your configuration will be available for selection, and users will receive an error if none of their cards are supported.
If you encounter issues specific to key importation or decryption, don't hesitate to contact Basis Theory's support team on our Community or via email at support@basistheory.com
By following this checklist, you will ensure a secure and compliant launch for your custom Google Pay™ integration.