使用 Google Wallet API 在 Android 上创建卡券

1. 简介

概览

借助 Google Wallet API,您可以通过各种类型的卡券(会员卡、优惠、礼品卡、活动门票、公交票券、登机牌等)与用户互动。每种卡券类型(或卡券类)都附带特定于用例的字段和功能,以提升用户体验。

不过,这些方法可能并不适用于所有用例。如需打造更个性化的体验,您可以使用通用卡券类型。以下是通用卡券类型的一些用例:

  • 停车券
  • 图书馆会员卡
  • 储值代金券
  • 健身房会员卡
  • 预留

凡是能够以以下形式展示的用例,您都可以为其使用通用卡券:

  • 最多三行信息
  • (可选)条形码图片
  • (可选)“详情”部分

一台 Android 设备,演示了“添加到 Google 钱包”配置流程

如需详细了解 Google Wallet API 或如何向 Android 应用添加添加到 Google 钱包按钮,请参阅 Google 钱包开发者文档

传递类和对象

Google Wallet API 公开了用于创建以下内容的方法:

类型

说明

卡券类

单个卡券对象的模板。它包含与此类中的所有通行对象通用的信息。

传递对象

与用户 ID 唯一对应的卡类实例。

关于此 Codelab

在此 Codelab 中,您将完成以下任务。

  1. 在演示模式下创建新的发卡机构账号
  2. 创建用于签发卡券的服务账号
  3. 创建新的通用卡券类
  4. 创建新的卡券对象
  5. 创建添加到 Google 钱包按钮以保存卡券
  6. 在 Android 应用中显示该按钮
  7. 处理卡券保存结果

前提条件

目标

完成此 Codelab 后,您将能够执行以下操作:

  • 将 Google Wallet SDK 添加到您的 Android 应用
  • 检查 Google Wallet API 是否适用于 Android 设备
  • 创建添加到 Google 钱包按钮

支持

如果您在 Codelab 中的任何步骤遇到困难,可以参阅 google-pay/wallet-android-codelab GitHub 代码库中的完整解决方案。

2. 设置

在此步骤中,您将在演示模式下创建一个发卡机构账号。这样,您就可以创建可添加到用户钱包的卡类和对象。接下来,您将创建一个 Google Cloud 项目和服务账号。这些类和对象将用于以与后端服务器相同的方式以编程方式创建卡券类和对象。最后,您将授权 Google Cloud 服务账号管理 Google 钱包发卡人账号中的卡券。

注册 Google Wallet API 发卡机构账号

您必须拥有发卡机构账号,才能为 Google 钱包创建和分发卡券。您可以使用 Google Pay 和钱包控制台进行注册。最初,您将能够在演示模式下创建卡券。这意味着,只有特定的测试用户才能添加您创建的卡券。您可以在 Google Pay & Wallet 控制台中管理测试用户。

如需详细了解演示模式,请参阅通用通行前提条件

  1. 打开 Google Pay & Wallet 控制台
  2. 按照屏幕上的说明创建发卡人账号
  3. 选择 Google Wallet API
  4. 确认您了解服务条款和隐私权政策
  5. 颁发者 ID 值复制到文本编辑器或其他位置
  6. 管理标签页下,选择设置测试账号
  7. 添加您将在此 Codelab 中使用的所有电子邮件地址

