💳 Google Pay Integration Guide for Android Developers
Integrating Google Pay into your Android app can dramatically improve user experience by offering a seamless, secure, and fast checkout process. In this guide, I'll walk you through the complete integration process — from setup to implementation — to help you get Google Pay running in your app smoothly.
🚀 Why Google Pay?
Google Pay offers:
🧰 Prerequisites
Before diving into code, ensure:
⚙️ Step 1: Add Required Dependencies
Update your build.gradle file:
//google pay
implementation(libs.play.services.wallet)
implementation(libs.compose.pay.button)
implementation(libs.kotlinx.coroutines.play.services)
in the libs.versions.toml
composePayButton = "1.0.0"
playServicesWallet = "19.4.0"
kotlinxCoroutinesPlayServices = "1.10.2"
🏗️ Step 2: Configure Your App Manifest
Add the Wallet permissions and required services:
<uses-permission android:name="android.permission.INTERNET"/>
<application>
<meta-data
android:name="com.google.android.gms.wallet.api.enabled"
android:value="true" />
</application>
🔐 Step 3: Create Your Payment Configuration
The payment configuration defines what payment methods your app supports, merchant information, and transaction parameters. To keep the integration clean and maintainable, it’s best to create a reusable utility — like PaymentsUtil — that handles this setup.
object Constants {
const val PAYMENTS_ENVIRONMENT = WalletConstants.ENVIRONMENT_PRODUCTION // Use TEST for dev
val SUPPORTED_NETWORKS = listOf("AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA")
val SUPPORTED_METHODS = listOf("PAN_ONLY", "CRYPTOGRAM_3DS")
const val COUNTRY_CODE = "EG"
const val CURRENCY_CODE = "EGP"
val SHIPPING_SUPPORTED_COUNTRIES = listOf("US", "GB")
private const val PAYMENT_GATEWAY_TOKENIZATION_NAME = "example" // Replace with actual gateway
val PAYMENT_GATEWAY_TOKENIZATION_PARAMETERS = mapOf(
"gateway" to PAYMENT_GATEWAY_TOKENIZATION_NAME,
"gatewayMerchantId" to "gatewayMerchantId"
)
const val DIRECT_TOKENIZATION_PUBLIC_KEY = "REPLACE_ME"
val DIRECT_TOKENIZATION_PARAMETERS = mapOf(
"protocolVersion" to "ECv1",
"publicKey" to DIRECT_TOKENIZATION_PUBLIC_KEY
)
}
🧠 Understanding apiVersion and apiVersionMinor
These fields define the version of the Google Pay API protocol your app uses:
val baseRequest = JSONObject()
.put("apiVersion", 2)
.put("apiVersionMinor", 0)
No need to change these unless specifically instructed in the documentation.
🧰 2. Create the PaymentsUtil Helper
A Kotlin object simplifies managing all Google Pay setup logic.
a. Define Allowed Card Methods
val allowedCardNetworks = JSONArray(Constants.SUPPORTED_NETWORKS)
val allowedCardAuthMethods = JSONArray(Constants.SUPPORTED_METHODS)
b. Set Up Tokenization (Gateway or Direct)
Recommended by LinkedIn
val gatewayTokenizationSpecification = JSONObject()
.put("type", "PAYMENT_GATEWAY")
.put("parameters", JSONObject(Constants.PAYMENT_GATEWAY_TOKENIZATION_PARAMETERS))
💡 Replace with DIRECT if you're doing direct integration with your own processor.
c. Describe the Card Payment Method
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")
)
)
🛍️ 3. Define Merchant and Transaction Info
private val merchantInfo = JSONObject().put("merchantName", "merchantName")
private fun getTransactionInfo(price: String): JSONObject = JSONObject()
.put("totalPrice", price)
.put("totalPriceStatus", "FINAL")
.put("countryCode", Constants.COUNTRY_CODE)
.put("currencyCode", Constants.CURRENCY_CODE)
🧾 4. Construct the Payment Data Request
This builds the final PaymentDataRequest object Google Pay uses:
fun getPaymentDataRequest(priceLabel: String): JSONObject =
baseRequest
.put("allowedPaymentMethods", JSONArray().put(
baseCardPaymentMethod().put("tokenizationSpecification", gatewayTokenizationSpecification)
))
.put("transactionInfo", getTransactionInfo(priceLabel))
.put("merchantInfo", merchantInfo)
.put("shippingAddressRequired", true)
.put("shippingAddressParameters", JSONObject()
.put("phoneNumberRequired", false)
.put("allowedCountryCodes", JSONArray(Constants.SHIPPING_SUPPORTED_COUNTRIES))
)
💻 Create a PaymentsClient instance:
val walletOptions = Wallet.WalletOptions.Builder()
.setEnvironment(WalletConstants.ENVIRONMENT_TEST) // Use PRODUCTION for release
.build()
val paymentsClient = Wallet.getPaymentsClient(context, walletOptions)
Check if Google Pay is available:
val isReadyToPayJson = JSONObject().apply {
put("apiVersion", 2)
put("apiVersionMinor", 0)
put("allowedPaymentMethods", JSONArray().apply {
put(JSONObject().apply {
put("type", "CARD")
put("parameters", JSONObject().apply {
put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
})
})
})
}
val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString())
paymentsClient.isReadyToPay(request)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
// Show Google Pay button
} else {
// Fallback UI
}
}
🛒 Launch the Google Pay Payment Sheet
val paymentDataRequestJson = loadPaymentDataRequest() // Load JSON from payments.json
val paymentDataRequest = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
AutoResolveHelper.resolveTask(
paymentsClient.loadPaymentData(paymentDataRequest),
activity,
LOAD_PAYMENT_DATA_REQUEST_CODE
)
🧾 Handle the Result in onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
LOAD_PAYMENT_DATA_REQUEST_CODE -> {
when (resultCode) {
Activity.RESULT_OK -> {
val paymentData = PaymentData.getFromIntent(data!!)
val json = paymentData?.toJson()
// Send payment info to your backend to complete transaction
}
Activity.RESULT_CANCELED -> {
// User canceled
}
AutoResolveHelper.RESULT_ERROR -> {
val status = AutoResolveHelper.getStatusFromIntent(data)
Log.e("GooglePay", "Error: ${status?.statusMessage}")
}
}
}
}
}
✅ Go Live
Before publishing:
🧪 Testing Tips
🔍 Debugging Common Issues
📦 Conclusion
Adding Google Pay support to your Android app can improve checkout speed and trust. The process is straightforward with good planning and testing. If you run into issues, the Google Pay Developer Documentation is a great reference.
عاش يا جو ❤️
Great work ya youssef,thanks for sharing
كلام متعوب عليه بجد ❤️