API Google Pay для Jetpack Compose на Android

1. Введение

Что вы построите

По завершении этого практического занятия у вас будет минимально работоспособное приложение Jetpack Compose с интеграцией Google Pay для Android. Этот проект получает платежный токен, который может быть отправлен поставщику платежных услуг для обработки.

Что вы узнаете

  • Как установить и настроить библиотеку Google Pay Jetpack Compose
  • Как отобразить кнопку Google Pay и обрабатывать клики.
  • Как запросить платежный токен в Google Pay

Что вам понадобится

  • Установлена ​​версия Android Studio (последняя стабильная).
  • Android SDK и эмулятор или устройство, настроенные в Android Studio.
  • Для запуска в производство вам потребуется merchantId Google Pay. Регистрация в консоли Google Pay & Wallet займет всего минуту, так что можете позаботиться об этом прямо сейчас.

2. Создайте проект Jetpack Compose.

Создайте файлы проекта

  1. Создайте в Android Studio новый проект Jetpack Compose с именем gpay-compose :
    • Откройте Android Studio и выберите New Project .
    • Выберите шаблон « Empty Activity (Jetpack Compose) .
    • Имя: gpay-compose , Имя пакета: com.example.gpay .
    • Язык программирования: Kotlin, минимальный набор SDK: API 21+.
    • Завершите процесс, чтобы сгенерировать проект.
  2. Добавьте зависимость кнопки «Оформить заказ» от Google Pay. В файл app/build.gradle(.kts) добавьте:
    dependencies {
        implementation("com.google.pay.button:compose-pay-button:1.0.0")
    }
    
    Groovy DSL:
    dependencies {
        implementation 'com.google.pay.button:compose-pay-button:1.0.0'
    }
    
  3. Добавьте зависимость Google Play Services Wallet (для открытия окна Google Pay): В файле app/build.gradle(.kts) добавьте следующую зависимость:
    dependencies {
        implementation("com.google.android.gms:play-services-wallet:19.3.0")
    }
    
    Если в вашем проекте используется Groovy DSL, используйте:
    dependencies {
        implementation 'com.google.android.gms:play-services-wallet:19.3.0'
    }
    
  4. Откройте MainActivity.kt в Android Studio и замените его содержимое следующим минимальным шаблоном приложения Compose (кнопку мы добавим позже):
    package com.example.gpay
    
    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.compose.foundation.layout.Box
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.material3.MaterialTheme
    import androidx.compose.material3.Surface
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                        // Google Pay button added in the next section
                    }
                }
            }
        }
    }
    

3. Настройка Google Pay

Для отправки платежа через Google Pay требуется объект запроса. Объект, определенный здесь как baseGooglePayRequest содержит минимальные общие настройки для всех запросов. Дополнительные настройки будут добавляться в зависимости от сделанного запроса, что мы рассмотрим в этом практическом занятии.

Добавьте константы конфигурации Google Pay в MainActivity.kt (вы будете использовать их повторно на следующем шаге):

private const val merchantId = "12345678901234567890"

// This is the base configuration for all Google Pay payment data requests.
private val baseGooglePayRequest = """
    {
      "apiVersion": 2,
      "apiVersionMinor": 0,
      "allowedPaymentMethods": [
        {
          "type": "CARD",
          "parameters": {
            "allowedAuthMethods": [
              "PAN_ONLY", "CRYPTOGRAM_3DS"
            ],
            "allowedCardNetworks": [
              "AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"
            ]
          },
          "tokenizationSpecification": {
            "type": "PAYMENT_GATEWAY",
            "parameters": {
              "gateway": "example",
              "gatewayMerchantId": "exampleGatewayMerchantId"
            }
          }
        }
      ],
      "merchantInfo": {
        "merchantId": "$merchantId"
      }
    }
""".trimIndent()

Ресурсы

  • Справочник по API : документация по объектам запросов API Google Pay.
  • Справочник API : Для получения дополнительной информации о разрешенных методах авторизации, разрешенных платежных сетях и спецификациях токенизации, включая правильное значение платежного шлюза, обратитесь к разделу PaymentMethod

4. Добавьте кнопку Google Pay.

Используйте кнопку «Создать платеж», чтобы отобразить стандартную кнопку Google Pay, и API Wallet, чтобы открыть окно Google Pay.

Замените всё содержимое файла MainActivity.kt следующим полным примером (включая конфигурацию + кнопку + процесс оплаты):

package com.example.gpay

