Google Pay™

In A Nutshell
In a nutshell

Allow customers to securely make payments using Google Pay on Android devices and most browsers.

Google Pay compliance

By enabling Google Pay on your integration, you agree that all transactions processed through Paystack comply with the Google Pay and Wallet API Acceptable Use Policy and the Google Pay API Terms of Service. If you display Google Pay branding on your own surfaces, use only approved assets that comply with the Google Pay Web brand guidelines.

Google Pay is available on most browsers (Chrome, Microsoft Edge, Brave, Safari, and Firefox) across desktop and Android. Paystack currently supports Google Pay for web merchants only, including on Android devices via Chromium browsers.

Paystack accepts two Google Pay authorization methods, both enabled by default. Here are the major distinctions between the two:

  • CRYPTOGRAM_3DS: the card is already device-tokenized and authenticated via the phone's biometrics (fingerprint/face). Card networks treat that on-device authentication as equivalent to running 3DS, so Paystack doesn't need to run a separate 3DS challenge.
  • PAN_ONLY: the card is just a stored card number with no device-level authentication behind it, so there's no built-in equivalent. Paystack runs an explicit 3DS step-up on every one of these charges.

For cards issued in Nigeria, Ghana, Kenya and CIV, they use PAN_ONLY. South Africa cards can use both. When the sheet loads, Paystack prioritises CRYPTOGRAM_3DS for Android and Chromium, and falls back to PAN_ONLY everywhere else. Paystack configures this list, known as Google Pay's allowedCardNetworks, directly. Merchants don't set it themselves. Visa and Mastercard are the only networks currently supported.

Google Pay web resources

For a deeper technical reference, see the Google Pay Web developer documentation. Before going live, review the Google Pay Web integration checklist and brand guidelines.

Activating Google Pay

You can configure the Google Pay channel for your web app on the Paystack Dashboard.

Go to the Payments settings page and check the Google Pay option under Accept payments via.

Image of the Payments settings page on Paystack Canvas, showing the checkbox to activate Google Pay
Card channel required

Leave Card enabled alongside Google Pay. Google Pay runs on the card channel, on the checkout.

If you use Invoices, Payment Pages, Storefronts or any plugin that redirects customers from your site for payment, Google Pay becomes available once enabled.

Setting up on Popup

Compatibility

Google Pay works on version 2 of our InlineJS only. If you are using version 1 follow this migration guide before proceeding.

There are two ways to set up Google Pay in your frontend app:

  1. Using the checkout modal
  2. Mounting a payment request button

Using the checkout modal

This method doesn't require any additional HTML elements, since Paystack does the heavy lifting for you. Tie your payment button to the checkout() method:

1const paystackPop = new PaystackPop();
2
3async function payWithPaystack() {
4 await paystackPop.checkout({
5 key: 'pk_domain_xxxxx',
6 email: 'example@email.com',
7 amount: 10000,
8 onSuccess: (transaction) => {
9 console.log('Transaction: ', transaction)
10 },
11 onCancel: () => {
12 console.log('Pop up closed!')
13 }
14 })
15}

The checkout method detects whether the customer's browser supports Google Pay. If it does, Paystack surfaces the Google Pay button automatically in the card section of the Checkout as shown below:

Image of checkout on mobile, showing the Google Pay button

Mounting a payment request button

This method lets you place the Google Pay button on your own page, in line with your design. Apple Pay mounts into the same container, so a customer gets whichever wallet their device supports.

Compatibility

The payment request button requires @paystack/inline-js version 2.26.0 or later. If you load InlineJS via CDN, you already have this. If you installed it with a package manager such as npm, yarn, or pnpm, upgrade before you start.

Mounting the button is a four-step process:

  1. Set up your Google Pay merchant profile
  2. Add your merchant details to the Dashboard
  3. Create a container
  4. Set up the payment request

Set up your Google Pay merchant profile

Google validates the origin serving the button against a registered merchant profile. The Checkout runs on Paystack's profile, but a button on your own domain needs yours, so set one up before you go any further.

Follow Google's official guides to create and publish your integration:

  1. Set up your Google Pay integration: create your Google Pay & Wallet Console account and configure your integration. Aim for a WEB and GATEWAY integration.
  2. Publish your integration: move your integration out of TEST and into PRODUCTION so it can process real transactions.

Add your merchant details to the Dashboard

Once Google approves your integration, hand Paystack the details of the profile you just created. Go to the Developers page on the Paystack Dashboard, open the Google Pay tab and click Add merchant details.

Image of the Google Pay tab on the Paystack Developers page, showing the button to add merchant details

