1. Giới thiệu
Sản phẩm bạn sẽ tạo ra
Khi hoàn tất lớp học lập trình này, bạn sẽ có một ứng dụng Jetpack Compose tối thiểu có thể hoạt động với tính năng tích hợp Google Pay cho Android. Dự án này truy xuất một mã thông báo thanh toán có thể được gửi đến một nhà cung cấp dịch vụ thanh toán để xử lý.
Kiến thức bạn sẽ học được
- Cách cài đặt và định cấu hình thư viện Google Pay Jetpack Compose
- Cách hiển thị nút Google Pay và xử lý các lượt nhấp
- Cách yêu cầu mã thông báo thanh toán từ Google Pay
Bạn cần có
- Đã cài đặt Android Studio (phiên bản ổn định mới nhất).
- SDK Android và trình mô phỏng hoặc thiết bị được thiết lập trong Android Studio.
- Đối với bản phát hành công khai, bạn sẽ cần có một
merchantIdGoogle Pay. Bạn chỉ mất một phút để đăng ký tại Google Pay & Wallet Console, vậy nên bạn có thể thực hiện ngay bây giờ.
2. Tạo dự án Jetpack Compose
Tạo tệp dự án
- Tạo một dự án Jetpack Compose mới trong Android Studio có tên là
gpay-compose:- Mở Android Studio rồi chọn
New Project. - Chọn mẫu
Empty Activity (Jetpack Compose). - Tên:
gpay-compose, Tên gói:com.example.gpay. - Ngôn ngữ: Kotlin, SDK tối thiểu: API 21 trở lên.
- Hoàn tất để tạo dự án.
- Mở Android Studio rồi chọn
- Thêm phần phụ thuộc Nút Google Pay Compose.Trong tệp
app/build.gradle(.kts), hãy thêm: Groovy DSL:dependencies { implementation("com.google.pay.button:compose-pay-button:1.2.0") }dependencies { implementation 'com.google.pay.button:compose-pay-button:1.2.0' } - Thêm phần phụ thuộc Dịch vụ Google Play Wallet (để mở trang Google Pay):Trong tệp
app/build.gradle(.kts), hãy thêm phần phụ thuộc sau: Nếu dự án của bạn dùng Groovy DSL, hãy sử dụng:dependencies { implementation("com.google.android.gms:play-services-wallet:19.5.0") }dependencies { implementation 'com.google.android.gms:play-services-wallet:19.5.0' } - Mở
MainActivity.kttrong Android Studio rồi thay thế nội dung bằng khung ứng dụng Compose tối thiểu sau đây (chúng ta sẽ kết nối nút này sau):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. Định cấu hình Google Pay
Yêu cầu thanh toán bằng Google Pay cần có một đối tượng yêu cầu. Đối tượng được xác định ở đây là baseGooglePayRequest chứa các chế độ cài đặt chung tối thiểu cho tất cả các yêu cầu. Các chế độ cài đặt bổ sung sẽ được thêm vào tuỳ thuộc vào yêu cầu được đưa ra mà chúng ta sẽ xem xét trong lớp học lập trình này.
Thêm các hằng số cấu hình Google Pay vào MainActivity.kt (bạn sẽ dùng lại các hằng số này ở bước tiếp theo):
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()
Tài nguyên
- Tài liệu tham khảo API: Tài liệu về các đối tượng yêu cầu của Google Pay API
- Tài liệu tham khảo về API: Tham khảo
PaymentMethodđể biết thêm thông tin về các phương thức uỷ quyền được phép, mạng thẻ được phép và quy cách mã hoá bao gồm cả giá trị cổng phù hợp.
4. Thêm nút Google Pay
Sử dụng Nút thanh toán Compose để hiển thị một nút Google Pay gốc và Wallet API để mở trang Google Pay.
Thay thế toàn bộ nội dung của MainActivity.kt bằng ví dụ hoàn chỉnh sau đây (bao gồm cấu hình + nút + quy trình thanh toán):
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. Tạo yêu cầu thanh toán
Khi người dùng nhấn vào nút Google Pay, requestPayment(...) sẽ tạo một PaymentDataRequest bằng cách thêm transactionInfo vào baseGooglePayRequest, mở trang Google Pay và trả về một mã thông báo thanh toán.
Điểm chính
- Nút:
PayButtonhiển thị nút Google Pay gốc. - Ứng dụng:
PaymentsClientđược định cấu hình bằng TEST hoặc PRODUCTION. - Khởi chạy: Sử dụng
loadPaymentDatavà giải quyết bằngIntentSenderkhi cần. - Mã thông báo: Phân tích cú pháp
PaymentData.toJson()để trích xuấtpaymentMethodData.tokenizationData.tokenvà gửi đến PSP của bạn.
6. Kết luận
Chúc mừng bạn đã hoàn thành Lớp học lập trình này! Bạn đã tìm hiểu cách tích hợp Google Pay API vào một ứng dụng Jetpack Compose cho Android.
Chạy dự án
Chạy dự án từ Android Studio (Run > Run 'app') để khởi động ứng dụng.
Nội dung tiếp theo nên tìm hiểu
Tài nguyên khác
- Tham gia cuộc trò chuyện trong kênh#payments trên Discord
- Theo dõi @GooglePayDevs trên X
- Xem các video liên quan đến Google Pay trên YouTube