> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.paymentkit.com/guides/integration/sdk-reference/payment-kit-js/google-pay/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.paymentkit.com/_mcp/server. # Google Pay Google Pay lets customers pay using cards saved to their Google account with a single tap. # Prerequisites PaymentKit.js checks Google Pay availability **automatically** when it initializes — there's no manual prepare step. You reveal your button once the SDK reports it's ready (see [Show the express button](#show-the-express-button)), and the customer's tap submits the payment. PaymentKit.js routes Google Pay through whichever processor your account has configured, and each processor relies on a different browser library. PaymentKit does **not** inject these scripts for you—add the one matching your processor (or both, if you're unsure which one the backend will select). > **Info** > > Google Pay readiness only succeeds when the checkout session's account has an **express-checkout processor** configured with Google Pay enabled. If none is configured, the SDK stays in the not-ready state and your `onGooglePayReady` callback reports `false` — so your button never appears. #### Stripe processor Add Stripe.js to your page. Google Pay rides Stripe's Payment Request API: ```html ``` #### Airwallex processor Add Google's Pay API script. The Airwallex flow uses `window.google.payments.api` directly: ```html ``` > **Warning** > > The processor is selected by the backend, so if your account can route to either processor, include **both** scripts. Loading only Stripe.js will cause Google Pay to fail on Airwallex processors with `Google Pay API not loaded`. > **Warning** > > **Airwallex processors must also have Google Pay activated in your Airwallex dashboard.** Enabling Google Pay in your PaymentKit dashboard alone is **not** enough — Google Pay must be enabled as a payment method on your Airwallex account before it can be tested or charged. If it isn't activated on the Airwallex side, the Google Pay sheet will fail to complete even when your PaymentKit configuration and page scripts are correct. # Setup #### CDN ```html ``` #### NPM/ES Modules ```typescript import PaymentKit from '@payment-kit-js/vanilla'; import GooglePayPaymentMethod from '@payment-kit-js/vanilla/payment-methods/google-pay'; const paymentKit = PaymentKit({ environment: 'production', secureToken: 'your_secure_token', paymentMethods: [GooglePayPaymentMethod] }); ``` ## Choose the wallet processor By default the SDK auto-selects your account's Google Pay express-checkout processor. If you have **more than one account** (Stripe or Airwallex) and want a specific one to handle Google Pay, pass `processorIds` when you construct PaymentKit — a map of payment method to processor id. The SDK then mints **and** charges Google Pay on the exact account you name (Stripe PaymentMethods are account-scoped, so mint and charge must stay on the same account — this keeps them aligned). Pass **ids only**; the processor family (Stripe/Airwallex) is resolved from your account. Apple Pay and Google Pay are set **independently** — use the `googlePay` key here: ```typescript import PaymentKit from '@payment-kit-js/vanilla'; import GooglePayPaymentMethod from '@payment-kit-js/vanilla/payment-methods/google-pay'; const paymentKit = PaymentKit({ environment: 'production', secureToken: 'your_secure_token', paymentMethods: [GooglePayPaymentMethod], processorIds: { googlePay: 'proc_prod_1e769fc8bf77493c', // EU account }, }); ``` `processorIds` is read once, when PaymentKit is constructed, and applies for that instance's lifetime. To steer Google Pay per checkout — e.g. the EU account for EU shoppers, the US account for US shoppers — compute the id and pass it when you initialize PaymentKit **for that session**. A single instance reused across checkouts keeps its original value until you re-init. ```typescript const paymentKit = PaymentKit({ environment: 'production', secureToken: 'your_secure_token', paymentMethods: [GooglePayPaymentMethod], processorIds: { googlePay: isEuShopper ? 'proc_prod_1e769fc8bf77493c' // EU account : 'proc_prod_53cd0b7dbdc4449e', // US account }, }); ``` > **Info** > > Leave `googlePay` out of `processorIds` (or omit `processorIds` entirely) to keep the automatic express-checkout selection. The processor **family** (Stripe or Airwallex) is resolved from your account — the SDK looks the pinned id up in the account's wallet processors — so pinning an **Airwallex** processor routes through the Airwallex flow automatically, with no type field to set. If the pinned id isn't one of the account's Google-Pay-eligible processors for the session, Google Pay simply stays unavailable (`onGooglePayReady` stays `false`) rather than failing mid-payment. # Show the express button The SDK checks Google Pay availability **automatically** when it initializes. Use `onGooglePayReady` to show or hide your express button, and `notifyAmountChanged` to re-prepare whenever the amount changes. ## React to readiness Register a callback with `onGooglePayReady`. It fires immediately with the current state, then again on every change. Register as many callbacks as you need — none are overwritten. ```typescript paymentKit.google_pay.onGooglePayReady((isReady) => { googlePayButton.hidden = !isReady; }); ``` While the SDK is re-preparing (see below), it reports `isReady: false`, then `true` again once it's ready — so the same callback naturally hides the button during the gap. ## Re-prepare after the amount changes Whenever the cart total changes — a coupon is applied, quantity is updated, shipping is added — call `notifyAmountChanged()` so the SDK clears the stale session and prepares a fresh one with the new amount. It returns a promise that resolves once Google Pay is ready again. ```typescript await paymentKit.google_pay.notifyAmountChanged(); ``` Your `onGooglePayReady` callback fires across the re-prepare (`false` while in flight, then `true`), so the button hides and reappears on its own. Calling it again while a prepare is already running coalesces the calls — the promise resolves once the latest prepare completes. > **Info** > > `onGooglePayReady` and `notifyAmountChanged` are methods on `paymentKit.google_pay`. # Submit payment Attach `submit` to the same button you reveal with `onGooglePayReady`. In the auto-prepare flow the SDK fills the processor from the checkout session, and Google Pay collects the payer's details from the sheet — so you don't pass `processorId`. ```typescript googlePayButton.addEventListener('click', () => { paymentKit.submit({ fields: {}, paymentMethod: 'google_pay', options: { customerInfo: { first_name: 'Jane', last_name: 'Smith' } }, onSuccess: (result) => { console.log('Transaction ID:', result.id); console.log('Checkout Session:', result.checkoutSessionId); window.location.href = '/success'; }, onError: (errors) => { if (errors.google_pay === 'Google Pay not available on this device') { // Hide button, show card form instead } } }); }); ``` > **Info** > > **Which account handles the wallet.** For Stripe, the Google Pay PaymentMethod is minted in the browser on the processor used to **prepare** the sheet, and Stripe PaymentMethods are account-scoped — so the payment is always **charged on that same processor**. Choose the account with the [`processorIds` init option](#choose-the-wallet-processor) (or the account's express-checkout processor when unset). A different `processorId` passed at `submit` is ignored for an already-prepared sheet and logs a warning — the SDK keeps mint and charge on one account. > **Info** > > Need to run your own validation after the shopper authorizes but before the charge? Pass `beforeConfirm` in `options` — see [Pre-charge validation](/guides/integration/sdk-reference/payment-kit-js/pre-charge-validation). # Options | Option | Type | Description | | ------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `processorId` | `string` | The processor that handles the whole wallet payment — the sheet mints its PaymentMethod on this account and the charge is made on the same one (Stripe PMs are account-scoped). Fixed at **prepare** time (auto-filled from the prepared session); a different value passed here is ignored for an already-prepared sheet. To pick the account, use the [`processorIds` init option](#choose-the-wallet-processor). | | `customerInfo.first_name` | `string` | Optional — Google Pay collects the payer name from the sheet. | | `customerInfo.last_name` | `string` | Optional — Google Pay collects the payer name from the sheet. | | `mockScenario` | `GooglePayMockScenario` | Testing only. Use `"success"` or `"cancelled"` to simulate Google Pay flows without a real device | # Browser support Google Pay works on: * Chrome 61+ on Android devices (with a card saved to Google Pay) * Chrome 61+ on desktop (with a card saved to Google Pay) * Microsoft Edge on desktop (with a card saved to Google Pay) > **Info** > > Depending on your processor, PaymentKit.js routes Google Pay through either Stripe's Payment Request API (Stripe) or Google's native Pay API (Airwallex). Both have specific browser requirements. Safari on iOS does not support Google Pay—use Apple Pay instead. > **Warning** > > Google Pay isn't available on all devices. Always provide card payments as a fallback. # Error handling | Error | Cause | | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | `Processor ID is required` | No processor available — the session has no express-checkout processor configured (or none passed when bypassing auto-prepare) | | `Stripe.js not loaded. Add to your page.` | Stripe.js script not loaded before initializing Google Pay (Stripe processors) | | `Google Pay API not loaded. Add to your page.` | Google's `pay.js` script not loaded before initializing Google Pay (Airwallex processors) | | `Google Pay not available on this device` | Device doesn't support Google Pay or no cards saved | | `Google Pay cancelled by user` | Customer closed the Google Pay sheet | | `Failed to start Google Pay` | API call to start checkout failed | | `Card setup failed` | Stripe card setup confirmation failed | | `Payment failed` | Payment confirmation returned a failure status | | `Google Pay error: {message}` | Unexpected error during the payment flow | > Accept Google Pay for fast, secure checkout on supported devices.