1. מבוא
מה תפַתחו
בסיום ה-codelab הזה, תהיה לכם אפליקציית Jetpack Compose מינימלית עם שילוב פעיל של Google Pay ל-Android. הפרויקט הזה מאחזר אסימון תשלום שאפשר לשלוח לספק שירותי תשלומים לצורך עיבוד.
מה תלמדו
- איך מתקינים ומגדירים את ספריית Google Pay Jetpack Compose
- איך להציג את לחצן Google Pay ולטפל בקליקים
- איך מבקשים טוקן תשלום מ-Google Pay
הדרישות
- Android Studio (הגרסה היציבה האחרונה) מותקן.
- Android SDK ואמולטור או מכשיר שהוגדרו ב-Android Studio.
- לסביבת הייצור, תצטרכו
merchantId. ההרשמה במסוף של Google Pay ו-Wallet נמשכת רק דקה, אז כדאי לעשות את זה עכשיו.
2. יצירת פרויקט Jetpack Compose
יצירת קבצים בפרויקט
- יוצרים פרויקט חדש של Jetpack Compose ב-Android Studio בשם
gpay-compose:- פותחים את Android Studio ובוחרים באפשרות
New Project. - בוחרים את התבנית
Empty Activity (Jetpack Compose). - שם:
gpay-compose, שם החבילה:com.example.gpay. - שפה: Kotlin, גרסת SDK מינימלית: API 21 ומעלה.
- לוחצים על סיום כדי ליצור את הפרויקט.
- פותחים את Android Studio ובוחרים באפשרות
- מוסיפים את התלות של לחצן Google Pay Compose.בקובץ
app/build.gradle(.kts), מוסיפים: 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' } - מוסיפים תלות ב-Google Play Services Wallet (כדי לפתוח את דף Google Pay):בקובץ
app/build.gradle(.kts), מוסיפים את התלות הבאה: אם בפרויקט שלכם נעשה שימוש ב-Groovy DSL, משתמשים בפקודה:dependencies { implementation("com.google.android.gms:play-services-wallet:19.3.0") }dependencies { implementation 'com.google.android.gms:play-services-wallet:19.3.0' } - פותחים את
MainActivity.ktב-Android Studio ומחליפים את התוכן שלו ב-scaffold הבא של אפליקציית 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 מכיל את ההגדרות המשותפות המינימליות לכל הבקשות. הגדרות נוספות יתווספו בהתאם לבקשה שהוגשה, ונבדוק אותן ב-codelab הזה.
מוסיפים את קבועי ההגדרה של 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: מאמרי העזרה בנושא אובייקטים של בקשות ב-Google Pay API
- API Reference: למידע נוסף על שיטות ההרשאה המותרות, רשתות הכרטיסים המותרות ומפרטי הטוקניזציה, כולל ערך השער המתאים, אפשר לעיין במאמר
PaymentMethod.
4. הוספת לחצן Google Pay
משתמשים ב-Compose Pay Button כדי לעבד לחצן מקורי של Google Pay, וב-Wallet API כדי לפתוח את גיליון 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 ומחזיר אסימון תשלום.
נקודות עיקריות
- כפתור:
PayButtonרכיב שמעבד את כפתור Google Pay המקורי. - לקוח:
PaymentsClientמוגדר עם TEST או PRODUCTION. - הפעלה: משתמשים ב-
loadPaymentDataומבצעים פתרון בעזרתIntentSenderכשנדרש. - אסימון: מנתחים את
PaymentData.toJson()כדי לחלץ אתpaymentMethodData.tokenizationData.tokenושולחים אותו לספק שירותי התשלום.
6. סיכום
כל הכבוד, סיימתם את ה-Codelab הזה! למדתם איך לשלב את Google Pay API באפליקציית Jetpack Compose ל-Android.
הרצת הפרויקט
מריצים את הפרויקט מ-Android Studio (Run > Run 'app') כדי להפעיל את האפליקציה.
לאן כדאי ללכת מכאן
מקורות מידע נוספים
- הצטרפות לשיחה בערוץ #payments ב-Discord
- עקבו אחרי @GooglePayDevs ב-X
- צפייה בסרטונים שקשורים ל-Google Pay ב-YouTube