Skip to content

Google Pay on Android

Let buyers pay with Google Pay in your Android application, using any debit or credit card saved to their Google account.

Overview

To add Google Pay to your Android app, you configure the payment methods and tokenization your app accepts, add the Google Pay button, and request payment data. When a buyer pays, you process the resulting token with the Finix API.

After setup, buyers can complete checkout with Google Pay and you process the payment like any other Finix transaction. The examples below show both Kotlin and Java.

Collect the billing address to avoid extra fees

Finix recommends passing the address field shown in the steps below. If you do not pass the address, the card network charges additional dues and assessments per transaction.

Prerequisites

Before you start, familiarize yourself with the Google Pay requirements for Finix, including the Finix API key, seller onboarding, and Google Pay merchant account steps.

Integration steps

Step 1: Define the Google Pay API version

Declare the version of the Google Pay API that your application uses. The major and minor versions affect the fields expected in each passed object and are included in the response.

Create a base request object that contains the properties present in all other request objects.

Google Pay API Version
private val baseRequest = JSONObject()
    .put("apiVersion", 2)
    .put("apiVersionMinor", 0)

Step 2: Request a Finix payment token

Configure the tokenization specification so Google Pay returns a Finix payment token.

  • Set gateway to finix.
  • Set gatewayMerchantId to the application owner Identity or merchant owner Identity. To choose the appropriate Identity ID, see Choose a Merchant identifier value.
Google Pay Tokenization Specification
private fun gatewayTokenizationSpecification(): JSONObject {
    return JSONObject().apply {
        put("type", "PAYMENT_GATEWAY")
        put("parameters", JSONObject(mapOf(
                "gateway" to "finix",
                "gatewayMerchantId" to "IDxxx")))
    }
}

Step 3: Define allowed card networks

Set which card networks your application accepts.

Google Pay Allowed Card Networks
private val allowedCardNetworks = JSONArray(listOf(
        "AMEX",
        "DISCOVER",
        "INTERAC",
        "JCB",
        "MASTERCARD",
        "VISA"))

Define allowedCardAuthMethods to set the authentication methods your application and gateway support.

Google Pay Allowed Card Auth Methods
private val allowedCardAuthMethods = JSONArray(listOf(
        "PAN_ONLY",
        "CRYPTOGRAM_3DS"))

For both PAN_ONLY and CRYPTOGRAM_3DS authorization methods, support for 3D Secure depends on the processors you integrate with in allowedCardNetworks. Finix accepts both PAN_ONLY and CRYPTOGRAM_3DS authorization methods.

Step 4: Describe allowed payment methods

After you define the supported card networks, describe your allowed payment methods:

  1. Combine allowedAuthMethods and allowedCardNetworks to describe how your application supports the CARD payment method.
  2. Extend the baseCardPaymentMethod object with the information you expect returned to your application, including a description of the tokenized payment data.
Google Pay Payment Methods
private fun baseCardPaymentMethod(): JSONObject =
    JSONObject()
        .put("type", "CARD")
        .put("parameters", JSONObject()
                .put("allowedAuthMethods", allowedCardAuthMethods)
                .put("allowedCardNetworks", allowedCardNetworks)
                .put("billingAddressRequired", true)
                .put("billingAddressParameters", JSONObject()
                        .put("format", "FULL")
                )
        )
private val cardPaymentMethod: JSONObject = baseCardPaymentMethod()
    .put("tokenizationSpecification", gatewayTokenizationSpecification())

Step 5: Create a PaymentsClient instance

Create a PaymentsClient instance to interact with the Google Pay API.

PaymentsClient Instance
fun createPaymentsClient(context: Context): PaymentsClient {
    val walletOptions = Wallet.WalletOptions.Builder()
        .setEnvironment(Constants.PAYMENTS_ENVIRONMENT)
        .build()

    return Wallet.getPaymentsClient(context, walletOptions)
}

Step 6: Check readiness to pay with Google Pay

