開始使用 Android SDK

請先完成所有必要條件,再開始使用 Android SDK。

您可以使用 Android SDK 在 Google 錢包中新增票證。在應用程式中新增「Google 錢包」按鈕後,使用者就能將票證新增至 Google 錢包,享受輕鬆又愉快的體驗。

請按照下列步驟在 Android 應用程式中新增「Google Wallet」按鈕:

1. 建立票證物件

注意:需要票證類別才能建立票證物件。如果尚未建立票證類別,請按照這篇文章中的指示操作。定義對應的 GenericObject,包括下列必要屬性:

  • classId:在先決條件中建立的票證類別 ID。
  • id:物件的專屬 ID。

  • genericType:資訊卡所屬的類型。如果您的卡片與可用選項不符,請設為 GENERIC_TYPE_UNSPECIFIED
  • cardTitle:票證的標題。
  • header:票證的標頭,例如使用者名稱。
此外,建議你加入下列屬性:
  • logo
  • subheader

如要進一步瞭解如何在一般傳遞中表示這些屬性,請參閱版面配置範本

以下是一般票證範例的定義:

JSON

      
{
  "id": "ISSUER_ID.OBJECT_ID",
  "classId": "ISSUER_ID.CLASS_ID",
  "genericType": "GENERIC_TYPE_UNSPECIFIED",
  "cardTitle": {
    "defaultValue": {
      "language": "en",
      "value": "Card title"
    }
  },
  "subheader": {
    "defaultValue": {
      "language": "en",
      "value": "Attendee"
    }
  },
  "header": {
    "defaultValue": {
      "language": "en",
      "value": "Alex McJacobs"
    }
  },
  "logo": {
    "sourceUri": {
      "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg"
    }
  }
}
      
    

2. 使用物件建立未簽署的 JWT

建立 GenericObject 後,請用 payload.GenericObjects 屬性包裝未簽署的 JWT,如以下程式碼片段所示:

JSON

{
  "iss": "OWNER_EMAIL_ADDRESS",
  "aud": "google",
  "typ": "savetowallet",
  "iat": "UNIX_TIME",
  "origins": [],
  "payload": {
      "genericObjects": [ NEW_OBJECT ]
  }
}

3. 在使用者介面中加入 Google 錢包按鈕

Google 錢包提供熟悉的按鈕,用於在應用程式中觸發「新增至 Google 錢包」流程。如要瞭解按鈕的向量素材資源,請參閱按鈕規範

您可以在 Android Studio 中透過 File > New > Vector Asset 匯入向量素材資源。在精靈中選取「本機檔案」,然後新增名稱 (例如: add_to_google_wallet_button.xml) 後,請在本機磁碟中找到要匯入的檔案。

現在,您可以使用匯入的可繪項目,在使用者介面中新增按鈕:

<ImageButton
    android:id="@+id/addToGoogleWalletButton"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:minWidth="200dp"
    android:clickable="true"
    android:src="@drawable/add_to_google_wallet_button" />

該按鈕的 layout_height 為 48 dp,寬度至少為 200 dp。

4. 檢查目標裝置是否支援 Google Wallet API

儲存新物件之前,請在 PayClient 類別呼叫 getPayApiAvailabilityStatus 方法,確保目標裝置可以使用 Google Wallet API。首先,請為您要顯示按鈕的活動新增成員變數,並在建立活動時將該按鈕執行個體化:

Kotlin

import com.google.android.gms.pay.PayClient

private lateinit var walletClient: PayClient

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

  walletClient = Pay.getClient(this)

  // Additional logic in your onCreate method
}

Java

import com.google.android.gms.pay.PayClient;

private final PayClient walletClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  walletClient = Pay.getClient(application);

  // Additional logic in your onCreate method
}

現在,請使用用戶端檢查 API 是否可用:

Kotlin

import com.google.android.gms.pay.PayApiAvailabilityStatus

private fun fetchCanUseGoogleWalletApi() {
  walletClient
    .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
    .addOnSuccessListener { status ->
      if (status == PayApiAvailabilityStatus.AVAILABLE) {
        // The API is available, show the button in your UI
      } else {
        // The user or device is not eligible for using the Pay API
      }
    }
    .addOnFailureListener {
      // Hide the button and optionally show an error message
    }
}

Java

import com.google.android.gms.pay.PayApiAvailabilityStatus;

private void fetchCanAddPassesToGoogleWallet() {
  walletClient
    .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
    .addOnSuccessListener(status -> {
      if (status == PayApiAvailabilityStatus.AVAILABLE) {
        // The API is available, show the button in your UI
      } else {
        // The user or device is not eligible for using the Pay API
      };
    })
    .addOnFailureListener(exception -> {
      // Google Play Services is too old, or API availability not verified
      // Hide the button and optionally show an error message
    });
}

最後,當您需要判斷 API 的可用性時,請呼叫應用程式上述定義的方法。

5. 將物件新增至 Google 錢包

只要將步驟 2 中未簽署的 JWT 傳遞至 savePasses 方法,即可新增 GenericObject。點選「Google 錢包」按鈕後,即可開始新增作業:

Kotlin

import android.os.Bundle
import android.view.View
import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding

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
  addToGoogleWalletButton.setOnClickListener {
    walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
  }

  // Additional logic in your onCreate method
}

Java

import android.os.Bundle;
import android.view.View;
import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding;

private static final int ADD_TO_GOOGLE_WALLET_REQUEST_CODE = 999;

private ActivityCheckoutBinding layout:
private View addToGoogleWalletButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Use view binding to access the UI elements
  layout = ActivityCheckoutBinding.inflate(getLayoutInflater());
  setContentView(layout.getRoot());

  addToGoogleWalletButton = layout.addToGoogleWalletButton;
  addToGoogleWalletButton.setOnClickListener(v -> {
    walletClient.savePasses(newObjectJson, this, ADD_TO_GOOGLE_WALLET_REQUEST_CODE);
  });

  // Additional logic in your onCreate method
}

savePasses 方法會觸發儲存流程,並在儲存流程完成後叫用 onActivityResult 方法。onActivityResult 的實作方式應如下所示:

Kotlin

import android.content.Intent

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  super.onActivityResult(requestCode, resultCode, data)

  if (requestCode == addToGoogleWalletRequestCode) {
    when (resultCode) {
      RESULT_OK -> {
        // Pass saved successfully
      }

      RESULT_CANCELED -> {
        // Save operation canceled
      }

      PayClient.SavePassesResult.SAVE_ERROR -> data?.let { intentData ->
        val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)
        // Handle error
      }

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

Java

import android.content.Intent;

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (requestCode == ADD_TO_GOOGLE_WALLET_REQUEST_CODE) {
    switch (resultCode) {
      case RESULT_OK: {
        // Pass saved successfully
        break;
      }

      case RESULT_CANCELED: {
        // Save operation canceled
        break;
      }

      case PayClient.SavePassesResult.SAVE_ERROR: {
        if (data != null) {
          String apiErrorMessage = data.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE);
          // Handle error
        }
        break;
      }

      default: {
        // Handle unexpected (non-API) exception
      }
    }
  }
}

成功新增票證後,resultCode 會包含 Activity.RESULT_OK 的值。

[僅用於測試] 通過

處於展示模式時,您建立的所有票證都會在票證的標題中加上額外文字「[TEST ONLY]」。以便區分試用版通行證和現場通行證。 一旦您獲得我們的團隊正式版核准,之後使用者在已連結裝置上重新開啟錢包應用程式時,展示模式票證就不會再顯示其他文字。

後續步驟