集成 Google Wallet API 以在 Android 上数字化卡券

集成 Google Wallet API 以在 Android 上数字化卡券

关于此 Codelab

subject上次更新时间:4月 27, 2022
account_circleStephen McDonald 编写

1. 准备工作

借助 Google Wallet API,您可以通过各种预定义的卡券类型与用户互动:会员卡、优惠券、礼品卡、活动门票、公交票卡和登机牌。这些卡券类型都具有特定于用例的字段和功能。但我们知道,这些类型可能并非在任何用例中都适用,因此我们创建了一个通用卡券类型。顾名思义,如果您的用例不属于任何其他专用类型,则应使用通用卡券类型。以下是通用卡券类型的一些用例:

  • 停车券
  • 图书馆会员卡
  • 储值代金券
  • 健身房会员卡
  • 保险卡
  • 各种预订

凡是能够以卡片(最多包含 3 行信息,可选择提供条形码和详细信息部分)形式向用户展示的用例,只要符合使用限制政策的要求,您都可以为其使用通用卡券。

借助 Google Wallet API,您可以创建:

  • 卡券类。您可以将类视为模板,其中包含属于某个项目或活动的所有卡券共享的通用信息。所有卡券对象都属于一个类。
  • 卡券对象服务于与您的商家活动和用户相关的具体用途(例如,停车券、健身房会员卡)。这些项都与之前定义的类相关联,并会继承类的通用属性。

此 Codelab 将为您提供一个预定义的类,并指导您为卡券对象定义 JSON,以及向您的 Android 应用添加“Add to Google Wallet”按钮,以允许用户将卡券保存到 Google 钱包。

如需详细了解 Google Wallet API 或如何向 Android 应用添加“Add to Google Wallet”按钮,请访问 Google 钱包开发者文档

前提条件

  • 一台安装了 Android Studio 的计算机。
  • 能够在 Android Studio 中创建和运行项目。
  • 已安装 Git。

学习内容

  • 如何将 Google Wallet SDK 添加到您的 Android 应用。
  • 如何检查 Wallet API 是否可用。
  • 如何实现界面,以允许用户将卡券添加到 Google 钱包。

2. 进行设置

创建临时发卡机构帐号

如需为用户创建卡券,您首先需要创建发卡机构帐号,启用 Wallet API,然后创建类。所有这些操作都可以通过 Google Pay 商家控制台完成。不过,只有在审批流程结束后,您才能获得访问权限。因此,在此 Codelab 中,我们将为您创建一个临时发卡机构帐号,以及一个卡券类。

  1. 点击创建临时发卡机构帐号和示例类
  1. 记下发卡机构 ID 和类 ID,您在后续步骤中会用到这些 ID。

克隆 Git 代码库

使用以下命令克隆包含您要修改的 Android 项目的 Git 代码库:

git clone -b wallet-lab git@github.com:google-pay/android-quickstart.git

在 Android Studio 中打开

打开 Android Studio,从欢迎屏幕中选择“Open”,然后在新克隆的代码库中选择 kotlin 文件夹,并以项目的形式将其打开。

3. 将 Google Wallet SDK 添加到您的应用

Android 项目包含一个空 activity,我们很快将修改此 activity,但首先,我们要将 Google Wallet SDK 添加为依赖项。在 Android Studio 中,选择模块级“build.gradle”脚本,并将以下代码行添加到 dependencies 部分:

dependencies {
   
...
    implementation
'com.google.android.gms:play-services-pay:16.0.3'
}

更改后,点击 Android Studio 右上角的 Gradle“Sync Project”按钮。

4. 添加“Add to Google Wallet”按钮

接下来,您将向 activity 添加“Add to Google Wallet”按钮。该按钮的相关资源已为您添加到项目中,您只需将其添加到布局文件中即可。为此,我们建议您创建一个包含该按钮的单独布局:

add_to_google_wallet_button.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:clickable="true"
   
android:focusable="true"
   
android:layout_width="match_parent"
   
android:layout_height="48sp"
   
android:background="@drawable/add_to_google_wallet_button_background_shape"
   
android:contentDescription="@string/add_to_google_wallet_button_content_description">
   
<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>

该按钮如下所示:

然后,将其添加到布局文件中:

<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"/>

5. 检查 API 是否可用

现在该开始编码了。在 Android Studio 中打开您将在其中调用 Google Wallet API 的文件(如果您使用的是示例应用,则打开 CheckoutActivity.kt 文件),然后将 PayClient 作为类成员实例化。此对象可帮助您调用 Google Wallet API。getClient 方法会接收实例化类的上下文(在本例中,就是调用 activity 的上下文)。

private lateinit var walletClient: PayClient

override fun onCreate(savedInstanceState: Bundle?) {
   
super.onCreate(savedInstanceState)

    walletClient
= Pay.getClient(this)
   
...
}

接下来,确保 Google Wallet SDK 和应用在设备上可用。在类中创建一个新方法(例如:fetchCanUseGoogleWalletApi),以确定 Google Wallet API 是否可用;如果该 API 可用,则创建另一个方法,以通过显示“Add to Google Wallet”按钮来响应结果。

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
       
}
}