After you describe your allowed payment methods, check readiness to pay with the Google Pay API:

  1. Add allowedPaymentMethods to the baseRequest object.
  2. Call isReadyToPay() to determine whether the user can pay with the Google Pay API.
Google Pay Readiness Check
fun isReadyToPayRequest(): JSONObject? =
    try {
        baseRequest
            .put("allowedPaymentMethods", JSONArray().put(baseCardPaymentMethod()))
    } catch (e: JSONException) {
        null
    }

private fun possiblyShowGooglePayButton() {
    val isReadyToPayJson = PaymentsUtil.isReadyToPayRequest() ?: return
    val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString()) ?: return
    // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an
    // OnCompleteListener to be triggered when the result of the call is known.
    val task = paymentsClient.isReadyToPay(request)
    task.addOnCompleteListener { completedTask ->
        try {
            completedTask.getResult(ApiException::class.java)?.let(::setGooglePayAvailable)
        } catch (exception: ApiException) {
            // Process error
            Log.w("isReadyToPay failed", exception)
        }
    }
}

Step 7: Add the Google Pay button

After you check readiness to pay, add a Google Pay payment button to your app.

Google Pay Button
PayButton(
    modifier = Modifier
        .testTag("payButton")
        .fillMaxWidth(),
    onClick = onGooglePayButtonClick,
    allowedPaymentMethods = PaymentsUtil.allowedPaymentMethods.toString()
)

To use the Jetpack Compose element, add the com.google.pay.button:compose-pay-button library to the list of dependencies in your Gradle build file. For more information, see Google Pay payment button.

If you add the Google Pay button with XML, initialize it in your Android activity along with your other UI elements.

Initialize Google Pay Button
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  // Use view binding to access the UI elements
  layout = ActivityCheckoutBinding.inflate(layoutInflater)
  setContentView(layout.root)

  // Setup buttons
  googlePayButton = layout.googlePayButton
  googlePayButton.initialize(
      ButtonOptions.newBuilder()
          .setAllowedPaymentMethods(PaymentsUtil.allowedPaymentMethods.toString()).build()
  )
  googlePayButton.setOnClickListener { requestPayment() }

  // Check Google Pay availability
  model.canUseGooglePay.observe(this, Observer(::setGooglePayAvailable))
}

Step 8: Create a payment data request

After you add the Google Pay button, create a PaymentDataRequest object. The PaymentDataRequest takes in the merchant and transaction information required to start the payment process with Google Pay.

paymentDataRequest
private fun getTransactionInfo(price: String): JSONObject =
    JSONObject()
        .put("totalPrice", price)
        .put("totalPriceStatus", "FINAL")
        .put("countryCode", Constants.COUNTRY_CODE)
        .put("currencyCode", Constants.CURRENCY_CODE)

private val merchantInfo: JSONObject =
    JSONObject().put("merchantName", "Example Merchant")

The getTransactionInfo object accepts the following arguments.

FieldTypeDescription
countryCodestring, requiredThe ISO country code.
currencyCodestring, requiredThe currency code of the locale.
totalPricestring, requiredTotal value of the transaction, with optional decimal precision of two places.
totalPriceStatusstring, requiredThe status of the total price. Pass FINAL if the total price does not change from the amount presented to the buyer. Pass ESTIMATED if the total price might adjust based on the response, such as sales tax based on a billing address. Pass NOT_CURRENTLY_KNOWN when using totalPriceStatus for a capability check.

The getMerchantInfo object accepts the following arguments.

FieldTypeDescription
merchantIdstring, requiredA Google merchant identifier issued after registration with the Google Pay Business Console. Required when PaymentsClient is initialized with an environment property of PRODUCTION.
merchantNamestring, requiredThe name of the Merchant.
Strong Customer Authentication (SCA)

Merchants that process transactions in the European Economic Area (EEA) or any other region subject to Strong Customer Authentication (SCA) must include the countryCode, totalPrice, and merchantName parameters to meet SCA requirements.