Fill the form with the values from your Google Pay & Wallet Console:

  • Merchant ID: your production Google Pay merchant identifier, a 15-16 character string.
  • Merchant name: the business name that appears on the Google Pay & Wallet Console.
  • Website domain: the domain you registered with Google, and the domain that serves the button. These have to be the same.
Image of the modal to add Google Pay merchant details, showing the merchant ID, merchant name and website domain fields

Paystack passes these to the Google Pay SDK when it mounts the button, so there's nothing further to configure in your code. They only apply to buttons you render yourself, and don't affect payments through the Paystack Checkout.

Create a container

Add the HTML tags that hold the wallet buttons, as well as the button to load other payment options:

1<!-- Wallet buttons, styles and event listeners will be injected to this div -->
2<div id="paystack-wallet-buttons"></div>
3<button id="paystack-other-channels">More payment options</button>

Use a div tag with a unique id for the container. The preceding snippet uses paystack-wallet-buttons, but you can use any name you prefer. This id is what you pass to the paymentRequest() method.

Set up the payment request

Pass the container id and the id for the other channels to the paymentRequest() method:

1const paystackPop = new PaystackPop();
2
3await paystackPop.paymentRequest({
4 key: 'pk_domain_xxxxx', // Replace with your public key
5 email: 'example@email.com',
6 amount: 10000,
7 currency: 'NGN',
8 channels: ['google_pay'],
9 container: 'paystack-wallet-buttons', // ID of div to mount payment button elements
10 loadPaystackCheckoutButton: 'paystack-other-channels', // ID of button to trigger opening Paystack checkout (optional)
11 styles: {
12 theme: 'dark',
13 googlePay: {
14 height: '50px',
15 borderRadius: '3px',
16 buttonType: 'pay'
17 }
18 }, // custom styles for button elements
19 onSuccess(transaction) {
20 console.log('Transaction: ', transaction)
21 },
22 onError(error) {
23 console.log('Error: ', error)
24 },
25 onCancel() {
26 console.log('Payment cancelled!')
27 },
28 onElementsMount(elements) { // { applePay: Boolean, googlePay: Boolean } or null
29 if (elements && elements.googlePay) {
30 document.querySelector('#paystack-other-channels').innerText = 'More payment options'
31 }
32 }
33});

See paymentRequest(options) in the InlineJS reference for the full list of styling options.

Authorization methods on your own domain

The payment request button only offers CRYPTOGRAM_3DS. PAN_ONLY isn't available on your own domain.

The button only renders when all of the following hold:

  • Your page is served over HTTPS from the same domain as the Website domain saved on your Dashboard. A mismatch is the most common reason the button goes missing.
  • google_pay is listed in channels alongside card. On its own, the transaction won't initialize.
  • The customer's card is stored as an Android device token, which in practice means an Android device with a card saved to Google Wallet.

Building a custom Google Pay checkout

Prerequisites

This option needs the same Google Pay merchant profile as the payment request button, so set that up first. You can skip adding the details to the Dashboard, since you pass them in your own code rather than having Paystack pass them for you.

Take this route if you want Google Pay on your own website and need both authorization methods, CRYPTOGRAM_3DS and PAN_ONLY. The payment request button only offers CRYPTOGRAM_3DS. Driving the Google Pay SDK yourself also reaches customers whose cards are saved to a Google Account but not device-tokenized, the PAN_ONLY case.

In exchange, you build the PaymentDataRequest, charge the token yourself, and render the 3DS step-up that PAN_ONLY charges return.

Use the following from the Google Pay & Wallet Console in the merchantInfo object when you initiate checkout:

  • merchantId: your production Google Pay merchant identifier (typically a 15-16 character string, for example BCR2DN7T...). Visible on your Google Pay & Wallet Console.
  • merchantName: the business name that appears on the Google Pay & Wallet Console.
  • merchantOrigin: the origin for your web integration as registered with Google.
Request parameters

Ensure your PaymentDataRequest supplied to Google Pay conforms to the parameters shown in the code snippet below.

Using Google Pay SDK

When using the Google Pay SDK, you build the PaymentDataRequest with the following defaults:

1{
2 "apiVersion": 2,
3 "apiVersionMinor": 0,
4 "allowedPaymentMethods": [{
5 "type": "CARD",
6 "parameters": {
7 "allowedAuthMethods": ["CRYPTOGRAM_3DS", "PAN_ONLY"],
8 "allowedCardNetworks": ["VISA", "MASTERCARD"],
9 "billingAddressRequired": true,
10 "billingAddressParameters": {
11 "format": "FULL",
12 "phoneNumberRequired": false
13 },
14 "assuranceDetailsRequired": true
15 },
16 "tokenizationSpecification": {
17 "type": "PAYMENT_GATEWAY",
18 "parameters": {
19 "gateway": "paystack",
20 "gatewayMerchantId": "YOUR_PAYSTACK_INTEGRATION_ID"
21 }
22 }
23 }],
24 "merchantInfo": {
25 "merchantName": "YOUR_BUSINESS_NAME",
26 "merchantId": "BCR2DN7TTCZK3ED6",
27 "merchantOrigin": "www.business-website.com"
28 }
29}

Key values you should consider:

  • tokenizationSpecification.parameters.gateway: Paystack's registered Google Pay gateway identifier.
  • tokenizationSpecification.parameters.gatewayMerchantId: your Paystack integration id from your dashboard.
  • allowedAuthMethods: ['CRYPTOGRAM_3DS', 'PAN_ONLY']: both are enabled together so Paystack can serve every browser.
  • allowedCardNetworks: ['VISA', 'MASTERCARD']: the card networks Paystack currently processes for Google Pay.
  • billingAddressRequired: true: Paystack requires a full billing address (street, city, region, postcode, country) on every Google Pay charge. Phone number is not required. See the Google reference for the BillingAddressParameters shape.
  • assuranceDetailsRequired: true: ensures Google Pay returns the cardHolderAuthenticated signal on the payment, which drives Paystack's downstream 3DS decision on PAN_ONLY tokens.

Charging a token

With your integration approved and the Google Pay button on your website, customers can interact with the button and select their preferred card. Google Pay then encrypts those card details into a token, which it forwards to Paystack (as the gateway selected under tokenizationSpecification) to decrypt and charge.

Charging an existing token uses the Google Pay Charge endpoint (googlepay/charge), but most integrations should route through Paystack's checkout instead. This section documents the endpoint for completeness.

Send the payload as application/x-www-form-urlencoded:

FieldRequiredNotes
transactionYesPaystack transaction id from Initialize TransactionAPI.
paymentObjectYesThe full paymentData object returned by loadPaymentData(), JSON-encoded as a single form value.
deviceNoDevice fingerprint, if you collect one.

The response follows Paystack's standard charge response structure. The list below shows the expected value of status and the meaning:

  • success: Paystack authorizes the charge inline. Typical for CRYPTOGRAM_3DS.
  • auth: the charge requires a 3DS step-up. Typical for PAN_ONLY. Open data.otpmessage in an iframe and subscribe to the Pusher channel 3DS_<transactionId>, event response, for the final result.
  • failed: the card issuer declined the charge, or Paystack rejected the token. message carries a customer-safe reason.

Recurring transactions

Once Paystack authorizes a Google Pay charge, you can process subsequent merchant-initiated charges (Subscriptions, Recurring Charges) against the resulting authorization code, similar to recurring card charges. See Recurring Charges for the full flow.

Refunds

Google Pay refunds work identically to card refunds. Paystack supports partial refunds. See Refunds for how to create and manage a refund.

Troubleshooting

If you experience any issues with your Google Pay integration, ensure there wasn't an oversight during setup:

  • Your server must serve all requests via HTTPS in production
  • Google Pay is enabled on your integration under the Preferences page
  • If you render the button on your own domain, your Google Pay merchant details are saved under Google Pay on the Developers page

If all checks out and you are still having issues with your Google Pay integration, here are some possible errors and resolutions you can try out:

ErrorResolution
Merchant's Category not supported for Google PayFor compliance reasons, Paystack allows only specific business categories to use Google Pay. Please reach out to support@paystack.com for more information
Invalid Google Payment Data ReceivedThe paymentObject sent to /googlepay/charge is missing required fields or has malformed data. Escalate this to techsupport@paystack.com with the payload sent to this endpoint.
DEVELOPER_ERROR or MERCHANT_ACCOUNT_ERROR from the Google Pay SDKGoogle rejected the merchant identity behind the button. Confirm your integration is published in the Google Pay & Wallet Console, and that the Website domain you saved on the Dashboard is the domain serving the page.
Merchant identifier mismatchThe gatewayMerchantId embedded in the Google Pay token doesn't match the Paystack integration id on the transaction. Confirm you generated both from the same Paystack integration.
An error occurred while processing requestGeneric failure, Paystack failed to decrypt the token or the transaction lifecycle hit an internal error. Retry the charge; if the issue persists, contact Paystack Support with the transaction reference.