Android'de Jetpack Compose için Google Pay API'si

1. Giriş

Ne oluşturacaksınız?

Bu codelab'i tamamladığınızda, Android için çalışan bir Google Pay entegrasyonuna sahip, minimum düzeyde işlevsel bir Jetpack Compose uygulamanız olacak. Bu proje, işlenmek üzere bir ödeme hizmeti sağlayıcısına gönderilebilecek bir ödeme jetonu alır.

Neler öğreneceksiniz?

  • Google Pay Jetpack Compose kitaplığını yükleme ve yapılandırma
  • Google Pay düğmesini görüntüleme ve tıklamaları işleme
  • Google Pay'den ödeme jetonu isteme

İhtiyacınız olanlar

  • Android Studio'nun en son kararlı sürümü yüklü olmalıdır.
  • Android SDK ve Android Studio'da ayarlanmış bir emülatör veya cihaz.
  • Üretim için Google Pay merchantId gerekir. Google Pay ve Cüzdan Konsolu'na kaydolmak yalnızca bir dakika sürer. Bu nedenle, kaydınızı hemen yapabilirsiniz.

2. Jetpack Compose projesi oluşturma

Proje dosyaları oluşturma

  1. Android Studio'da gpay-compose adlı yeni bir Jetpack Compose projesi oluşturun:
    • Android Studio'yu açıp New Project simgesini seçin.
    • Empty Activity (Jetpack Compose) şablonunu seçin.
    • Ad: gpay-compose, Paket adı: com.example.gpay.
    • Dil: Kotlin, Minimum SDK: API 21 ve üzeri.
    • Projeyi oluşturmayı tamamlayın.
  2. Google Pay Compose Button bağımlılığını ekleyin.app/build.gradle(.kts) dosyanıza şunu ekleyin:
    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 Hizmetleri Cüzdan bağımlılığını ekleyin (Google Pay sayfasını açmak için):app/build.gradle(.kts) dosyanıza aşağıdaki bağımlılığı ekleyin:
    dependencies {
        implementation("com.google.android.gms:play-services-wallet:19.3.0")
    }
    
    Projenizde Groovy DSL kullanılıyorsa:
    dependencies {
        implementation 'com.google.android.gms:play-services-wallet:19.3.0'
    }
    
  4. Android Studio'da MainActivity.kt dosyasını açın ve içeriğini aşağıdaki minimum Compose uygulaması iskeletiyle değiştirin (düğmeyi daha sonra bağlayacağız):
    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'i yapılandırma

Google Pay ödeme isteği için istek nesnesi gerekir. Burada baseGooglePayRequest olarak tanımlanan nesne, tüm istekler için minimum ortak ayarları içerir. Yapılan isteğe bağlı olarak ek ayarlar eklenecektir. Bu ayarları bu codelab'de inceleyeceğiz.

Google Pay yapılandırma sabitlerini MainActivity.kt öğesine ekleyin (bunları sonraki adımda yeniden kullanacaksınız):

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()

Kaynaklar

  • API Referansı: Google Pay API istek nesneleri dokümanları
  • API Referansı: İzin verilen yetkilendirme yöntemleri, izin verilen kart ağları ve uygun ağ geçidi değeri de dahil olmak üzere belirteç oluşturma spesifikasyonları hakkında daha fazla bilgi için PaymentMethod bölümüne bakın.

4. Google Pay düğmesini ekleme

Yerel bir Google Pay düğmesi oluşturmak için Compose Pay Button'ı, Google Pay sayfasını açmak için ise Wallet API'yi kullanın.

MainActivity.kt'nın tüm içeriğini aşağıdaki tam örnekle değiştirin (yapılandırma + düğme + ödeme akışı dahil):

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. Ödeme isteğinde bulunma

Google Pay düğmesine basıldığında requestPayment(...), transactionInfo öğesini baseGooglePayRequest öğenize ekleyerek PaymentDataRequest oluşturur, Google Pay sayfasını açar ve bir ödeme jetonu döndürür.

Önemli noktalar

  • Button: PayButton, yerel Google Pay düğmesini oluşturur.
  • İstemci: PaymentsClient, TEST veya PRODUCTION ile yapılandırılmış.
  • Lansman: Gerekirse loadPaymentData kullanın ve IntentSender ile çözün.
  • Jeton: PaymentData.toJson() ayrıştırılarak paymentMethodData.tokenizationData.token çıkarılır ve ÖHP'nize gönderilir.

6. Sonuç

Bu Codelab'i tamamladığınız için tebrikler. Google Pay API'yi Android için bir Jetpack Compose uygulamasına nasıl entegre edeceğinizi öğrendiniz.

Projeyi yürütme

Uygulamanızı başlatmak için projeyi Android Studio'dan (Run > Run 'app') çalıştırın.

Şimdi beni ne bekliyor?

Ek kaynaklar