Assign your base request object to a new PaymentDataRequest JSON object. Then add the payment methods your application supports, along with any configuration of additional data expected in the response. Finally, add the transaction and merchant information for the request. For more information, see Step 5 of Google Pay integration.

Step 9: Use a Buyer Identity

A Buyer Identity is required before you can process a payment. You can create a new Buyer Identity with the Finix API, or use an existing one.

Buyer Identity data

All Buyer Identity fields are optional. Finix recommends including basic information (name, email, address, and phone) to make payment operations easier.

To find and reuse an existing Buyer Identity:

  1. Log in to your Finix Dashboard.
  2. In the left sidebar, select Data ResourcesIdentities.
  3. Search for the Buyer Identity you want to use, and confirm its Role is Buyer.
  4. Copy the Buyer Identity ID (for example, IDjWktr7BPDGhz4amrPJZoXg).

Step 10: Create a Payment Instrument

Call loadPaymentData using the Google Pay PaymentsClient object, which returns a Task object. Extract the payment token from the PaymentData result object. For more information, see Step 6 of Google Pay integration.

paymentDataRequest
fun getLoadPaymentDataTask(priceLabel: String): Task<PaymentData> {
    val paymentDataRequestJson = PaymentsUtil.getPaymentDataRequest(priceLabel)
    val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
    return paymentsClient.loadPaymentData(request)
}

To process the result, use one of the activity result contracts in the API. For more information, see Step 6 of Google Pay integration.

Before you present the buyer with a confirmation of their purchase, extract the payment token from the PaymentData result object and use it in the Payment Instrument request below.

Pass the third_party_token, name, and billing address that Google Pay returns when creating a Payment Instrument.

curl -i -X POST \
  -u USfdccsr1Z5iVbXDyYt7hjZZ:313636f3-fac2-45a7-bff7-a334b93e7bda \
  https://finix.sandbox-payments-api.com/payment_instruments \
  -H 'Content-Type: application/json' \
  -H 'Finix-Version: 2022-02-01' \
  -d '{
    "address": {
      "city": "San Francisco",
      "country": "USA",
      "line1": "900 Metro Center Blv",
      "line2": "APT 200",
      "postal_code": "94404",
      "region": "CA"
    },
    "identity": "ID78Fh8mcnnzukVzbdoyex5y",
    "merchant_identity": "IDwhCCvPwCDEmiFd8Be7pDzN",
    "name": "Finix Sandbox",
    "third_party_token": "{\"signature\":\"MEYCIQCYTkaEMgug7pcjzEEdbIn+R57kYO5yYc2KYj41AQQn9wIhAN1QvylvZ2XydVecfejwi2xYS9y3Y9y/MmDnRnUfNw5H\",\"intermediateSigningKey\":{\"signedKey\":\"{\\\"keyValue\\\":\\\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4xc3fjeM9SMTjd1TL2GQCPmgqPf2h42aM3akPh/mTUBqWEgOITruK10A02rQ+4YZOvLCpQKQZzLSAd09nctnuA\\\\u003d\\\\u003d\\\",\\\"keyExpiration\\\":\\\"1648843199734\\\"}\",\"signatures\":[\"MEQCICwCI4s5YCLu4qRCyXwSJ3qG8y3ocFtP1Mque4Uzysl8AiARoD/0qbj5W0Q2PWKpxkEnfcP+nU5kwYS8FyQ9boDTmQ\\u003d\\u003d\"]},\"protocolVersion\":\"ECv2\",\"signedMessage\":\"{\\\"encryptedMessage\\\":\\\"roD4ikTpZ7Srunq+0zUnp+eiXzcuZBfIFSuZAJu1PQLXcP0RvnGDiGKtoarNCHvn+cnXsHCzIBWXMZSJ9Aglqky9VfP5a+qsXQhf5m5AFUbT2xnihtKwageGQQK6HzyjHSXXSjvuCzeo75ToOgIUxLFASZyaZ89u3Jifqhhc2c4a0Mtlx564BxXiwcxDFdtNkOle7uAIsJzsryk7Rcwgr8ZMJJM//XpvaeE5wNmkVFHUtR2uTqPm0BvkoYkFHCTRo4NHXWpxeLjXWzKGk2ELyTK1diuCa6c9ig0jO3t8BIh1cR63UeP8Ar7u5fh8C9FPPAsgPbTGLfiaRe615e4SxASgcZ4/8uWo5mikEPFqA5s2K2mid9ncXoMNYaHUc3qzJAyxHVYSd5SRNZYXHMkEcWcjnpDx+ErYjR1sMo1LMYXfrfGyZz3M69bQLKPYFe7ChjvgFI9MnfcFTNB4HAdNKMhbZT0EKinfxxGWkT7LVbGnUuqPlHp4toCe4kpbx7fulwXTj3bAFvg/qvxxwGOS38iP0HR/f+4GF0xHspqYVbdWdIJ5iJUdpBG8Nu5P56h2GEDxXMkKSmh+qbvKWlYipNNGoeg8uHc\\\\u003d\\\",\\\"ephemeralPublicKey\\\":\\\"BMqIyb1IyXhuZ4YpWm1PiRr74i3tCwDfQqJ1P4OZ3zK4Rq16SuwgJ605fCEvlViwSQuo2Hpv+CcR+2D3+/YrLB8\\\\u003d\\\",\\\"tag\\\":\\\"5K4LlTucDK7jAThbIozYtyoxX95hRNd5cJJGfxWAxw8\\\\u003d\\\"}\"}",
    "type": "GOOGLE_PAY"
  }'