最后,在 onCreate 方法中调用 fetchCanUseGoogleWalletApi 方法,以确定 Google Wallet API 是否可用:

override fun onCreate(savedInstanceState: Bundle?) {
   
super.onCreate(savedInstanceState)

   
...
    fetchCanUseGoogleWalletApi
()
}

现在,当您运行应用时,应该会在界面中看到“Add to Google Wallet”按钮:

6. 向 Google 钱包添加卡券

现在您已经验证了 Google Wallet API 可用,接下来您可以提示用户将卡券添加到 Google 钱包。在此之前,请花点时间查看以下研讨会中创建的卡券:

该布局利用通用卡券的灵活性来创建可用作身份徽章的对象,同时还支持用于提醒参与者在活动期间收集积分的提示。该通用对象如下所示:

{
   
"id": "999999.d1fa-4cca1...",
   
"classId": "999999.a92b-129f...",
   
"genericType": "GENERIC_TYPE_UNSPECIFIED",
   
"hexBackgroundColor": "#4285f4",
   
"logo": { ... },
   
"cardTitle": { ... },
   
"subheader": { ... },
   
"header": { ... },
   
"barcode": { ... },
   
"heroImage": { ... },
   
"textModulesData": []
}

如需插入对象,该 API 需要封装新元素的未签名 JWT 主体:

{
   
"iss": <owner-email-address>,
   
"aud": "google",
   
"typ": "savetowallet",
   
"iat": <unix-time>,
   
"origins": [],
   
"payload": {
       
"genericObjects": [],
       
"genericClasses": [],
       
...
   
}
}

将这些元素组合起来(使用您之前创建临时发卡机构帐号时获取的值),并将生成的对象分配给类中的某个变量:

private val issuerEmail = "<insert-your-issuer-email-address>"
private val issuerId = "<insert-your-issuer-id>"
private val passClass = "<insert-your-class-id>"
private val passId = UUID.randomUUID().toString()

private val newObjectJson = """
    {
      "
iss": "$issuerEmail",
      "
aud": "google",
      "
typ": "savetowallet",
      "
iat": ${Date().time / 1000L},
      "
origins": [],
      "
payload": {
        "
genericObjects": [
          {
            "
id": "$issuerId.$passId",
            "
classId": "$passClass",
            "
genericType": "GENERIC_TYPE_UNSPECIFIED",
            "
hexBackgroundColor": "#4285f4",
           
"logo": {
             
"sourceUri": {
               
"uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg"
             
}
           
},
           
"cardTitle": {
             
"defaultValue": {
               
"language": "en",
               
"value": "Google I/O '22  [DEMO ONLY]"
             
}
           
},
           
"subheader": {
             
"defaultValue": {
               
"language": "en",
               
"value": "Attendee"
             
}
           
},
           
"header": {
             
"defaultValue": {
               
"language": "en",
               
"value": "Alex McJacobs"
             
}
           
},
           
"barcode": {
             
"type": "QR_CODE",
             
"value": "$passId"
           
},
           
"heroImage": {
             
"sourceUri": {
               
"uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/google-io-hero-demo-only.jpg"
             
}
           
},
           
"textModulesData": [
             
{
               
"header": "POINTS",
               
"body": "${Random.nextInt(0, 9999)}",
               
"id": "points"
             
},
             
{
               
"header": "CONTACTS",
               
"body": "${Random.nextInt(1, 99)}",
               
"id": "contacts"
             
}
           
]
         
}
       
]
     
}
   
}
   
"""

最后,返回 onCreate 方法,向“Add to Google Wallet”按钮添加点击处理程序,以便使用客户端中的 savePasses 方法启动操作:

private val addToGoogleWalletRequestCode = 1000

private lateinit var layout: ActivityCheckoutBinding
private lateinit var addToGoogleWalletButton: View

override fun onCreate(savedInstanceState: Bundle?) {
   
super.onCreate(savedInstanceState)

   
// Use view binding to access the UI elements
    layout
= ActivityCheckoutBinding.inflate(layoutInflater)
    setContentView
(layout.root)

    addToGoogleWalletButton
= layout.addToGoogleWalletButton.root
    addToGoogleWalletButton
.setOnClickListener {
        walletClient
.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
   
}

   
...
}

这样一来,您就使用之前创建的发卡机构 ID 和类 ID 为新对象定义了 JSON。当用户点击“Add to Google Wallet”按钮时,系统会调用 payClient.savePasses,并提示用户将新的卡券对象添加到 Google 钱包:

7. 处理结果

即将大功告成。最后,处理操作结果(成功或失败)。替换 onActivityResult 方法以包含以下代码:

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.
           
}

           
else -> {
               
// Handle unexpected (non-API) exception
           
}
       
}
   
}
}

借助此代码,您可以处理卡券添加成功状态、用户取消操作以及可能出现的任何错误。再次运行应用,确认是否可以按预期添加卡券并处理结果。

8. 恭喜

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

了解详情

如需查看完整示例,请参阅 GitHub 中的示例应用中的完整集成。

注册发卡机构帐号

当您准备好在生产环境中发布自己的卡券时,请前往 Google Pay 和钱包控制台,请求对 Google Wallet API 的访问权限,并授权您的 Android 应用对该 API 发出调用。如需了解详情,请参阅此文档