For the complete documentation index, see llms.txt. Append
.mdto any page URL for its markdown version.
Google Pay lets users pay with a card already saved to their device — no card entry, no redirect. The payment sheet is native and dismisses back into your app once the transaction is confirmed.
Identity creation, KYC, eligibility, and OTP must be completed before reaching the payment step. See the Integration Guide if you haven't done this yet. This guide picks up from paymentReady: true.
| Approach | Best for |
|---|---|
| React Native SDK | React Native mobile apps (Android only) |
| Android SDK | Native Android apps (Kotlin) |
| Flutter SDK | Flutter apps (Dart) |
| Embedded Payment Button | Web apps (Vanilla JS, React, Vue) |
| JS Native Payments SDK | Web apps (native payment sheet, including cards) |
Google Pay via the React Native SDK is Android only.
When your Android app presents Google Pay directly, Google requires app-level approval before you can process live payments. This is separate from any approval Banxa holds.
Banxa has Google Pay approval for its own website. That approval applies only when a user is redirected to an external browser or Custom Chrome Tab — not when Google Pay is presented inside your app. If you are integrating via the React Native SDK or the Android SDK, your app requires its own approval.
To apply:
- Integrate Google Pay in your app following Google's integration requirements
- Complete the Google Pay API production access request
- Google will review your integration and confirm approval
You can develop and test against Google Pay's test environment while your approval is in progress. See Testing below.
Once your app has Google Pay approval (or is in test mode), trigger the payment sheet after your backend confirms paymentReady: true:
import {
isPrimerCheckoutWebViewResult,
} from '@banxa-official/react-native-sdk';
const result = await banxa.buy.createOrderAndShowPrimerCheckout(orderRequest, {
paymentMethod: 'googlePay',
callbacks: {
onCheckoutComplete: () => {
// Google Pay confirmed — transaction is in progress
},
onError: (error) => {
// Google Pay unavailable or failed — see error handling below
},
onDismiss: () => {
// User dismissed the payment sheet without completing
},
},
});
if (isPrimerCheckoutWebViewResult(result)) {
// Google Pay unavailable for this session — SDK fell back to hosted WebView
render(<CheckoutWebView {...result.webViewProps} />);
}The orderRequest must include externalCustomerId — pass the same identityReference you used for eligibility.
onError is called when Google Pay is unavailable for the current session. Common causes:
- User has not set up Google Pay on their device
- No cards added to Google Pay
- None of the user's cards match supported networks
- Device doesn't support Google Pay
Google Pay provides a test environment that returns simulated payment results without processing real transactions. Use this during development before your production approval is confirmed.
const banxa = new Banxa({
environment: 'sandbox',
// ...
});Google Pay can be tested on a physical Android device or on an Android emulator with Google Play Services installed.
The error codes below are Primer errors surfaced through the SDK.
Google Pay button does not appear
Google Pay is not available for the current user or session. Common reasons:
- User has not set up Google Pay on their device
- No cards added to Google Pay
- None of the user's cards match supported networks
- Device does not have Google Play Services
The SDK filters Google Pay from available payment methods in these cases. Only show a Google Pay option when the SDK confirms it is available.
Google Pay sheet appears in test but fails in production
Your app has not yet received Google Pay production approval. Ensure your production access request has been approved by Google before releasing to users.
[unable-to-present-payment-method]
Google Pay is not available for this session. See causes above.
[payment-cancelled]
The user dismissed the Google Pay sheet without completing payment. No action required — handle via onDismiss or onError in your callbacks.
Before releasing to production:
- Confirm your Google Pay production approval is active
- Switch to production credentials in the SDK
- Confirm with your Banxa integration contact that your account is provisioned for production
The Android SDK presents Google Pay in a native payment sheet from a native Kotlin app. It is headless and Compose-first: you render one composable and receive the outcome on callback lambdas.
Your app needs its own Google Pay approval, exactly as for the React Native SDK. Banxa's website approval does not cover payments presented inside your app. Complete Android app approval above before going live.
Start this early. It is the most common cause of a delayed Android launch.
The Android SDK is published to Maven Central. Add the dependency to your module's Gradle build file.
dependencies {
implementation("com.banxa.nativepaymentssdk:android-payments-sdk:1.0.0")
}val config = BanxaConfig.Builder()
.apiKey("YOUR_API_KEY")
.partnerID("your-partner-id")
.environment(Environment.SANDBOX)
.build()
Banxa.initialize(config)After your backend confirms paymentReady: true from eligibility, render StartPayment with paymentMethodId set to google-pay.
StartPayment(
createOrderRequest = CreateOrderRequest(
fiat = "AUD",
crypto = "BTC",
fiatAmount = "500.00",
cryptoAmount = null,
walletAddress = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
redirectUrl = "your-app-scheme://banxa-return",
paymentMethodId = "google-pay",
email = "[email protected]",
externalCustomerId = "user-123"
),
banxaDidReceiveCheckout = { result ->
// Google Pay confirmed, the transaction is in progress.
},
banxaDidFail = { error ->
// Google Pay unavailable or the payment failed.
},
banxaDidDismiss = {
// The customer dismissed the payment sheet without completing.
}
)Pass the same identityReference you used for eligibility as externalCustomerId. StartPayment creates the order and presents the payment sheet together, so render it at the moment the customer confirms.
Treat banxaDidReceiveCheckout as a UI signal only, and confirm the final state from webhooks before crediting a customer.
banxaDidFail fires when Google Pay cannot be presented, but the Android SDK does not expose the eligibility result or the reason. Do not render a Google Pay button on the strength of a failed attempt. Gate on POST /eapi/v0/eligibility from your backend, and treat banxaDidFail as a terminal state for that attempt.
The Android SDK accepts a PrimerTheme on the config builder, so you can match the payment sheet to your app. See Payment sheet theming in the reference. This is Android only: the iOS SDK does not expose theming.
Google Pay's test environment returns simulated results without processing real transactions. Use Environment.SANDBOX during development, before your production approval is confirmed.
Test on a physical Android device, or on an emulator with Google Play Services installed.
The failure modes are identical to the React Native SDK, because both present the same payment sheet. See Troubleshooting above.
- Confirm your Google Pay production approval is active
- Switch
environmenttoEnvironment.PRODUCTIONand use production credentials - Confirm with your Banxa integration contact that your account is provisioned for production
The Flutter SDK presents Google Pay in a native payment sheet from a Flutter app. startPayment creates the order and presents the sheet in one call, and outcomes arrive on a stream.
Your app needs its own Google Pay approval, exactly as for the React Native and Android SDKs. Banxa's website approval does not cover payments presented inside your app. Complete Android app approval above before going live.
Start this early. It is the most common cause of a delayed Android launch.
dependencies:
banxa_payments_flutter: 0.1.0The plugin requires Android minSdk 24 and merges the INTERNET permission. Declare android.permission.CAMERA in your own AndroidManifest.xml for KYC document capture.
Configure once at app launch. Google Pay needs no extra configuration beyond your credentials.
import 'package:banxa_payments_flutter/banxa_payments_flutter.dart';
await BanxaPayments.configure(
const BanxaConfig(
apiKey: 'YOUR_API_KEY',
partnerId: 'your-partner-id',
environment: BanxaEnvironment.sandbox,
),
);After your backend confirms paymentReady: true from eligibility, call startPayment with paymentMethodId set to google-pay.
final launch = await BanxaPayments.startPayment(
const CreateOrderRequest(
orderType: OrderType.buy,
crypto: 'ETH',
fiat: 'AUD',
fiatAmount: '500.00',
walletAddress: '0x0000000000000000000000000000000000000000',
email: '[email protected]',
redirectUrl: 'https://app.yourcompany.com/complete',
paymentMethodId: 'google-pay',
externalCustomerId: 'user-123',
),
);Pass the same identityReference you used for eligibility as externalCustomerId.
Subscribe to checkoutEvents before starting the payment, and switch on the launch result.
BanxaPayments.checkoutEvents.listen((event) {
switch (event) {
case BanxaCheckoutCompleted():
// Google Pay confirmed, the transaction is in progress.
case BanxaCheckoutFailed(:final message):
// The payment failed.
case BanxaCheckoutDismissed():
// The customer dismissed the payment sheet without completing.
}
});
switch (launch) {
case BanxaPrimerCheckoutLaunched():
// The payment sheet is on screen.
case BanxaHostedCheckoutRequired():
// Google Pay was not available. Render BanxaHostedCheckoutView.
}BanxaCheckoutCompleted.status may be null on Android. Treat the event as a UI signal only, and confirm the final state from webhooks before crediting a customer.
On Android, Primer Checkout 3.x presents the payment methods from the client session rather than a single method. The requested Banxa method is still recorded natively.
When Google Play services are missing, or Google Pay otherwise cannot be presented, startPayment returns BanxaHostedCheckoutRequired rather than throwing. The SDK does not tell you why. Gate on POST /eapi/v0/eligibility from your backend and decide up front whether to offer Google Pay at all.
Google Pay's test environment returns simulated results without processing real transactions. Use BanxaEnvironment.sandbox during development, before your production approval is confirmed.
Test on a physical Android device, or on an emulator with Google Play Services installed. Without Play Services, the SDK falls back to hosted checkout.
The failure modes are identical to the React Native and Android SDKs, because all three present the same payment sheet. See Troubleshooting above.
- Confirm your Google Pay production approval is active
- Switch
environmenttoBanxaEnvironment.productionand use production credentials - Confirm with your Banxa integration contact that your account is provisioned for production
The Embedded Payment Button renders Google Pay inside a web component — no SDK install required. It is a web integration for Vanilla JS, React, and Vue apps. No additional Google Pay setup is required — Banxa's approval covers the web integration.
Before you start: Contact your Banxa integration contact to get provisioned. The button-only setting must be enabled on your environment before this works.
Google Pay only works on Android devices. Do not show the Google Pay button on Apple devices — if a user on an Apple device triggers the payment sheet, the payment will fail. Detect the device and render only the appropriate payment method.
The button-only configuration applies to your entire environment. If it is enabled, the standard full checkout widget will no longer render for that environment. If you need both — for example, the button on one surface and full checkout on another — you will need a separate environment provisioned by Banxa.
npm install @banxa-official/embedded-checkout-web-componentImport the package once to register the custom element:
import '@banxa-official/embedded-checkout-web-component';Once your backend confirms paymentReady: true from eligibility, create an order. This returns a checkoutUrl which you pass to the web component.
POST /{partner}/v2/buy
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"externalCustomerId": "user-123",
"fiat": "AUD",
"crypto": "BTC",
"walletAddress": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"fiatAmount": "500.00",
"redirectUrl": "https://app.yourcompany.com/complete"
}Pass the checkoutUrl as the source attribute:
<banxa-checkout source="https://checkout.banxa.com/..."></banxa-checkout>The component stays hidden until the checkout page signals it is ready — at that point it resizes to fit the payment button and becomes visible.
Lifecycle callbacks
Assign functions to these properties on the element instance:
| Property | When called |
|---|---|
onLoading | Checkout is loading |
onReady | Component is ready and visible |
onPaymentPending | Payment initiated, awaiting confirmation |
onComplete | Payment completed successfully |
onError | An error occurred |
Each callback receives a detail object, not a DOM event.
<script type="module">
import '@banxa-official/embedded-checkout-web-component';
</script>
<banxa-checkout id="checkout" source="https://checkout.banxa.com/..."></banxa-checkout>
<script>
const el = document.getElementById('checkout');
el.onLoading = (detail) => console.log('loading', detail);
el.onReady = (detail) => console.log('ready', detail);
el.onPaymentPending = (detail) => console.log('payment pending', detail);
el.onComplete = (detail) => console.log('complete', detail);
el.onError = (detail) => console.log('error', detail);
</script>Before releasing to production:
- Confirm with your Banxa integration contact that your environment is provisioned for the Embedded Payment Button
- Switch to production credentials for order creation
The JS Native Payments SDK renders Google Pay in the native payment sheet directly on your page through the <banxa-primer-checkout> web component. Unlike the Embedded Payment Button, it is not limited to a button: the same component can present cards and Google Pay together. It is a web integration for Vanilla JS, React, and Vue apps.
Google Pay only works on Android devices and Chrome. Detect the platform and offer Google Pay only where it is available.
npm install @banxa-official/javascript-native-payments-sdk @primer-io/primer-js@primer-io/primer-js is the peer dependency that powers the native payment sheet.
Because the Google Pay sheet renders on your own web domain rather than a Banxa-hosted surface, your domain needs its own Google Pay approval before you can process live payments. This is how Google Pay's registration model works for any merchant that renders the button on its own surface: Banxa's website approval does not extend to your domain. Established Google Pay integrators require the same of their headless partners.
To go live:
- Create a Google Pay Business Profile and accept the Terms of Service in the Google Pay & Wallet Console.
- Obtain your own Merchant ID.
- Submit your specific domain for review, following Google Pay: Publish your integration.
Payments are processed through Primer as the gateway, so you do not need your own PCI DSS attestation. That does not exempt you from registering your own domain and obtaining Google's approval for it. See the Google Pay integration checklist. Coordinate with your Banxa integration contact so your Merchant ID and domain are configured correctly on Banxa's side.
You can develop and test Google Pay in sandbox without approval. Google Pay approval is only required before processing live payments in production.
Once your backend confirms paymentReady: true from eligibility, create the order and return the nativeToken (the Primer client token) to your page. Keep your API key server-side.
import { BanxaApiClient } from '@banxa-official/javascript-native-payments-sdk';
const client = new BanxaApiClient({ apiKey, partner, environment: 'sandbox' });
const order = await client.createOrder({
externalCustomerId: 'user-123', // the same identityReference used for eligibility
fiat: 'AUD',
crypto: 'BTC',
fiatAmount: '500.00',
walletAddress: 'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',
redirectUrl: 'https://app.yourcompany.com/complete',
});
// return order.nativeToken to the browserRegister the component, include GOOGLE_PAY in payment-methods, and set the token returned by your backend.
<script type="module">
import { registerBanxaPrimerCheckout } from '@banxa-official/javascript-native-payments-sdk/web';
registerBanxaPrimerCheckout();
</script>
<banxa-primer-checkout id="checkout" payment-methods="GOOGLE_PAY" locale="en"></banxa-primer-checkout>
<script type="module">
const { nativeToken } = await (await fetch('/api/create-order', { method: 'POST' })).json();
const checkout = document.getElementById('checkout');
checkout.clientToken = nativeToken;
checkout.addEventListener('banxa:payment-success', () => { /* Google Pay confirmed */ });
checkout.addEventListener('banxa:payment-failure', () => { /* payment failed */ });
</script>To offer Google Pay alongside cards in one sheet, set payment-methods="PAYMENT_CARD,GOOGLE_PAY".
- Complete your own Google Pay approval for your production domain (Business Profile, Merchant ID, and domain review)
- Install the
@primer-io/primer-jspeer dependency in your production build - Switch to production credentials for order creation
For the full component API (attributes, events, layout modes), see the JS Native Payments SDK Reference.