A successful request returns the newly created Payment Instrument, which you use to process the payment.

Payment Instrument - Google Pay
{
  "id": "PIwpqpJZCharsZAt6WKVopPS",
  "created_at": "2025-05-08T18:44:58.56Z",
  "updated_at": "2025-05-08T18:44:58.56Z",
  "application": "APc9vhYcPsRuTSpKD9KpMtPe",
  "created_via": "API",
  "currency": "USD",
  "disabled_code": null,
  "disabled_message": null,
  "enabled": true,
  "fingerprint": "FPR88YBDbK4TqYMUNU8t8fbeQ",
  "identity": "IDmj1yA97RS4rMjiQgvK3Vio",
  "instrument_type": "APPLE_PAY",
  "address": {
    "line1": "900 Metro Center Blv",
    "line2": "APT 200",
    "city": "San Francisco",
    "region": "CA",
    "postal_code": "94404",
    "country": "USA"
  },
  "bin": "370382",
  "brand": "AMERICAN_EXPRESS",
  "card_type": "CREDIT",
  "expiration_month": 11,
  "expiration_year": 2024,
  "issuer_country": "USA",
  "last_four": "8576",
  "name": "John Smith",
  "tags": {},
  "third_party": null,
  "third_party_token": null,
  "type": "GOOGLE_PAY",
  "_links": {
    "self": {
      "href": "https://finix.sandbox-payments-api.com/payment_instruments/PIwpqpJZCharsZAt6WKVopPS"
    },
    "authorizations": {
      "href": "https://finix.sandbox-payments-api.com/payment_instruments/PIwpqpJZCharsZAt6WKVopPS/authorizations"
    },
    "transfers": {
      "href": "https://finix.sandbox-payments-api.com/payment_instruments/PIwpqpJZCharsZAt6WKVopPS/transfers"
    },
    "verifications": {
      "href": "https://finix.sandbox-payments-api.com/payment_instruments/PIwpqpJZCharsZAt6WKVopPS/verifications"
    },
    "application": {
      "href": "https://finix.sandbox-payments-api.com/applications/APc9vhYcPsRuTSpKD9KpMtPe"
    },
    "identity": {
      "href": "https://finix.sandbox-payments-api.com/identities/IDmj1yA97RS4rMjiQgvK3Vio"
    }
  }
}

