使用 Google Pay 在 Android 上打造快速结账体验

1. 简介

有了 Google Pay API,用户可以使用存储在其 Google 账号中的付款信息随时随地进行付款。在本实验中,您将利用 Google Pay 的 Android 版客户端库,通过创建更快速、更便捷、更安全的体验来提升简化版示例移动应用的结账体验,从而获得更多转化并提高客户满意度。

Auto T-Shirt Shop 是一家创新型商店,利用人工智能的最新技术,利用风格偏好、天气、一年中时间和时尚趋势等信息,为你推荐最适合购买的商品。

互动相关指标的表现都超出预期。然而遗憾的是,这些数据也反映出大量用户在结账过程中放弃了购买。该项目的一位所有者下定决心,他回想起自己曾看过一段视频,其中展示了 Google Pay 为其他类似网站取得的可喜成果,因此他们决定试一试,相信您来完成集成。

概览

此 Codelab 会指导您将 Google Pay 集成到现有应用中,包括确定用户是否可以使用 Google Pay 支持的付款方式进行付款、付款按钮的放置位置和设计,以及交易的执行方式。

示例应用

在此 Codelab 中,您将学习如何:

  1. 将 Google Pay 集成到现有 Android 应用中
  2. 确定用户是否已准备好使用 Google Pay 付款
  3. 将 Google Pay 按钮添加到界面中
  4. 使用 Google Pay 完成付款操作

前提条件

  • Git
  • Android Studio 或面向 Android 应用的替代开发环境
  • 安装了最新版 Google Play 服务的 Android 设备或模拟器

支持

如果您遇到困难,请参阅 google-pay/android-quickstart GitHub 代码库包含完整的解决方案,供您参考。

2. 开始

从 GitHub 克隆代码库

使用以下命令将代码库克隆到计算机上的文件夹中:

git clone https://github.com/google-pay/android-quickstart

或者,如果您更愿意使用 ZIP 归档文件:

浏览示例应用

如您所见,该代码库的文件结构较为简单。此 Codelab 的主要目的是让您能够根据现有和未来的应用来调整此集成,而无需考虑您选择使用的编程语言、库或工具。

3. 在 Android Studio 中打开项目

您克隆的 GitHub 代码库包含一个具有基本活动的 Android 项目。在此步骤中,您将在此活动中进行修改,以验证 Google Pay 是否已准备就绪,并显示 Google Pay 按钮。

  1. 打开 Android Studio
  2. 选择文件,然后选择打开
  3. 选择代码库中的 kotlin 目录
  4. 选择打开

将 Google Pay 库作为依赖项添加到 build.gradle 文件中

  1. 打开模块级 Gradle build 文件 (kotlin/app/build.gradle.kts)
  2. 将 Google Pay 库添加到 dependencies 部分
implementation "com.google.android.gms:play-services-wallet:19.3.0"
  1. 保存文件。
  2. 选择 File,然后选择 Sync Project with Gradle Files

在 Android 清单文件中启用 Google Pay API

最后,在清单文件的 application 节点内添加 meta-data 元素:

<meta-data
    android:name="com.google.android.gms.wallet.api.enabled"
    android:value="true" />

4. 确定 Google Pay 按钮在界面中的什么位置

视图中的布局和整体位置是影响用户完成付款交易的可能性的重要因素。通过使用 Google Pay,只需点按几下即可选择付款方式,这让您可以通过新的选项了解在应用中为用户提供付款方式的位置和时间。例如,您可以在流程的早期(在商品详情视图等区域)添加快速结账选项,以便用户快速购买他们喜欢的单件商品。

确定如何排列界面后,下一步就是放置 Google Pay 按钮。您可以配置按钮的一些视觉功能,例如类型、主题和圆角。下面是一些示例:

Google Pay 动态按钮示例

Google Pay 库包含一个视图,可简化将该按钮添加到界面的操作。如果您使用 XML 构建布局,可以通过以下方式实现这一点:

<com.google.android.gms.wallet.button.PayButton
    android:id="@+id/googlePayButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

稍后您将以编程方式初始化该按钮(请参阅示例)。
如果您使用的是 Jetpack Compose,请在 build.gradlebuild.gradle.kts 文件中添加以下依赖项的最新版本:

implementation "com.google.pay.button:compose-pay-button:1.0.0"

然后,将 Google Pay 按钮添加到 Compose 布局中,如下所示:

PayButton(
    modifier = Modifier
        .testTag("payButton")
        .fillMaxWidth(),
    onClick = onGooglePayButtonClick,
    allowedPaymentMethods = PaymentsUtil.allowedPaymentMethods.toString()
)

查看 GitHub 中的示例,详细了解如何构建接受的付款方式列表。

5. 初始化和配置 Google Pay API

实例化 API 客户端