启用 Google Wallet API

  1. 登录 Google Cloud 控制台
  2. 如果您还没有 Google Cloud 项目,请立即创建一个(如需了解详情,请参阅创建和管理项目
  3. 为您的项目启用 Google Wallet API(也称为 Google Pay for Passes API)

创建服务账号和密钥

您必须拥有服务账号和服务账号密钥,才能调用 Google Wallet API。服务账号是调用 Google Wallet API 的身份。服务账号密钥包含一个私钥,用于将您的应用标识为服务账号。此密钥非常敏感,请务必保密。

创建服务账号

  1. 在 Google Cloud 控制台中,打开服务账号
  2. 输入服务账号的名称、ID 和说明
  3. 选择创建并继续
  4. 选择完成

创建服务账号密钥

  1. 选择您的服务账号
  2. 选择KEYS菜单
  3. 依次选择添加密钥创建新密钥
  4. 选择 JSON 密钥类型
  5. 选择创建

系统会提示您将密钥文件保存到本地工作站。请务必记住其位置。

设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量

Google SDK 使用 GOOGLE_APPLICATION_CREDENTIALS 环境变量以服务账号身份进行身份验证,并访问 Google Cloud 项目的不同 API。

  1. 按照 Google Cloud 服务账号密钥文档中的说明设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量
  2. 验证环境变量是否在新终端(MacOS/Linux)或命令行(Windows)会话中设置(如果您已打开一个会话,则可能需要启动一个新会话)
    echo $GOOGLE_APPLICATION_CREDENTIALS
    

向服务账号授权

最后,您需要授权服务账号管理 Google 钱包卡券。

  1. 打开 Google Pay & Wallet 控制台
  2. 选择用户
  3. 选择邀请用户
  4. 输入服务账号的电子邮件地址(例如 test-svc@myproject.iam.gserviceaccount.com
  5. 访问权限级别下拉菜单中选择开发者管理员
  6. 选择邀请

3. 创建通用卡券类

在此步骤中,您将为卡券创建基类。每当为用户创建新卡券时,该卡券都会继承卡券类中定义的属性。

您在此 Codelab 中创建的卡券类利用通用卡券的灵活性来创建一个既可用作身份徽章,又可用作挑战积分跟踪器的对象。通过此类创建卡券对象时,该对象将如下图所示。

您可以直接在 Google Pay & Wallet 控制台中或使用 Google 钱包 API 创建卡券类。在此 Codelab 中,您将使用该 API 创建通用卡券类。这遵循了专用后端服务器创建通行密钥类的过程。

  1. google-pay/wallet-android-codelab GitHub 代码库克隆到本地工作站
    git clone https://github.com/google-pay/wallet-android-codelab.git
    
  2. 在终端或命令行提示符中打开克隆的代码库
  3. 进入 backend 目录(这些脚本会模拟后端服务器操作)
    cd backend
    
  4. 安装 Node.js 依赖项
    npm install .
    
  5. backend 目录中,打开 generic_class.js
  6. issuerId 的值替换为 Google Pay & Wallet 控制台中的发卡机构 ID
    // TODO: Define Issuer ID
    let issuerId = 'ISSUER_ID';
    
  7. 在终端或命令行提示符中,运行 generic_class.js 脚本
    node generic_class.js
    

代码运行时,它会创建一个新的卡券类并输出类 ID。类 ID 由发卡机构 ID 和开发者定义的后缀组成。在本例中,后缀设置为 codelab_class(类 ID 类似于 1234123412341234123.codelab_class)。输出日志还将包含 Google Wallet API 的响应。

4. 在 Android Studio 中打开项目

您克隆的 GitHub 代码库包含一个包含空 activity 的 Android 项目。在此步骤中,您将在此 activity 中进行修改,以在商品页面上添加添加到 Google 钱包按钮。

  1. 打开 Android Studio
  2. 依次选择文件打开
  3. 在代码库中选择 android 目录
  4. 选择打开

将 Google 钱包 SDK 添加到您的应用

  1. 打开模块级 Gradle build 文件 (android/app/build.gradle)
  2. 将 Google 钱包 SDK 添加到 dependencies 部分
    // TODO: Add the "com.google.android.gms:play-services-pay" dependency to
    //       use the Google Wallet API
    implementation "com.google.android.gms:play-services-pay:16.0.3"
    
  3. 保存文件。
  4. 依次选择 File(文件)和 Sync Project with Gradle Files(将项目与 Gradle 文件同步)

5. 创建“Add to Google Wallet”(添加到 Google 钱包)按钮

在此步骤中,您将创建一个添加到 Google 钱包按钮,并将其添加到现有 activity。该按钮的相关资源已包含在项目中。如需添加按钮,您需要创建一个单独的布局文件。添加后,该按钮将如下所示。

“Add to Google Wallet”(添加到 Google 钱包)按钮

  1. 创建新的布局文件:app/src/main/res/layout/add_to_google_wallet_button.xml
  2. 将以下内容添加到新布局文件中
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="48sp"
        android:background="@drawable/add_to_google_wallet_button_background_shape"
        android:clickable="true"
        android:contentDescription="@string/add_to_google_wallet_button_content_description"
        android:focusable="true">
      <ImageView
          android:layout_width="227dp"
          android:layout_height="26dp"
          android:layout_gravity="center"
          android:duplicateParentState="true"
          android:src="@drawable/add_to_google_wallet_button_foreground" />
    </FrameLayout>
    
  3. 在结账 activity 布局文件 (app/src/main/res/layout/activity_checkout.xml) 中添加 add_to_google_wallet_button.xml 布局
    <!--
        TODO: Create the button under `add_to_google_wallet_button.xml`
              and include it in your UI
    -->
    <include
        android:id="@+id/addToGoogleWalletButton"
        layout="@layout/add_to_google_wallet_button"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_marginTop="10dp" />
    

6. 检查 Google Wallet API 是否可用

如果用户在不支持 Google Wallet API 的设备上打开您的应用,则在尝试添加卡券时可能会获得不良体验。如果用户的设备不支持 Google 钱包 API,请隐藏 Add to Google Wallet 按钮,以免造成混淆。导致该 API 不可用的原因有很多,例如 Android 或 Google Play 服务版本过低,或 Google 钱包在用户所在的国家/地区无法使用。

在此步骤中,您将向应用添加逻辑,用于检查设备上是否有 Google Wallet API。如果是,系统会在 activity 中呈现该按钮。否则,系统会隐藏该按钮。

  1. app/src/main/java/com/google/android/gms/samples/wallet/activity/ 中打开 CheckoutActivity.kt 文件
  2. PayClient 实例创建类属性
    // TODO: Create a client to interact with the Google Wallet API
    private lateinit var walletClient: PayClient
    
  3. onCreate 方法中实例化 PayClient 属性
    // TODO: Instantiate the client
    walletClient = Pay.getClient(this)
    
  4. 创建一个方法,用于检查设备上是否有 Google Wallet SDK 和 API,并处理结果
    // TODO: Create a method to check for the Google Wallet SDK and API
    private fun fetchCanUseGoogleWalletApi() {
      walletClient
        .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
        .addOnSuccessListener { status ->
          if (status == PayApiAvailabilityStatus.AVAILABLE)
            layout.passContainer.visibility = View.VISIBLE
        }
        .addOnFailureListener {
          // Hide the button and optionally show an error message
        }
    }
    
  5. onCreate 方法中调用 fetchCanUseGoogleWalletApi 方法,以检查 Google Wallet API 是否可用
    // TODO: Check if the Google Wallet API is available
    fetchCanUseGoogleWalletApi()
    

现在,运行应用时,您应该会在界面中看到添加到 Google 钱包按钮。

“添加到 Google 钱包”按钮现在会显示在应用 activity 中

7. 创建通用卡券对象

现在您已经验证了 Google Wallet API 可用,接下来您可以创建卡券并提示用户将其添加到钱包。为用户创建卡券对象有两种流程。

在后端服务器上创建卡券对象

在此方法中,通行证对象是在后端服务器上创建的,并作为已签名的 JWT 返回给客户端应用。这种方式最适合用户采用率较高的情况,因为它可确保在用户尝试将对象添加到钱包之前,该对象已存在。

在用户将卡券添加到钱包时创建卡券对象

在此方法中,通行证对象会在后端服务器上定义并编码为已签名的 JWT。然后,在引用 JWT 的客户端应用中呈现 Add to Google Wallet 按钮。当用户选择该按钮时,系统会使用 JWT 创建卡券对象。这最适合用户采用情况不稳定或未知的情况,因为它可以防止创建了但未使用的通行密钥对象。本 Codelab 将使用此方法。

  1. 打开 backend/generic_pass.js 文件
  2. issuerId 的值替换为 Google Pay & Wallet 控制台中的发卡机构 ID
    // TODO: Define Issuer ID
    let issuerId = 'ISSUER_ID';
    
  3. 在终端或命令行提示符中,运行 generic_pass.js 文件
    node generic_pass.js
    
  4. 将输出令牌复制到剪贴板或文本编辑器

代码运行时,它会定义一个新的卡券对象并将其嵌入 JWT 中。然后,JWT 由您之前创建的服务账号密钥签名。这会对向 Google 钱包 API 的请求进行身份验证,以便无需在客户端应用中存储凭据。

aside 在生产环境中,您的后端系统将负责创建 JWT 并将其返回给客户端。在此 Codelab 中,generic_pass.js 脚本会模拟此行为并“返回”一个令牌,以供您在客户端应用中使用。

8. 将卡券添加到 Google 钱包

现在您已经验证了 Google Wallet API 可用,并创建了已签名的 JWT,接下来您可以提示用户将卡券添加到其钱包。在此步骤中,您将向 Add to Google Wallet 按钮添加监听器,该监听器使用 Google Wallet API 将卡券保存到用户的钱包中。

  1. 打开 app/src/main/CheckoutActivity.kt 文件
  2. token 的值替换为您之前创建的 JWT
    // TODO: Save the JWT from the backend "response"
    private val token = "TOKEN"
    
  3. 创建一个类属性来存储请求代码
    // TODO: Add a request code for the save operation
    private val addToGoogleWalletRequestCode = 1000
    
  4. Add to Google Wallet 按钮设置监听器
    // TODO: Set an on-click listener on the "Add to Google Wallet" button
    addToGoogleWalletButton = layout.addToGoogleWalletButton.
    
    addToGoogleWalletButton.setOnClickListener {
      walletClient.savePassesJwt(token, this, addToGoogleWalletRequestCode)
    }
    

当用户选择添加到 Google 钱包按钮时,系统会调用 walletClient.savePassesJwt 方法。此方法会提示用户将新的卡券对象添加到其 Google 钱包。

9. 处理 savePassesJwt 结果

在此 Codelab 的最后一步中,您将配置应用以处理 walletClient.savePassesJwt 操作的结果。

  1. 打开 app/src/main/CheckoutActivity.kt 文件
  2. 替换 onActivityResult 方法,使其包含以下代码
    // TODO: Handle the result
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
      super.onActivityResult(requestCode, resultCode, data)
    
      if (requestCode == addToGoogleWalletRequestCode) {
        when (resultCode) {
          RESULT_OK -> {
            // Pass saved successfully. Consider informing the user.
          }
    
          RESULT_CANCELED -> {
            // Save canceled
          }
    
          PayClient.SavePassesResult.SAVE_ERROR ->
            data?.let { intentData ->
              val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)
              // Handle error. Consider informing the user.
              Log.e("SavePassesResult", errorMessage.toString())
            }
    
          else -> {
            // Handle unexpected (non-API) exception
          }
        }
      }
    }
    

现在,您的应用能够处理以下场景:

  • 成功添加卡券
  • 用户取消
  • 意外错误

运行应用,确认是否可以按预期添加卡券并处理结果。

10. 恭喜

通用传递对象示例。

恭喜,您已成功在 Android 设备上集成 Google Wallet API!

了解详情

如需查看完整集成,请参阅 google-pay/wallet-android-codelab GitHub 代码库。

创建卡券并申请正式版发布权限

当您准备好在生产环境中发布自己的卡券时,请前往 Google Pay 和钱包控制台,请求正式版访问权限并授权您的 Android 应用。

如需了解详情,请参阅 Android SDK 前提条件