Google Pay via Widget
This guide walks you through integrating Google Pay using the DEUNA SKDs. It covers the two integration paths the SDK exposes:
| Payment Widget | Payment Vault | |
|---|---|---|
| What it does** | Handles the full checkout: UI, payment processing, and confirmation | Tokenizes the card only — returns a card_id for you to use |
| Who processes the purchase | DEUNA (internally) | You (via the Purchase API from your backend) |
| Google Pay button | Rendered inside DEUNA's iframe | Rendered by you, in your own UI |
| SDK method | initPaymentWidget | initElements({ types: ['GOOGLE_PAY'] }) |
| Use when | You want a drop-in checkout experience | You need control over the payment flow or want to store the card for later |
1. Prerequisites
Before you start, make sure the following are in place:
| Requirement | Notes |
|---|---|
| DEUNA account | Active merchant account in the DEUNA Dashboard. |
publicApiKey | Public API key issued by DEUNA. Required for DeunaSDK.initialize. |
orderToken | Generated on your backend via the DEUNA Orders API. Required to start a payment. |
userToken (optional) | Required only when you want to tokenize the card against a known DEUNA user. |
| Compatibility requirements | Refer to the official Google Pay supported devices guide. Google Pay supports Chrome, Firefox, Safari, Edge, Opera, and UC Browser. For Android WebView integrations, additional requirements apply — see the Android WebView guide |
2. What needs to be pre‑configured for Google Pay
The setup has two parts: credentials and, for production, domain registration inside the Google Pay Business Console.
2.1 Credentials (handled by DEUNA)
DEUNA resolves Google Pay credentials from your merchant configuration. The fields involved are:
| Field | Meaning | Where it comes from |
|---|---|---|
merchantId | Your Google Pay Merchant ID (e.g. 12345678901234567890). | Google Pay Business Console, stored in DEUNA Dashboard. |
merchantName | Label shown on the Google Pay sheet. | DEUNA Dashboard. |
gateway | Payment gateway identifier (e.g. "deuna", "adyen"). Used with PAYMENT_GATEWAY tokenization. | DEUNA Dashboard. |
gatewayMerchantId | Merchant identifier within the gateway. | DEUNA Dashboard. |
tokenizationType | "PAYMENT_GATEWAY" (default) or "DIRECT". | Merchant choice. |
publicKey (DIRECT only) | Base64‑encoded public key used for DIRECT tokenization. | DEUNA Dashboard. |
protocolVersion (DIRECT only) | Defaults to "ECv2". | DEUNA Dashboard. |
allowedCardNetworks | Subset of VISA, MASTERCARD, AMEX, DISCOVER, INTERAC, JCB. | Optional — defaults provided. |
allowedCardAuthMethods | PAN_ONLY, CRYPTOGRAM_3DS. | Optional — defaults provided. |
Most integrations will use PAYMENT_GATEWAY tokenization with DEUNA as the gateway. DIRECT is reserved for merchants that decrypt the Google Pay token themselves.
What you need to provide/confirm in the DEUNA Dashboard:
- Google Pay credential enabled for your merchant.
- Merchant ID and merchant name.
- Gateway and gateway merchant ID (for PAYMENT_GATEWAY).
- Allowed networks and auth methods (optional).
2.2 Domain registration (production only)
Google Pay requires that every production domain be registered in the Google Pay Business Console before it can take live payments:
- Go to Google Pay & Wallet Console → Integration → Business information.
- Register the domain(s) that will load the Web‑SDK (e.g.
checkout.mystore.com). - Submit your integration for approval (screenshots of the checkout flow are required).
No file needs to be hosted on your domain. Test/sandbox environments work out of the box — only production requires the console registration.
The SDK automatically switches Google Pay to
TESTmode for anyenvother than"production", so you can develop and QA without console registration.
For the full widget integration guide, including initialization, callbacks, and display options.
Google Pay particularities
- No extra configuration needed in code.
- Google Pay is enabled or disabled from the DEUNA Dashboard. If the merchant has it active and the user's browser supports it, the button appears automatically.
- userToken is optional — only needed when you want to associate the payment with a known DEUNA user account.
- The standard widget callbacks (onSuccess, onError, onClosed, onPaymentProcessing) work the same way as for other payment methods.
- The SDK automatically calls isReadyToPay and hides the button on unsupported devices — no additional check is required on your side.
What the commerce must do for Google PayThis is the checklist the merchant (commerce) owns:
- Chrome, Edge, Firefox, Safari (any evergreen browser). User must be signed into a Google account with a saved card.
- Serve the checkout over HTTPS. Google Pay refuses to run on http:// except localhost.
- Register all production domains in the Google Pay Business Console. Staging/dev hosts don't need registration because the SDK runs Google Pay in
TESTmode there.- Complete the Google Pay brand‑compliance review. Upload screenshots of the full checkout (button on cart, payment sheet, confirmation) in the Business Console.
- Do not modify the Google Pay token. The SDK forwards
paymentMethodDataunchanged toonPaymentAuthorized/onSuccess. Re‑serializing it will break tokenization.
3. Integrations
Make sure to follow the Getting Started guide for our SDKs depending on your specific integration:
3.1 Payment Widget
Use this path when you want DEUNA to handle the full checkout experience (UI, payment processing, and confirmation).
Web SDK
No Extra Configuration Required: You do not need to manually include Google’s scripts. The Web SDK dynamically loads the Google Pay JavaScript SDK (pay.js) the moment initPaymentWidget is called.
Respect the user gesture. When using
initElements, the button click must reachloadPaymentData()without a long await in between, or Chrome will block the sheet.
Android SDK
In Android, Google Pay is enabled via PaymentRequest within the WebView used by the DEUNA SDK. The host app must apply the following configuration:
- Add the following to your app module's
build.gradleorbuild.gradle.kts:dependencies { implementation("androidx.webkit:webkit:1.14.0") } AndroidManifest.xmlQueries: The host app must declare these intents to allow communication with Google Pay.<queries> <intent> <action android:name="org.chromium.intent.action.PAY" /> </intent> <intent> <action android:name="org.chromium.intent.action.IS_READY_TO_PAY" /> </intent> <intent> <action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" /> </intent> </queries>- SDK Configuration: This configuration must be executed before calling
initPaymentWidgetmethod or rendering an embeddedDeunaWidget.import androidx.webkit.WebSettingsCompat import androidx.webkit.WebViewFeature import com.deuna.maven.DeunaSDK import com.deuna.maven.shared.Environment val deunaSDK = DeunaSDK( environment = Environment.SANDBOX, publicApiKey = "YOUR_PUBLIC_API_KEY" ) // This enables the host app to configure PaymentRequest for Google Pay support. deunaSDK.applyCustomWebViewSettings { settings -> // Guard the call to avoid crashes on devices/WebView versions that do not support PaymentRequest. if (WebViewFeature.isFeatureSupported(WebViewFeature.PAYMENT_REQUEST)) { // Enable PaymentRequest API on DEUNA's internal WebView settings. WebSettingsCompat.setPaymentRequestEnabled(settings, true) } }
3.2 Payment Vault
Use this path when you want to render a native Google Pay button inside your own UI (no DEUNA iframe). Common in custom/headless checkouts.
Web SDK
Let the Web SDK resolve Google Pay credentials from the DEUNA backend using your publicApiKey and (optionally) an orderToken.
For more info check the getWalletsAvailable documentation.
// 1) Initialize the SDK
await DeunaSDK.initialize({
env: 'staging',
publicApiKey: '<YOUR_PUBLIC_API_KEY>',
});
// 2) Check availability + warm up the Google Pay provider
const available = await DeunaSDK.getWalletsAvailable();
if (available.includes('GOOGLE_PAY')) {
// Render button for Google Pay and append a listener (EXAMPLE)
btn.addEventListener('click', () => {
deuna.initElements({
types: [{ name: 'GOOGLE_PAY' }],
orderToken: '<order-token>', // REQUIRED FOR MERCHANTS
userInfo: {
email: '<email>',
firstName: '<firstName>',
lastName: '<lastName>',
},
callbacks: {
// Called after user approves the Google Pay sheet.
// Send the token to your backend, return the result.
onSuccess: async (payload) => {
const cardId = payload.data.card_id;
// use the cardId to process payment
},
onError: (error) => {
console.error('Payment failed:', error.metadata.message);
},
},
});
});
} else {
console.error('Google Pay is not available on this device.');
}
Android SDK
Use this path when you want to render a native Google Pay sheet directly. The SDK checks device availability, fetches Google Pay credentials from the DEUNA backend, and launches the payment sheet. The result is a tokenized card payload delivered to your onSuccess callback.
Step 1 — Check availability
Call getWalletsAvailable() once, before the user reaches the payment step. The SDK checks both the DEUNA merchant configuration and whether the device has Google Play Services with a saved card.
import com.deuna.maven.DeunaSDK
import com.deuna.maven.shared.Environment
import com.deuna.maven.wallets.GetWalletsAvailableParams
import com.deuna.maven.wallets.WalletProvider
import com.deuna.maven.wallets.getWalletsAvailable
val deunaSDK = DeunaSDK(
environment = Environment.SANDBOX,
publicApiKey = "YOUR_PUBLIC_API_KEY",
)
deunaSDK.getWalletsAvailable(
context = context,
params = GetWalletsAvailableParams(
orderToken = "<order-token>", // optional — pass if you have one at this point
),
) { wallets, error ->
if (error != null) {
// handle fetch error
return@getWalletsAvailable
}
val googlePayAvailable = WalletProvider.GOOGLE_PAY in wallets
// show or hide your Google Pay button based on googlePayAvailable
}getWalletsAvailable() caches the result. Subsequent calls return the cached list immediately — safe to call on every screen load.
Step 2 — Launch Google Pay
When the user taps your Google Pay button, call initElements with GOOGLE_PAY as the type. The SDK fetches fresh credentials for the order, then launches the native payment sheet.
// Wire this to your Google Pay button's onClick
deunaSDK.initElements(
context = context,
types = listOf(mapOf("name" to "GOOGLE_PAY")),
orderToken = "<order-token>",// required for google pay wallet
userInfo = UserInfo(// optional — associate with a DEUNA user
email = "[email protected]",
firstName = "Jane",
lastName = "Doe",
),
callbacks = ElementsCallbacks().apply {
onSuccess = { payload ->
// payload contains the tokenized card data
// send it to your backend to complete the purchase
}
onError = { error ->
// error.metadata.code and error.metadata.message describe the failure
}
onClosed = { action ->
// user dismissed the sheet
}
},
)iOS SDK
Use this path when you want to render a native Apple Pay sheet directly. The SDK checks device availability, fetches Apple Pay credentials from the DEUNA backend, and launches the payment sheet. The result is a tokenized card payload delivered to your onSuccess callback.
iOS Apple Pay prerequisites
- Enable Apple Pay capability in your app target.
- Add the Merchant ID in Signing & Capabilities > Apple Pay.
- Ensure the same Merchant ID is returned by DEUNA credentials (external_merchant_id).
- In Apple Developer, that Merchant ID must have an active Apple Pay Payment Processing Certificate.
- Regenerate provisioning profiles after capability/merchant changes and reinstall the app on a real device.
Common errors
- APPLE_PAY_PRESENT_FAILED: Usually capability/profile/merchant certificate mismatch in the signed app.
- MISSING_USER_AUTH: Backend did not return userToken/userId (pass valid userInfo with firstName, lastName and email).
Step 1 — Check availability Call getWalletsAvailable() once before the payment step. The SDK validates both DEUNA merchant configuration and Apple Pay availability on the device.
import DeunaSDK
let deunaSDK = DeunaSDK(
environment: .sandbox,
publicApiKey: "YOUR_PUBLIC_API_KEY"
)
deunaSDK.getWalletsAvailable(
params: GetWalletsAvailableParams(
orderToken: "<order-token>", // optional at this stage
userInfo: DeunaSDK.UserInfo(
email: "[email protected]",
firstName: "Jane",
lastName: "Doe"
) // recommended for wallet auth flows
)
) { wallets, error in
if let error = error {
// handle fetch error
return
}
let applePayAvailable = wallets.contains(.applePay)
// show or hide your Apple Pay button based on applePayAvailable
}
getWalletsAvailable() caches the result. Subsequent calls return cached wallets immediately, so it is safe to call on each screen load.
Step 2 — Launch Apple Pay When the user taps your Apple Pay button, call initElements with APPLE_PAY as the type. The SDK fetches order credentials and launches the native Apple Pay sheet.
deunaSDK.initElements(
userToken: "YOUR_ORDER_TOKEN", // required for apple pay wallet
callbacks: ElementsCallbacks(
onSuccess: { payload in
// payload contains tokenized card data
},
onError: { error in
// error.metadata?.code / message
},
onClosed: { _ in
// user dismissed the sheet
},
onEventDispatch: nil
),
closeEvents: [],
userInfo: DeunaSDK.UserInfo(
email: "[email protected]",
firstName: "Jane",
lastName: "Doe"
),
styleFile: nil,
types: [["name": "APPLE_PAY"]],
language: nil,
orderToken: "<order-token>",
widgetExperience: nil,
behavior: nil,
fraudCredentials: nil,
customUserAgent: nil,
domain: nil
)
Gotchas
| Gotcha | Fix |
|---|---|
| Button does not render | Check getWalletsAvailable() result. isReadyToPay may be rejecting the device — verify you're signed into Google and have a saved card. |
| Works locally, fails in production | Domain is not registered in the Google Pay Business Console. |
DEVELOPER_ERROR in the sheet | merchantId, gateway, or gatewayMerchantId is wrong or missing. Double‑check the walletConfig. |
| Sheet opens but no payment methods | Card networks in allowedCardNetworks don't match any saved card on the Google account. |
| Token decryption fails on your backend | You're in DIRECT mode with a mismatched publicKey / protocolVersion. Prefer PAYMENT_GATEWAY unless you need raw card data. |
Quick reference
| API | Purpose |
|---|---|
DeunaSDK.getWalletsAvailable() | Check which wallets are usable + warm up providers. |
DeunaSDK.initElements({ types, orderToken?, walletConfig?, callbacks }) | Mount native wallet buttons in your own UI. |
| Google Pay Business Console | Where production domains must be registered. No file to host on your server. |
Updated 5 days ago