Google Pay

Google Pay lets customers pay in one tap with cards already stored in their Google Wallet — no manual card entry. The SDK provides a native Google Pay button that handles availability checking, the payment sheet, and result handling for you.

Order PageGoogle Payment Sheet

Flow: Google Pay button is shown if available on the device → user taps it → Google Pay sheet opens → user confirms → result is returned via GooglePayButtonResult.

Prerequisites

payabl. requirements

  • The SDK is added to your project — see Android SDK.
  • Your backend can create a session via /mobile/init, and the request must include the country parameter for Google Pay sessions — see Setup Your Server.

Google Pay™ requirements

  • Your app is published on Google Play.
  • Complete your Business profile in the Google Pay & Wallet Console.
  • Share your Google Merchant ID with payabl. so we can configure it in our system.

Device and account setup (for testing)

Manifest configuration

Enable the Google Wallet API in your AndroidManifest.xml:

<application>
    ...
    <meta-data
        android:name="com.google.android.gms.wallet.api.enabled"
        android:value="true" />
</application>

Integration

Use the PayablGooglePayButton composable. It handles the availability check, lazy session loading, and the payment flow.

@Composable
fun PaymentScreen() {
    PayablGooglePayButton(
        modifier = Modifier
            .fillMaxWidth()
            .height(56.dp),
        buttonType = ButtonType.Pay, // Options: Pay, Buy, Checkout
        environment = PBLEnvironment.SANDBOX, // use PBLEnvironment.PRODUCTION when going live
        // 1. Check availability
        onGooglePayAvailability = { isAvailable ->
            // Show a fallback payment method if false
        },
        // 2. Provide the session (lazy — runs only when the button is tapped)
        sessionProvider = {
            fetchSessionConfiguration()
        },
        // 3. Handle the result
        onPaymentResult = { result ->
            handlePaymentResult(result)
        }
    )
}

Configuration parameters

ParameterTypeDefaultDescription
buttonTypeButtonTypeButtonType.PayType of button (Pay, Buy, Checkout, etc.)
themeButtonTheme?nullButton theme (Light/Dark); auto-detects the system theme if null
radiusDp100.dpCorner radius of the button
environmentPBLEnvironmentPBLEnvironment.SANDBOXEnvironment for availability checking
onGooglePayAvailability(Boolean) -> Unit{}Invoked when availability is determined — true if Google Pay is available on the device
sessionProvidersuspend () -> PBLConfigurationRequiredSuspend function that provides the session configuration
onPaymentResult(GooglePayButtonResult) -> UnitRequiredCallback for payment results

Session provider

The sessionProvider runs only when the user taps the button — lazy initialization that avoids creating sessions the user never uses. Create a new session for every payment attempt.

private suspend fun fetchSessionConfiguration(): PBLConfiguration {
    return withContext(Dispatchers.IO) {
        // Call your backend, which calls /mobile/init (with the country parameter)
        val response = apiClient.initPayment()
        response.getOrElse { exception ->
            throw exception // surfaces as GooglePayButtonResult.Error
        }
        PBLConfiguration(
            sessionId = response.sessionId,
            ephemeralKey = response.ephemeralKey,
            userId = "user_id_from_app",
            environment = PBLEnvironment.SANDBOX // use PBLEnvironment.PRODUCTION when going live
        )
    }
}

Handle the result

The button reports outcomes through the GooglePayButtonResult sealed class. Handle all three cases.

fun handlePaymentResult(result: GooglePayButtonResult) {
    when (result) {
        is GooglePayButtonResult.Success -> {
            // Transaction complete — details via result.status (amount, orderId, timestamp)
        }
        is GooglePayButtonResult.Error -> {
            // Payment failed or technical error — inspect result.errorMessage
        }
        is GooglePayButtonResult.Cancelled -> {
            // User closed the Google Pay sheet without paying
        }
    }
}

Testing

Use PBLEnvironment.SANDBOX throughout development. To test on a physical device:

  • Device runs Android 9+ and is in a Google Pay-supported region.
  • Log in with your Google Account and add a card from Google's test card suite to Google Wallet.
  • Run payments in the sandbox before going live.

For test data across all payment methods, see Testing.

Going live

When transitioning from sandbox to production:

  1. Switch the environment in both the button and your session configuration to PBLEnvironment.PRODUCTION, and make sure your backend uses live credentials.
  2. Request production access with Google: submit your app for Google Pay production review, choose Gateway as the integration type, provide screenshots of your implementation, and wait for Google's approval.
  3. Test in production with a signed release build and a real payment method.

Common issues

IssueCause & resolution
Button never becomes available (onGooglePayAvailability returns false)No Google Account or no valid payment method in Google Wallet, unsupported device/region, or the Wallet API meta-data is missing from the manifest.
Session created but payment failscountry missing from the /mobile/init request — required for Google Pay. See Setup Your Server.
Works in sandbox, fails in productionGoogle production access not approved yet, environment still set to SANDBOX somewhere, or the app isn't a signed release build.
Works on one device, not anotherEmulator limitations, or the device's region/account doesn't support Google Pay. Test on a physical device with a supported account.

When something goes wrong, see Error Handling & Troubleshooting.