如需开始使用 API,您需要实例化客户端对象,该对象可用于调用 Google Pay API。创建 activity 或控制器后,即可立即执行此操作:

private val paymentsClient: PaymentsClient = createPaymentsClient(context)

fun createPaymentsClient(context: Context): PaymentsClient {
    val walletOptions = Wallet.WalletOptions.Builder()
            .setEnvironment(WalletConstants.ENVIRONMENT_TEST).build()
    return Wallet.getPaymentsClient(context, walletOptions)
}

付款客户端通过 WalletOptions 对象进行初始化。将环境设为 ENVIRONMENT_TEST 后,您可以对测试付款信息进行实验。准备好进行实际付款交易后,您可以将环境属性更新为 ENVIRONMENT_PRODUCTION

Google Pay 请求剖析

当您向 Google Pay API 发出请求时,需要在请求中包含许多配置参数,例如您的目标 API 的版本。对于本 Codelab,此对象还会包含与应用接受的付款方式有关的信息。最终的结构如下所示:

{
    apiVersion: number,
    apiVersionMinor: number,
    allowedPaymentMethods: Array
}

属性 allowedPaymentMethods 将获取一个付款方式列表。对于每种付款方式,您都必须包含以下属性:

{
    type: 'CARD',
    parameters: {
        allowedCardNetworks: Array.<string>,
        allowedAuthMethods: Array.<string>
    }
}

付款方式配置

在此示例中,您只能接受 Mastercard 和 Visa 的银行卡付款,这两种方式均采用令牌化和主账号 (PAN) 形式。您的付款方式如下所示:

private val baseCardPaymentMethod =
    JSONObject()
        .put("type", "CARD")
        .put("parameters", JSONObject()
            .put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
            .put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
        )

综合应用

我们来回顾一下。您已定义了一个要在应用中接受的付款方式,接下来将使用 API 的 2.0 版本。生成的配置如下所示:

private val baseCardPaymentMethod = JSONObject()
    .put("type", "CARD")
    .put("parameters", JSONObject()
        .put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        .put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
    )

private val googlePayBaseConfiguration = JSONObject()
    .put("apiVersion", 2)
    .put("apiVersionMinor", 0)
    .put("allowedPaymentMethods",  JSONArray(listOf(baseCardPaymentMethod)))
}

6. 确定是否能使用 Google Pay 付款

通过使用 isReadyToPay 请求,您可以确定应用中的用户是否能够使用 Google Pay 付款。您可以利用这些信息相应地调整应用中的用户体验。

此请求要求您指定 Google Pay API 的版本以及应用中允许的付款方式列表。这正是上一步中定义的基本配置对象的内容:

private suspend fun fetchCanUseGooglePay(): Boolean {
    val request = IsReadyToPayRequest.fromJson(googlePayBaseConfiguration.toString())
    return paymentsClient.isReadyToPay(request).await()
}

。Google Pay API 使用 Task 解析远程调用。借助 Tasks API,您可以使用协程解析 Task 操作。了解详情

如您所见,检查是否可以使用 Google Pay 付款会返回一个布尔值对象。如果结果是肯定的,下一步就是在界面中显示 Google Pay 按钮。否则,请考虑显示支持其他付款方式的额外界面。

显示 Google Pay 按钮

现在,请返回界面,根据上一次调用的结果更新 Google Pay 按钮的位置。此示例使用类来保存视图的状态,该状态会根据对 isReadyToPay 的调用等输入进行更新。

if (payUiState !is PaymentUiState.NotStarted) {
    PayButton(
        modifier = Modifier
            .testTag("payButton")
            .fillMaxWidth(),
        onClick = onGooglePayButtonClick,
        allowedPaymentMethods = PaymentsUtil.allowedPaymentMethods.toString()
    )
}

7. 可以付款了!

### 准备付款请求

此时,您已加载 Google Pay API 并确定应用中的用户可以使用 Google Pay 进行付款。因此,您已在界面中显示 Google Pay 付款按钮,且用户现在可以发起交易了。现在,您可以加载付款表格,列出用户可用的付款方式了。

与对 isReadyToPay 的调用类似,此请求需要之前定义的基本配置对象中的属性(apiVersionapiVersionMinorallowedPaymentMethods)。这一次,您还需要一个名为 tokenizationSpecification 的新属性,以及其他用于描述交易和请求信息(例如账单邮寄地址、送货地址或用户信息)的参数电子邮件地址或电话号码

#### tokenizationSpecification 属性

标记化规范决定了系统如何处理您的用户选择的付款方式,以及如何使用付款方式完成交易。

支持两种不同类型的处理机制。如果您要在符合 PCI DSS 标准的服务器中处理付款交易,请使用 DIRECT 规范类型。在此示例中,您使用支付网关处理付款,因此设置了 PAYMENT_GATEWAY 规范类型:

private val tokenizationSpecification = JSONObject()
    .put("type", "PAYMENT_GATEWAY")
    .put("parameters", JSONObject(mapOf(
            "gateway" to "example",
            "gatewayMerchantId" to "exampleGatewayMerchantId")))
}

parameters 部分,您可以从 Google Pay API 支持的提供商列表中指定网关,以及每个网关所需的其他配置。在本实验中,您将使用 example 网关,该网关会返回所执行事务的测试结果。

其他参数

同样,您也可以向用户索要更多详细信息,以便成功下单。在此示例中,您将了解如何添加 billingAddressRequiredbillingAddressParameters 属性,以指明对于此交易,用户的账单邮寄地址必须采用完整格式并包含电话号码:

private val cardPaymentMethod = JSONObject()
    .put("type", "CARD")
    .put("tokenizationSpecification", tokenizationSpecification)
    .put("parameters", JSONObject()
        .put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        .put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
        .put("billingAddressRequired", true)
        .put("billingAddressParameters", JSONObject(mapOf("format" to "FULL")))
    )

#### 添加有关交易的更多信息

transactionInfo 属性定义

private val transactionInfo = JSONObject()
    .put("totalPrice", "123.45")
    .put("totalPriceStatus", "FINAL")
    .put("currencyCode", "USD")
}

#### 添加商家信息

付款请求会获取 merchantInfo 属性下执行请求的商家的相关信息。在此 Codelab 中,您将重点关注两个属性:

  • merchantId 中包含与您的账号关联的标识符。您可以在付款和钱包控制台。请注意,使用 TEST 环境时,系统不会对此字段进行求值。
  • merchantName 是应用或组织的用户可见名称。此信息可能会显示在 Google Pay 付款表格内,以便为用户提供有关请求操作的更多背景信息。

准备就绪后,只需将商家相关信息添加到 paymentDataRequest 对象即可:

private val merchantInfo = JSONObject()
    .put("merchantName", "Example Merchant")
    .put("merchantId", "01234567890123456789")

发出请求并处理结果

现在,将配置对象组合在一起,并将其传递给 loadPaymentData 请求:

private val paymentDataRequestJson = JSONObject(googlePayBaseConfiguration.toString())
    .put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod))
    .put("transactionInfo", transactionInfo)
    .put("merchantInfo", merchantInfo)

此时,您已具备请求 Google Pay API 提供有效付款方式所需的一切条件。为此,请在 PaymentsClient 对象中使用 loadPaymentData 方法,并传入您刚刚定义的配置:

fun getLoadPaymentDataTask(): Task<PaymentData> {
    val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
    return paymentsClient.loadPaymentData(request)
}

private fun requestPayment() {
    val task = getLoadPaymentDataTask()
    task.addOnCompleteListener(paymentDataLauncher::launch)
}

Google Pay API 使用 Activity Result API 返回结果。该 API 包含协定类,可简化处理和响应结果的流程。此示例使用 GetPaymentDataResult 合同,该合同除了包含付款结果之外,还包含操作的相关信息:

private val paymentDataLauncher = registerForActivityResult(GetPaymentDataResult()) { taskResult ->
    when (taskResult.status.statusCode) {
        CommonStatusCodes.SUCCESS -> {
            taskResult.result!!.let {
                Log.i("Google Pay result:", it.toJson())
                // TODO something with the result
            }
        }
        CommonStatusCodes.CANCELED -> // The user canceled
        AutoResolveHelper.RESULT_ERROR -> // The API returned an error (it.status: Status)
        CommonStatusCodes.INTERNAL_ERROR -> // Handle other unexpected errors
    }
}

调用此方法会触发 Google Pay 付款表格的显示。如果没有配置错误,您就能看到与当前登录账号关联的有效付款方式的列表。

选择后,该工作表将关闭,结果会发送回您的 activity,并由上面定义的 activity 结果启动器捕获。

如果选择成功,系统会返回 PaymentData 对象的结果,该对象包含所选付款方式的相关信息:

{
  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "examplePaymentMethodToken"
    },
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234",
      "billingAddress": {
        "phoneNumber": ...,
        ...
      }
    }
  }
}

您现在可以使用此付款方式通过支付网关完成交易:

private fun handlePaymentSuccess(paymentData: PaymentData) {
    val paymentMethodToken = paymentData
            .getJSONObject("tokenizationData")
            .getString("token")

    // Sample TODO: Use this token to perform a payment through your payment gateway
}

8. 恭喜!

您已成功将 Google Pay 添加到 Android 应用中。

### 后续步骤

### 了解详情

您觉得这有用吗?

<ph type="x-smartling-placeholder"></ph> 非常有用 与我预期的情况差不多 不太对