1. 简介
构建内容
完成此 Codelab 后,您将拥有一个最低可行性 Jetpack Compose 应用,其中包含可正常运行的 Google Pay Android 集成。此项目会检索付款令牌,该令牌可能会发送给支付服务提供商进行处理。
学习内容
- 如何安装和配置 Google Pay Jetpack Compose 库
- 如何显示 Google Pay 按钮并处理点击事件
- 如何从 Google Pay 请求支付令牌
所需条件
- 已安装 Android Studio(最新稳定版)。
- Android SDK 以及在 Android Studio 中设置的模拟器或设备。
- 对于生产环境,您需要 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 及更高版本。
- 完成以生成项目。
- 打开 Android Studio,然后选择
- 添加 Google Pay Compose 按钮依赖项。在
app/build.gradle(.kts)文件中,添加: 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' } - 添加 Google Play 服务钱包依赖项(以打开 Google Pay 表单):在
app/build.gradle(.kts)文件中,添加以下依赖项: 如果您的项目使用 Groovy DSL,请使用:dependencies { implementation("com.google.android.gms:play-services-wallet:19.5.0") }dependencies { implementation 'com.google.android.gms:play-services-wallet:19.5.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 集成到 Jetpack Compose Android 应用中。
运行项目
从 Android Studio (Run > Run 'app') 运行项目以启动应用。
后续步骤
其他资源
- 在 Discord 的 #payments 频道中加入对话
- 在 X 上关注 @GooglePayDevs
- 在 YouTube 上观看与 Google Pay 相关的视频