For security, Google Pay tokens are active for only a short period of time. The third_party_token in the request above has expired. To test the request, use your own third_party_token and Finix credentials.

Step 11: Create a payment

After the Payment Instrument is created, use it to create a Transfer or an Authorization, the same as any other Finix transaction.

To process a sale:

  1. Set the source to the buyer's Payment Instrument ID.
  2. Set the merchant to an APPROVED Merchant account.
  3. Set the amount in cents.
Example Transfer Request
curl https://finix.sandbox-payments-api.com/transfers \
    -H "Content-Type: application/json" \
    -H 'Finix-Version: 2022-02-01' \
    -u  USsRhsHYZGBPnQw8CByJyEQW:8a14c2f9-d94b-4c72-8f5c-a62908e5b30e \
    -d '{
        "merchant": "MUeDVrf2ahuKc9Eg5TeZugvs",
        "currency": "USD",
        "amount": 662154,
        "source": "PIwpqpJZCharsZAt6WKVopPS"
    }'
Example Transfer Response
{
  "id": "TR29av3LN1TAGPbXscsup1tt",
  "amount": 662154,
  "tags": {},
  "state": "SUCCEEDED",
  "trace_id": "34f40e87-2599-414b-874b-f472790ff521",
  "currency": "USD",
  "application": "APgPDQrLD52TYvqazjHJJchM",
  "source": "PIwpqpJZCharsZAt6WKVopPS",
  "destination": null,
  "ready_to_settle_at": null,
  "externally_funded": "UNKNOWN",
  "fee": 0,
  "statement_descriptor": "FNX*FINIX FLOWERS",
  "type": "DEBIT",
  "messages": [],
  "raw": null,
  "created_at": "2022-08-25T20:39:37.59Z",
  "updated_at": "2022-08-25T20:39:38.17Z",
  "idempotency_id": null,
  "merchant": "MUeDVrf2ahuKc9Eg5TeZugvs",
  "merchant_identity": "IDpYDM7J9n57q849o9E9yNrG",
  "subtype": "API",
  "failure_code": null,
  "failure_message": null,
  "additional_buyer_charges": null,
  "_links": {
    "application": {
      "href": "https://finix.sandbox-payments-api.com/applications/APgPDQrLD52TYvqazjHJJchM"
    },
    "self": {
      "href": "https://finix.sandbox-payments-api.com/transfers/TR29av3LN1TAGPbXscsup1tt"
    },
    "merchant_identity": {
      "href": "https://finix.sandbox-payments-api.com/identities/IDpYDM7J9n57q849o9E9yNrG"
    },
    "payment_instruments": {
      "href": "https://finix.sandbox-payments-api.com/transfers/TR29av3LN1TAGPbXscsup1tt/payment_instruments"
    },
    "reversals": {
      "href": "https://finix.sandbox-payments-api.com/transfers/TR29av3LN1TAGPbXscsup1tt/reversals"
    },
    "fees": {
      "href": "https://finix.sandbox-payments-api.com/transfers/TR29av3LN1TAGPbXscsup1tt/fees"
    },
    "disputes": {
      "href": "https://finix.sandbox-payments-api.com/transfers/TR29av3LN1TAGPbXscsup1tt/disputes"
    },
    "source": {
      "href": "https://finix.sandbox-payments-api.com/payment_instruments/PIwpqpJZCharsZAt6WKVopPS"
    },
    "fee_profile": {
      "href": "https://finix.sandbox-payments-api.com/fee_profiles/FPvCQUcnsueN3Bc3zR1qCBG8"
    }
  }
}

Alternatively, create an Authorization and capture it later with two separate API calls. This is useful when you need to verify the payment details first and capture a specific amount later. For more information, see Creating and capturing an Authorization.

Next steps