I’m trying to implement a google pay method of paying in my android jetpack compose app, but I get this error “Payment failed: 6: BuyFlow UI needs to be shown” when I run my code. The message is clear and I thought I was doing that by calling this line “val task = paymentsClient.loadPaymentData(paymentDataRequest)”, but it seems it doesn’t work.
This is the code from my viewModel that gets called when I press on the button to “pay now”
private fun getTransactionInfo(price: String): JSONObject {
return JSONObject()
.put("totalPrice", price)
.put("totalPriceStatus", "FINAL")
.put("countryCode", "US") // Example country code (or use your specific country code)
.put("currencyCode", "USD") // Example currency code
}
private val merchantInfo: JSONObject =
JSONObject().put("merchantName", "ACME")
private fun getAllowedPaymentMethods(): JSONArray {
val allowedPaymentMethods = JSONArray()
val cardPaymentMethod = JSONObject()
.put("type", "CARD")
.put("parameters", JSONObject()
.put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
.put("allowedCardNetworks", JSONArray(listOf("AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"))))
.put("tokenizationSpecification", JSONObject()
.put("type", "PAYMENT_GATEWAY")
.put("parameters", JSONObject()
.put("gateway", "stripe")
.put("gatewayMerchantId", "The code from my google wallet console next to my company name")))
allowedPaymentMethods.put(cardPaymentMethod)
return allowedPaymentMethods
}
fun getPaymentDataRequest(priceLabel: String): JSONObject {
return JSONObject()
.put("apiVersion", 2) // API version for Google Pay
.put("apiVersionMinor", 0) // API minor version
.put("allowedPaymentMethods", getAllowedPaymentMethods()) // This function will return allowed payment methods JSON
.put("transactionInfo", getTransactionInfo(priceLabel))
.put("merchantInfo", merchantInfo)
.put("shippingAddressRequired", true) // Example: Set whether shipping address is required
.put("shippingAddressParameters", JSONObject()
.put("phoneNumberRequired", false)
.put("allowedCountryCodes", JSONArray(listOf("US", "GB")))) // Shipping address restrictions
}
fun getGooglePayPaymentToken(activity: Activity, price: Int) {
val walletOptions = WalletOptions.Builder()
.setEnvironment(WalletConstants.ENVIRONMENT_TEST) // or ENVIRONMENT_PRODUCTION for real payments
.build()
val paymentsClient = Wallet.getPaymentsClient(activity, walletOptions)
val isReadyToPayRequest = IsReadyToPayRequest.newBuilder()
.addAllowedPaymentMethod(WalletConstants.PAYMENT_METHOD_CARD)
.build()
val task = paymentsClient.isReadyToPay(isReadyToPayRequest)
task.addOnCompleteListener {
if (it.isSuccessful) {
val currency: String = "USD"
Log.i("paymentViewModel", " inside getGooglePayPaymentToken")
val paymentDataRequestJson = getPaymentDataRequest("12.34")
val paymentDataRequest = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
val task = paymentsClient.loadPaymentData(paymentDataRequest)
Log.i("paymentViewModel", " After load Payment data")
task.addOnCompleteListener { result: Task<PaymentData> ->
if (result.isSuccessful) {
Log.i("paymentViewModel", "Inside is succesful")
val paymentData = result.result
val paymentMethodNonce = paymentData?.paymentMethodToken?.token
if (paymentMethodNonce != null) {
// Send the Google Pay token to your backend
val googlePayPaymentObject =
GooglePayPaymentObject(price, currency, paymentMethodNonce)
initiateGooglePayPayment(price, googlePayPaymentObject)
} else {
// Handle error: No payment token received
Log.i("paymentViewModel", "Inside no token received")
}
} else {
// Handle error from Google Pay
Log.i("paymentViewModel", "Inside payment NOT successful")
Log.e("paymentViewModel", "Payment failed: ${result.exception?.message}")
// You can print the error message or inspect the exception for more details
result.exception?.printStackTrace() // Print the stack trace to log the error in more detail
}
}
}
}
}
So the code runs smoothly, the log statement “Log.i(“paymentViewModel”, ” After load Payment data”)” prints, but when I get to “task.addOnCompleteListener” it is not successful and this log statement prints the error “Log.e(“paymentViewModel”, “Payment failed ${result.exception?.message}”
I have juggled around with different ways to construct the “paymentDataRequest” i first tried with the deprecated “val paymentDataRequest = PaymentDataRequest.newBuilder()” and also with a custom data class to construct the paymentDataRequest, because I thought that the function val task = paymentsClient.loadPaymentData(paymentDataRequest) was having problem with the paymentDataRequest, but it didn’t work. Then I thought that I had a problem with my stripe configuration, but google pay is active and I have a verified domain id and I know that stripe works because I can pay with a test credit card and I don’t think the problem is there because the UI doesn’t load on my android app so i’m my code doesn’t even reach the stripe backend. So maybe there is a problem with my google pay api. I know that there is a section in the google pay and wallet console under google pay api that asks “Integrate with your Android app” but the link doesn’t work.