Accept Google Pay in your Android application using Finix.
This guide details how to get started accepting Google Pay on Android devices using Finix.
We recommend that you pass the address field listed in the steps below. If the address is not passed, you will be charged additional dues and assessments per transaction from the card network.
Start by familiarizing yourself with the prerequisites for using Google Pay with Finix.
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 properties that are present in all other request objects.
private val baseRequest = JSONObject()
.put("apiVersion", 2)
.put("apiVersionMinor", 0)
Now that you've defined your Google Pay API Version, request a Finix payment token.
gateway
should be set tofinix
gatewayMerchantId
should be set to the application owner identity or merchant owner identity. To choose the appropriate Identity ID, see Choose Merchant Identifier Value.
private fun gatewayTokenizationSpecification(): JSONObject {
return JSONObject().apply {
put("type", "PAYMENT_GATEWAY")
put("parameters", JSONObject(mapOf(
"gateway" to "finix",
"gatewayMerchantId" to "IDxxx")))
}
}
Now that we've requested a Finix payment token, you can set which card networks will be accepted on your site.
private val allowedCardNetworks = JSONArray(listOf(
"AMEX",
"DISCOVER",
"INTERAC",
"JCB",
"MASTERCARD",
"VISA"))
Defining allowedCardAuthMethods
sets the authentication methods supported by your site and gateway.
private val allowedCardAuthMethods = JSONArray(listOf(
"PAN_ONLY",
"CRYPTOGRAM_3DS"))
For both PAN_ONLY
and CRYPTOGRAM_3DS
authorization methods, support for 3D Secure is dictated by the processors you integrate with in allowedCardNetworks
. Finix accepts both PAN_ONLY
and CRYPTOGRAM_3DS
authorization methods.
After you've defined the supported payment card networks, you need to describe your allowed payment methods. You can do this with the following steps:
- Combine
allowedAuthMethods
andallowedCardNetworks
to describe how your application supports theCARD
payment method. - Extend the
baseCardPaymentMethod
object and describe the information you expect to be returned to your application. Include a description of the tokenized payment data.
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)
Create a PaymentsClient
instance to interact with the Google Pay API.
fun createPaymentsClient(context: Context): PaymentsClient {
val walletOptions = Wallet.WalletOptions.Builder()
.setEnvironment(Constants.PAYMENTS_ENVIRONMENT)
.build()
return Wallet.getPaymentsClient(context, walletOptions)
}
Now that you've described your allowed payment methods, you need to check readiness to pay with the Google Pay API. To check readiness to pay with Google Pay's API:
- Add
allowedPaymentMethods
to thebaseRequest
object. - Call
isReadyToPay()
to determine if the user can make payments with the Google Pay API.
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)
}
}
}
Now that you've checked readiness to pay with Google Pay API, you can add a Google Pay payment button to your website.
- For information about the different button types and display requirements, see Google's Brand guidelines.
- To try all the different Google Pay buttons, see Google Pay's interactive demo.
PayButton(
modifier = Modifier
.testTag("payButton")
.fillMaxWidth(),
onClick = onGooglePayButtonClick,
allowedPaymentMethods = PaymentsUtil.allowedPaymentMethods.toString()
)
Note: 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’re adding the Google Pay button via XML, be sure to initialize it in your Android activity along with other UI elements.
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))
}
After creating a Google Pay payment button, you need to create a PaymentDataRequest
object. The PaymentDataRequest
takes in information about the merchant and transaction which is required to start the payment process with Google Pay.
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")
Field | Type | Description |
---|---|---|
countryCode | string, required | The ISO country code. |
currencyCode | string, required | The currency code of the locale. |
totalPrice | string, required | Total value of the transaction with an optional decimal precision of two decimal places. |
totalPriceStatus | string, required | The status of the total price used.
|
Field | Type | Description |
---|---|---|
merchantID | string, required | A Google merchant identifier issued after registration with the Google Pay Business Console. Required when PaymentsClient is initialized with an environment property of LIVE |
merchantName | string, required | Pass in the name of the Merchant . |
Merchants that process transactions in the European Economic Area (EEA) or any other countries that are 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 supported by your application, such as any configuration of additional data expected in the response. Finally, add information about the transaction and the merchant who makes the request. For more information, see Step 5 of Google Pay Integration
A buyer identity is required before you can proceed with the next steps. You can either create a new buyer identity through the Finix API, or use an existing one you’ve already created.
All buyer Identity fields are optional. However, Finix recommends including basic information (name, email, address, and phone) to make payment operations easier.
Use an existing buyer
- Log in to your Finix Dashboard.
- In the left sidebar, select Data Resources → Identities.
- Search for the buyer identity you want to use.
- Confirm the Role is Buyer.
- Option to use filters to quickly narrow down results.
- Copy the Buyer Identity (e.g.
IDjWktr7BPDGhz4amrPJZoXg
)
Create a new buyer
curl -i -X POST \
-u USfdccsr1Z5iVbXDyYt7hjZZ:313636f3-fac2-45a7-bff7-a334b93e7bda \
https://finix.sandbox-payments-api.com/identities \
-H 'Content-Type: application/json' \
-H 'Finix-Version: 2022-02-01' \
-d '{
"entity": {
"phone": "7145677613",
"first_name": "John",
"last_name": "Smith",
"email": "finix_example@finix.com",
"personal_address": {
"city": "San Mateo",
"country": "USA",
"region": "CA",
"line2": "Apartment 7",
"line1": "741 Douglass St",
"postal_code": "94114"
}
},
"identity_roles": [
"BUYER"
],
"tags": {
"key": "value"
},
"type": "PERSONAL"
}'
{
"id": "IDmkDvJfxZWMEK56FDFtbozo",
"created_at": "2024-08-09T09:34:36.87Z",
"updated_at": "2024-08-09T09:34:36.87Z",
"application": "APgPDQrLD52TYvqazjHJJchM",
"entity": {
"ach_max_transaction_amount": 0,
"amex_mid": null,
"annual_card_volume": 0,
"business_address": null,
"business_name": null,
"business_phone": null,
"business_tax_id_provided": false,
"business_type": null,
"default_statement_descriptor": null,
"discover_mid": null,
"dob": null,
"doing_business_as": null,
"email": "finix_example@finix.com",
"first_name": "John",
"has_accepted_credit_cards_previously": false,
"incorporation_date": null,
"last_name": "Smith",
"max_transaction_amount": 0,
"mcc": null,
"ownership_type": null,
"personal_address": {
"line1": "741 Douglass St",
"line2": "Apartment 7",
"city": "San Mateo",
"region": "CA",
"postal_code": "94114",
"country": "USA"
},
"phone": "7145677613",
"principal_percentage_ownership": null,
"short_business_name": null,
"tax_authority": null,
"tax_id_provided": false,
"title": null,
"url": null
},
"identity_roles": [],
"tags": {
"key": "value"
},
"type": "PERSONAL",
"_links": {
"self": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo"
},
"verifications": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/verifications"
},
"merchants": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/merchants"
},
"settlements": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/settlements"
},
"authorizations": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/authorizations"
},
"transfers": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/transfers"
},
"payment_instruments": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/payment_instruments"
},
"associated_identities": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/associated_identities"
},
"disputes": {
"href": "https://finix.sandbox-payments-api.com/identities/IDmkDvJfxZWMEK56FDFtbozo/disputes"
},
"application": {
"href": "https://finix.sandbox-payments-api.com/applications/APgPDQrLD52TYvqazjHJJchM"
}
}
}
Call loadPaymentData
using the Google Pay PaymentsClient
object, which results in a Task
object. Extract the payment token from the PaymentData
result object. For more information, see Step 6 of Google Pay Integration
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 presenting the user with a confirmation of their purchase, extract the payment token from PaymentData
result object, and use it in the Payment Instrument request below.
You need to pass in the third_party_token
, name
, and billing address
that Google Pay returns when creating a Payment Instrument
.
Field | Type | Description |
---|---|---|
identity | string, required | ID of the Identity that the card should be associated with. Source: Buyer Identity (Step 10: Get Buyer Identity) |
merchant_identity | string, required | The merchant_identity_id used when registering the business with Apple Pay through our registration API. Source: Log in to Finix Dashboard → Developer → Finix Integration → Merchant Identity ID (e.g. IDwhCCvPwCDEmiFd8Be7pDzN ) |
name | string, required | Full name of the registered card holder. |
third_party_token | string, required | Stringified token provided by Google. Required to process Google Pay transactions. |
type | string, required | Use GOOGLE_PAY for type of Payment Instrument. |
address | object, optional | Object containing address data. If address is not passed, fees will apply. |
curl https://finix.sandbox-payments-api.com/payment_instruments \
-H 'Content-Type: application/json' \
-H 'Finix-Version: 2022-02-01' \
-u USsRhsHYZGBPnQw8CByJyEQW:8a14c2f9-d94b-4c72-8f5c-a62908e5b30e \
-d '{
"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",
"address": {
"country": "USA",
"postal_code": 12345
}
}'
{
"id": "PIf8dyFFcEGBqPhaG22hPyYs",
"created_at": "2022-10-10T05:36:55.27Z",
"updated_at": "2022-10-10T05:36:55.27Z",
"address": {
"city": null,
"country": "USA",
"line1": null,
"line2": null,
"postal_code": 12345,
"region": null
},
"application": "APeUfzF5qdNkBCtdgcf3333n",
"created_via": "API",
"currency": "USD",
"enabled": true,
"fingerprint": "FPRrcobjtdU98gr4sjiqYR1Qg",
"identity": "ID78Fh8mcnnzukVzbdoyex5y",
"instrument_type": "GOOGLE_PAY",
"bin": "411111",
"brand": "VISA",
"card_type": "UNKNOWN",
"expiration_month": 12,
"expiration_year": 2027,
"issuer_country": "UNKNOWN",
"last_four": "1111",
"name": "Finix Sandbox",
"tags": {},
"type": "GOOGLE_PAY",
"_links": {
"self": {
"href": "https://finix.sandbox-payments-api.com/payment_instruments/PIf8dyFFcEGBqPhaG22hPyYs"
},
"authorizations": {
"href": "https://finix.sandbox-payments-api.com/payment_instruments/PIf8dyFFcEGBqPhaG22hPyYs/authorizations"
},
"transfers": {
"href": "https://finix.sandbox-payments-api.com/payment_instruments/PIf8dyFFcEGBqPhaG22hPyYs/transfers"
},
"verifications": {
"href": "https://finix.sandbox-payments-api.com/payment_instruments/PIf8dyFFcEGBqPhaG22hPyYs/verifications"
},
"application": {
"href": "https://finix.sandbox-payments-api.com/applications/APeUfzF5qdNkBCtdgcf3333n"
},
"identity": {
"href": "https://finix.sandbox-payments-api.com/identities/ID78Fh8mcnnzukVzbdoyex5y"
}
}
}
For security purposes, Google Pay tokens are only active for a short period of time.
Due to this limited lifetime, the third_party_token
used in the request above has expired. To test the request, use your third_party_token
and Finix credentials.
Similar to other Finix transactions, after the Payment Instrument
is created, you can use the instrument and create a transfer
or an authorization
to process transactions.
- Set the
source
to your Buyer's Payment Instrument ID - Set the
merchant
to anAPPROVED
Merchant account - Set the
amount
in cents
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": "PIf8dyFFcEGBqPhaG22hPyYs",
}'
{
"id": "TR29av3LN1TAGPbXscsup1tt",
"amount": 662154,
"tags": {},
"state": "SUCCEEDED",
"trace_id": "34f40e87-2599-414b-874b-f472790ff521",
"currency": "USD",
"application": "APgPDQrLD52TYvqazjHJJchM",
"source": "PImE5ZhGZJNFy14DtX8wX6f6",
"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/IDuqZpDw28f2KK6YuDk4jNLg"
},
"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/PIe2YvpcjvoVJ6PzoRPBK137"
},
"fee_profile": {
"href": "https://finix.sandbox-payments-api.com/fee_profiles/FPvCQUcnsueN3Bc3zR1qCBG8"
}
}
}
You can create an Authorization and capture it later using two separate API calls. This approach is useful if you need to first verify the payment details and then capture a specific amount at a later time. For more details, see Creating and Capturing an Authorization.