Интеграция платежной системы Google Pay в мобильное приложение
Google Pay на Android работает через Google Pay API — это не отдельный SDK, а часть Google Play Services. Интеграция технически проще Apple Pay: нет сертификатов и отдельного developer portal, только конфигурация PaymentDataRequest и обработка токена. Но точек, где можно ошибиться, тоже достаточно.
PaymentsClient и среды ENVIRONMENT_TEST / ENVIRONMENT_PRODUCTION
Google Pay работает в двух средах. В ENVIRONMENT_TEST можно получать фиктивные токены без реальной карты — удобно для разработки. В ENVIRONMENT_PRODUCTION нужно предварительно пройти проверку Google (заполнить форму в Google Pay Business Console и получить одобрение).
private fun createPaymentsClient(activity: Activity): PaymentsClient {
val walletOptions = Wallet.WalletOptions.Builder()
.setEnvironment(WalletConstants.ENVIRONMENT_PRODUCTION)
.build()
return Wallet.getPaymentsClient(activity, walletOptions)
}
Настройка PaymentDataRequest
private fun createPaymentDataRequest(price: String): PaymentDataRequest {
val tokenizationSpec = JSONObject().apply {
put("type", "PAYMENT_GATEWAY")
put("parameters", JSONObject().apply {
put("gateway", "stripe") // или "cloudpayments", "yookassa" и т.д.
put("stripe:version", "2023-10-16")
put("stripe:publishableKey", "pk_live_...")
})
}
val cardPaymentMethod = JSONObject().apply {
put("type", "CARD")
put("parameters", JSONObject().apply {
put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
put("allowedCardNetworks", JSONArray(listOf("MASTERCARD", "VISA", "MIR")))
})
put("tokenizationSpecification", tokenizationSpec)
}
val request = JSONObject().apply {
put("apiVersion", 2)
put("apiVersionMinor", 0)
put("allowedPaymentMethods", JSONArray(listOf(cardPaymentMethod)))
put("transactionInfo", JSONObject().apply {
put("totalPrice", price)
put("totalPriceStatus", "FINAL")
put("currencyCode", "RUB")
put("countryCode", "RU")
})
put("merchantInfo", JSONObject().apply {
put("merchantName", "Your Company Name")
put("merchantId", "YOUR_MERCHANT_ID") // из Business Console
})
}
return PaymentDataRequest.fromJson(request.toString())
}
PAN_ONLY vs CRYPTOGRAM_3DS
Это часто вызывает вопросы. PAN_ONLY — карта добавлена в Google Pay через браузер или вручную, без 3DS-токена. CRYPTOGRAM_3DS — устройство с аппаратной защитой (SE или StrongBox), карта прошла токенизацию в Trusted Execution Environment. Для российских эквайеров оба метода поддерживаются, но уточните у провайдера — некоторые принимают только CRYPTOGRAM_3DS для снижения фрода.
Запуск платёжного интерфейса
private val paymentLauncher = registerForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
) { result ->
when (result.resultCode) {
Activity.RESULT_OK -> {
val data = result.data ?: return@registerForActivityResult
val paymentData = PaymentData.getFromIntent(data)
val token = paymentData
?.paymentMethodToken
?.token // JSON-строка с токеном провайдера
// Передаём token на бэкенд
}
Activity.RESULT_CANCELED -> { /* пользователь закрыл */ }
AutoResolveHelper.RESULT_ERROR -> {
val status = AutoResolveHelper.getStatusFromIntent(result.data)
Log.e("GPay", "Error: ${status?.statusMessage}")
}
}
}
// Запуск
val task = paymentsClient.loadPaymentData(createPaymentDataRequest("1500.00"))
task.addOnCompleteListener { completedTask ->
if (completedTask.isSuccessful) {
paymentLauncher.launch(
IntentSenderRequest.Builder(
completedTask.result.resolutionPendingIntent!!.intentSender
).build()
)
}
}
Кнопка Google Pay: требования дизайна
Google жёстко регулирует внешний вид кнопки. Нельзя менять цвет, шрифт, соотношение сторон кнопки Google Pay. Google проверяет это при ревью перед выходом в ENVIRONMENT_PRODUCTION.
Правильно использовать готовый виджет:
val button = PayButton(context).apply {
initialize(
ButtonOptions.newBuilder()
.setButtonType(ButtonType.BUY)
.setCornerRadius(8)
.build()
)
}
isReadyToPay перед показом кнопки
Не показывайте кнопку Google Pay без проверки:
val isReadyToPayRequest = IsReadyToPayRequest.fromJson(
JSONObject().apply {
put("apiVersion", 2)
put("apiVersionMinor", 0)
put("allowedPaymentMethods", JSONArray(listOf(cardPaymentMethod)))
}.toString()
)
paymentsClient.isReadyToPay(isReadyToPayRequest)
.addOnSuccessListener { result ->
googlePayButton.isVisible = result
}
Если карта не добавлена в Google Pay или устройство несовместимо — кнопку показывать не нужно.
Что входит в работу
- Настройка PaymentsClient с правильным environment
- Конфигурация tokenizationSpecification под платёжного провайдера
- Реализация isReadyToPay и корректное скрытие кнопки
- Обработка PaymentData и передача токена на бэкенд
- Прохождение ревью Google Pay Business Console
Сроки
2–3 дня. Стоимость рассчитывается индивидуально после анализа требований.