import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.tasks.Task
import com.google.android.gms.wallet.contract.TaskResultContracts.GetPaymentDataResult
import com.google.android.gms.wallet.*
import com.google.pay.button.ButtonTheme
import com.google.pay.button.ButtonType
import com.google.pay.button.PayButton
import org.json.JSONObject

private const val merchantId = "12345678901234567890"

// Base Google Pay request used for both the button and the Wallet request
private val baseGooglePayRequest = """
    {
      "apiVersion": 2,
      "apiVersionMinor": 0,
      "allowedPaymentMethods": [
        {
          "type": "CARD",
          "parameters": {
            "allowedAuthMethods": [
              "PAN_ONLY", "CRYPTOGRAM_3DS"
            ],
            "allowedCardNetworks": [
              "AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"
            ]
          },
          "tokenizationSpecification": {
            "type": "PAYMENT_GATEWAY",
            "parameters": {
              "gateway": "example",
              "gatewayMerchantId": "exampleGatewayMerchantId"
            }
          }
        }
      ],
      "merchantInfo": {
        "merchantId": "$merchantId"
      }
    }
""".trimIndent()

class MainActivity : ComponentActivity() {
  private val paymentDataLauncher = registerForActivityResult(GetPaymentDataResult()) { taskResult ->
    when (taskResult.status.statusCode) {
      CommonStatusCodes.SUCCESS -> {
        handlePaymentData(taskResult.result!!)
      }
      //CommonStatusCodes.CANCELED -> The user canceled
      //CommonStatusCodes.DEVELOPER_ERROR -> The API returned an error (it.status: Status)
      //else -> Handle internal and other unexpected errors
    }
  }
  private lateinit var paymentsClient: PaymentsClient

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Create the PaymentsClient
    paymentsClient = Wallet.getPaymentsClient(
      this,
      Wallet.WalletOptions.Builder()
        .setEnvironment(WalletConstants.ENVIRONMENT_TEST) // Switch to PRODUCTION when ready
        .build()
    )

    // Derive allowedPaymentMethods for the button from baseGooglePayRequest
    val allowedPaymentMethods = JSONObject(baseGooglePayRequest)
      .getJSONArray("allowedPaymentMethods")
      .toString()

    setContent {
      Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        PayButton(
          onClick = { requestPayment(paymentDataLauncher) },
          allowedPaymentMethods = allowedPaymentMethods,
          type = ButtonType.Pay,
          theme = ButtonTheme.Light
        )
      }
    }
  }

  private fun requestPayment(launcher: ActivityResultLauncher<Task<PaymentData>>) {
    // Build a PaymentDataRequest from the base request by adding transaction info
    val requestJson = JSONObject(baseGooglePayRequest).apply {
      put("transactionInfo", JSONObject().apply {
        put("totalPrice", "14.95")
        put("totalPriceStatus", "FINAL")
        put("countryCode", "US")
        put("currencyCode", "USD")
      })
    }
    val request = PaymentDataRequest.fromJson(requestJson.toString())
    val task = paymentsClient.loadPaymentData(request)
    task.addOnCompleteListener(paymentDataLauncher::launch)
  }

  private fun handlePaymentData(paymentData: PaymentData?) {
    val json = paymentData?.toJson() ?: return
    val paymentMethodData = JSONObject(json).getJSONObject("paymentMethodData")
    val tokenizationData = paymentMethodData.getJSONObject("tokenizationData")
    val token = tokenizationData.getString("token")
    // Send 'token' to your payment service provider (PSP)
    println("Payment token: $token")
  }
}

5. Отправьте запрос на оплату.

При нажатии кнопки Google Pay requestPayment(...) формирует объект PaymentDataRequest , добавляя transactionInfo к вашему baseGooglePayRequest , открывает окно Google Pay и возвращает платежный токен.

Ключевые моменты

  • Button: PayButton отображает стандартную кнопку Google Pay.
  • Клиент: PaymentsClient настроен на тестовую или производственную среду.
  • Запуск: Используйте loadPaymentData и при необходимости вызовите IntentSender .
  • Токен: Используйте метод Pars PaymentData.toJson() для извлечения paymentMethodData.tokenizationData.token и отправки их в вашу платежную систему.

6. Заключение

Поздравляем с завершением этого практического занятия! Вы научились интегрировать API Google Pay в приложение Jetpack Compose для Android.

Запустите проект

Запустите проект из Android Studio ( Run > Run 'app' ), чтобы запустить приложение.

Что делать дальше?

Дополнительные ресурсы

  • Присоединяйтесь к обсуждению в канале #payments в Discord.
  • Подписывайтесь на @GooglePayDevs в X
  • Смотрите видеоролики, посвященные Google Pay, на YouTube.