1. 简介
构建内容
完成此 Codelab 后,您将拥有一个最低可行性 Jetpack Compose 应用,其中包含适用于 Android 的 Google Pay 集成。此项目会检索付款令牌,该令牌可能会发送给付款服务提供商进行处理。
学习内容
- 如何安装和配置 Google Pay Jetpack Compose 库
- 如何显示 Google Pay 按钮并处理点击事件
- 如何向 Google Pay 请求付款令牌
所需条件
- 已安装 Android Studio(最新稳定版)。
- 已在 Android Studio 中设置 Android SDK 和模拟器或设备。
- 对于生产环境,您需要 Google Pay
merchantId。在 Google Pay & Wallet Console 中注册只需一分钟,因此不妨现在就完成注册。
2. 创建 Jetpack Compose 项目
创建项目文件
- 在 Android Studio 中创建一个名为
gpay-compose的新 Jetpack Compose 项目:- 打开 Android Studio,然后选择
New Project。 - 选择
Empty Activity (Jetpack Compose)模板。 - 名称:
gpay-compose,软件包名称:com.example.gpay。 - 语言:Kotlin,最低 SDK 版本:API 21+。
- 点击“Finish”以生成项目。
- 打开 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 服务钱包依赖项(以打开 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' } - 在 Android Studio 中打开
MainActivity.kt,然后将内容替换为以下最小 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 参考文档:如需详细了解允许的授权方法、允许的卡网络和令牌化规范(包括正确的网关值),请参阅
PaymentMethod。
4. 添加 Google Pay 按钮
使用 Compose Pay 按钮呈现原生 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(...) 会通过将 transactionInfo 添加到您的 baseGooglePayRequest 来构建 PaymentDataRequest,打开 Google Pay 界面,并返回付款令牌。
要点
- 按钮:
PayButton呈现原生 Google Pay 按钮。 - 客户端:
PaymentsClient配置为 TEST 或 PRODUCTION。 - 启动:使用
loadPaymentData,并在需要时使用IntentSender解析。 - 令牌:解析
PaymentData.toJson()以提取paymentMethodData.tokenizationData.token并发送给您的 PSP。
6. 总结
恭喜您完成此 Codelab!您已了解如何将 Google Pay API 集成到适用于 Android 的 Jetpack Compose 应用中。
运行项目
从 Android Studio 运行项目(Run > Run 'app')以启动应用。
后续步骤
其他资源
- 在 Discord 的 #payments 频道中参与讨论
- 在 X 上关注 @GooglePayDevs
- 在 YouTube 上观看与 Google Pay 相关的视频