Google Pay API für Jetpack Compose unter Android

1. Einführung

Aufgaben

Am Ende dieses Codelabs haben Sie eine minimal funktionsfähige Jetpack Compose-App mit einer funktionierenden Google Pay-Integration für Android. In diesem Projekt wird ein Zahlungstoken abgerufen, das zur Verarbeitung an einen Zahlungsdienstleister gesendet werden kann.

Lerninhalte

  • Google Pay Jetpack Compose-Bibliothek installieren und konfigurieren
  • Google Pay-Schaltfläche anzeigen und Klicks verarbeiten
  • Zahlungstoken von Google Pay anfordern

Voraussetzungen

  • Die aktuelle stabile Version von Android Studio ist installiert.
  • Android SDK und ein in Android Studio eingerichteter Emulator oder ein Gerät.
  • Für die Produktion benötigen Sie ein Google Pay-merchantId. Die Registrierung in der Google Pay & Wallet Console dauert nur eine Minute. Sie können sie also gleich erledigen.

2. Jetpack Compose-Projekt erstellen

Projektdateien erstellen

  1. Erstellen Sie in Android Studio ein neues Jetpack Compose-Projekt mit dem Namen gpay-compose:
    • Öffnen Sie Android Studio und wählen Sie New Project aus.
    • Wählen Sie die Vorlage Empty Activity (Jetpack Compose) aus.
    • Name: gpay-compose, Paketname: com.example.gpay.
    • Sprache: Kotlin, Minimum SDK: API 21+.
    • Warten Sie, bis das Projekt generiert wurde.
  2. Fügen Sie die Google Pay Compose-Schaltflächenabhängigkeit hinzu.Fügen Sie in Ihrer app/build.gradle(.kts)-Datei Folgendes hinzu:
    dependencies {
        implementation("com.google.pay.button:compose-pay-button:1.2.0")
    }
    
    Groovy-DSL:
    dependencies {
        implementation 'com.google.pay.button:compose-pay-button:1.2.0'
    }
    
  3. Google Play-Dienste-Wallet-Abhängigkeit hinzufügen (um das Google Pay-Sheet zu öffnen):Fügen Sie in Ihrer app/build.gradle(.kts)-Datei die folgende Abhängigkeit hinzu:
    dependencies {
        implementation("com.google.android.gms:play-services-wallet:19.5.0")
    }
    
    Wenn Ihr Projekt die Groovy-DSL verwendet, verwenden Sie:
    dependencies {
        implementation 'com.google.android.gms:play-services-wallet:19.5.0'
    }
    
  4. Öffnen Sie MainActivity.kt in Android Studio und ersetzen Sie den Inhalt durch das folgende minimale Compose-App-Gerüst. Wir werden die Schaltfläche als Nächstes einbinden:
    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 konfigurieren

Für eine Google Pay-Zahlungsanfrage ist ein Anfrageobjekt erforderlich. Das hier als baseGooglePayRequest definierte Objekt enthält die minimalen gemeinsamen Einstellungen für alle Anfragen. Je nach Anfrage werden zusätzliche Einstellungen hinzugefügt, die wir in diesem Codelab näher betrachten.

Fügen Sie die Google Pay-Konstanten zu MainActivity.kt hinzu. Sie werden sie im nächsten Schritt wiederverwenden:

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

Ressourcen

  • API-Referenz: Dokumentation zu Anfrageobjekten der Google Pay API
  • API-Referenz: Weitere Informationen zu den zulässigen Autorisierungsmethoden, zulässigen Kartennetzwerken und Tokenisierungsspezifikationen, einschließlich des richtigen Gateway-Werts, finden Sie unter PaymentMethod.

4. Google Pay-Button hinzufügen

Verwenden Sie die Compose Pay-Schaltfläche, um eine native Google Pay-Schaltfläche zu rendern, und die Wallet API, um das Google Pay-Sheet zu öffnen.

Ersetzen Sie den gesamten Inhalt von MainActivity.kt durch das folgende vollständige Beispiel (Konfiguration + Schaltfläche + Zahlungsablauf):

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. Zahlungsaufforderung senden

Wenn die Google Pay-Schaltfläche gedrückt wird, erstellt requestPayment(...) ein PaymentDataRequest, indem transactionInfo zu Ihrem baseGooglePayRequest hinzugefügt wird, öffnet das Google Pay-Sheet und gibt ein Zahlungstoken zurück.

Wichtige Fakten

  • Schaltfläche: Mit PayButton wird die native Google Pay-Schaltfläche gerendert.
  • Client: PaymentsClient ist mit TEST oder PRODUCTION konfiguriert.
  • Start: Verwenden Sie loadPaymentData und beheben Sie das Problem bei Bedarf mit IntentSender.
  • Token: Parsen Sie PaymentData.toJson(), um paymentMethodData.tokenizationData.token zu extrahieren und an Ihren Zahlungsdienstleister zu senden.

6. Fazit

Sie haben dieses Codelab abgeschlossen. Sie haben gelernt, wie Sie die Google Pay API in eine Jetpack Compose-App für Android einbinden.

Projekt ausführen

Führen Sie das Projekt in Android Studio Run > Run 'app' aus, um die App zu starten.

So geht es weiter

Zusätzliche Ressourcen