1. Wprowadzenie
Co utworzysz
Po ukończeniu tego modułu będziesz mieć minimalną działającą aplikację Jetpack Compose z działającą integracją Google Pay na Androida. Ten projekt pobiera token płatności, który może zostać wysłany do dostawcy usług płatniczych w celu przetworzenia.
Czego się nauczysz
- Instalowanie i konfigurowanie biblioteki Google Pay Jetpack Compose
- Wyświetlanie przycisku Google Pay i obsługa kliknięć
- Jak poprosić o token płatności w Google Pay
Czego potrzebujesz
- Zainstalowane Android Studio (najnowsza stabilna wersja).
- pakiet SDK Androida oraz emulator lub urządzenie skonfigurowane w Android Studio;
- W przypadku środowiska produkcyjnego potrzebujesz
merchantIdGoogle Pay. Rejestracja w Konsoli usług Google Pay i Portfela Google zajmuje tylko minutę, więc warto to zrobić od razu.
2. Tworzenie projektu Jetpack Compose
Tworzenie plików projektu
- Utwórz w Android Studio nowy projekt Jetpack Compose o nazwie
gpay-compose:- Otwórz Android Studio i kliknij
New Project. - Wybierz szablon
Empty Activity (Jetpack Compose). - Nazwa:
gpay-compose, nazwa pakietu:com.example.gpay. - Język: Kotlin, minimalna wersja SDK: API 21 lub nowsza.
- Zakończ, aby wygenerować projekt.
- Otwórz Android Studio i kliknij
- Dodaj zależność przycisku Google Pay Compose.W pliku
app/build.gradle(.kts)dodaj: Groovy DSL:dependencies { implementation("com.google.pay.button:compose-pay-button:1.0.0") }dependencies { implementation 'com.google.pay.button:compose-pay-button:1.0.0' } - Dodaj zależność Portfela w Usługach Google Play (aby otworzyć arkusz Google Pay):w pliku
app/build.gradle(.kts)dodaj tę zależność: Jeśli Twój projekt korzysta z Groovy DSL, użyj:dependencies { implementation("com.google.android.gms:play-services-wallet:19.3.0") }dependencies { implementation 'com.google.android.gms:play-services-wallet:19.3.0' } - Otwórz plik
MainActivity.ktw Android Studio i zastąp jego zawartość tym minimalnym szkieletem aplikacji Compose (przycisk połączymy później):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. Konfigurowanie Google Pay
Żądanie płatności Google Pay wymaga obiektu żądania. Obiekt zdefiniowany tutaj jako baseGooglePayRequest zawiera minimalne wspólne ustawienia wszystkich żądań. W zależności od zgłoszenia zostaną dodane dodatkowe ustawienia, które omówimy w tym laboratorium.
Dodaj do MainActivity.kt stałe konfiguracji Google Pay (użyjesz ich w następnym kroku):
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()
Zasoby
- Dokumentacja API: dokumentacja obiektów żądań interfejsu Google Pay API
- Dokumentacja interfejsu API: więcej informacji o dozwolonych metodach autoryzacji, dozwolonych sieciach kart i specyfikacjach tokenizacji, w tym o prawidłowej wartości bramy, znajdziesz w
PaymentMethod.
4. Dodawanie przycisku Google Pay
Użyj komponentu Compose Pay Button, aby wyrenderować natywny przycisk Google Pay, oraz interfejsu Wallet API, aby otworzyć arkusz Google Pay.
Zastąp całą zawartość pliku MainActivity.kt tym kompletnym przykładem (obejmuje konfigurację, przycisk i proces płatności):
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. Wysyłanie prośby o płatność
Gdy użytkownik naciśnie przycisk Google Pay, requestPayment(...) utworzy PaymentDataRequest, dodając transactionInfo do baseGooglePayRequest, otworzy arkusz Google Pay i zwróci token płatności.
Najważniejsze kwestie
- Przycisk:
PayButtonrenderuje natywny przycisk Google Pay. - Klient:
PaymentsClientjest skonfigurowany jako TEST lub PRODUCTION. - Uruchomienie: użyj
loadPaymentDatai w razie potrzeby rozwiąż problem za pomocąIntentSender. - Token: przeanalizuj
PaymentData.toJson(), aby wyodrębnićpaymentMethodData.tokenizationData.tokeni wysłać do dostawcy usług płatniczych.
6. Podsumowanie
Gratulujemy ukończenia tego ćwiczenia! Wiesz już, jak zintegrować Google Pay API z aplikacją na Androida napisaną w Jetpack Compose.
Uruchamianie projektu
Uruchom projekt w Android Studio Run > Run 'app', aby rozpocząć korzystanie z aplikacji.
Co dalej
Dodatkowe materiały
- Dołącz do rozmowy na kanale#payments w Discordzie
- Obserwuj @GooglePayDevs na X
- Oglądaj filmy związane z Google Pay w YouTube