1. Introduction
Overview
The Google Wallet API allows you to engage with users through various types of passes: loyalty cards, offers, gift cards, event tickets, transit tickets, boarding passes, and more. Each pass type, or pass class, comes with use-case specific fields and features to enhance the user experience.
However, these might not fit every use case. To create a more customized experience, you can use the generic pass type. Here are some example use cases for the generic pass type:
- Parking passes
- Library membership cards
- Stored value vouchers
- Gym membership cards
- Reservations
You can use generic passes for any use case that can be presented with:
- Up to three rows of information
- (Optional) Barcode graphic
- (Optional) Details section
For more information on the Google Wallet API, or adding an Add to Google Wallet button to an Android application, please see the Google Wallet developer documentation.
Pass classes and objects
The Google Wallet API exposes methods to create the following:
Type | Description |
Pass class | A template for an individual pass object. It contains information common to all pass objects that belong to this class. |
Pass object | An instance of a pass class that is unique to a user ID. |
About this codelab
In this codelab, you will complete the following tasks.
- Create a new issuer account in demo mode
- Create a service account for issuing passes
- Create a new Generic pass class
- Create a new pass object
- Create an Add to Google Wallet button to save a pass
- Display the button in your Android app
- Handle the pass save result
Prerequisites
- Android Studio
- Git
- A Google Account with access to the Google Cloud console
- Node.js version 10 or greater
Objectives
After completing this codelab, you will be able to do the following:
- Add the Google Wallet SDK to your Android app
- Check if the Google Wallet API is available on an Android-powered device
- Create an Add to Google Wallet button
Support
If you are stuck at any point in the codelab, the google-pay/wallet-android-codelab GitHub repository contains a complete solution for reference.
2. Setup
In this step, you will create an Issuer account in demo mode. This will allow you to create pass classes and objects that can be added to user wallets. Next, you will create a Google Cloud project and service account. These will be used to programmatically create pass classes and objects in the same manner as a backend server. Last, you will authorize the Google Cloud service account to manage passes in your Google Wallet issuer account.
Sign up for a Google Wallet API issuer account
An Issuer account is necessary to create and distribute passes for Google Wallet. You can sign up using the Google Pay & Wallet Console. Initially, you will have access to create passes in demo mode. This means that only specific test users will be able to add passes you create. Test users can be managed in the Google Pay & Wallet Console.
For more information on demo mode, see the Generic pass prerequisites.
- Open the Google Pay & Wallet Console
- Follow the on-screen instructions to create an Issuer account
- Select Google Wallet API
- Confirm you understand the terms of service and privacy policy
- Copy the Issuer ID value to a text editor or other location
- Under the Manage tab, select Set up test accounts
- Add any email addresses you will use in this codelab
Enable the Google Wallet API
- Sign into the Google Cloud console
- If you don't already have a Google Cloud project, create one now (see Creating and managing projects for more information)
- Enable the Google Wallet API (also referred to as Google Pay for Passes API) for your project
Create a service account and key
A service account and a service account key are necessary to call the Google Wallet API. The service account is the identity that calls the Google Wallet API. The service account key contains a private key that identifies your application as the service account. This key is sensitive, so keep it confidential.
Create a service account
- In the Google Cloud console, open Service Accounts
- Enter a name, ID, and description for your service account
- Select CREATE AND CONTINUE
- Select DONE
Create a service account key
- Select your service account
- Select the KEYS menu
- Select ADD KEY, then Create new key
- Select the JSON key type
- Select CREATE
You will be prompted to save the key file to your local workstation. Make sure to remember its location.
Set the GOOGLE_APPLICATION_CREDENTIALS
environment variable
The GOOGLE_APPLICATION_CREDENTIALS
environment variable is used by Google SDKs to authenticate as a service account and access different APIs for a Google Cloud project.
- Follow the instructions in the Google Cloud Service account keys documentation to set the
GOOGLE_APPLICATION_CREDENTIALS
environment variable - Verify the environment variable is set in a new terminal (MacOS/Linux) or command-line (Windows) session (you may need to start a new session if you have one open already)
echo $GOOGLE_APPLICATION_CREDENTIALS
Authorize the service account
Lastly, you will need to authorize the service account to manage Google Wallet passes.
- Open the Google Pay & Wallet Console
- Select Users
- Select Invite a user
- Enter the email address of the service account (e.g.
test-svc@myproject.iam.gserviceaccount.com
) - Select either Developer or Admin from the Access level drop-down menu
- Select Invite
3. Create a Generic pass class
In this step, you will create the base class for your pass. Any time a new pass is created for a user, it will inherit the properties defined in the pass class.
The pass class you will create during this codelab uses the flexibility of Generic passes to create an object that works as both an identity badge and challenge points tracker. When a pass object is created from this class, it will look like the following graphic.
Pass classes can be created directly in the Google Pay & Wallet Console or by using the Google Wallet API. In this codelab, you will create the Generic pass class using the API. This follows the process a private, backend server would use to create pass classes.
- Clone the google-pay/wallet-android-codelab GitHub repository to your local workstation
git clone https://github.com/google-pay/wallet-android-codelab.git
- Open the cloned repository in your terminal or command-line prompt
- Navigate to the
backend
directory (these scripts imitate backend server actions)cd backend
- Install the Node.js dependencies
npm install .
- In the
backend
directory, opengeneric_class.js
- Replace the value of
issuerId
with your Issuer ID from the Google Pay & Wallet Console// TODO: Define Issuer ID let issuerId = 'ISSUER_ID';
- In your terminal or command-line prompt, run the
generic_class.js
scriptnode generic_class.js
When your code runs, it will create a new pass class and output the class ID. The class ID is made up of the issuer ID followed by a developer-defined suffix. In this case, the suffix is set to codelab_class
(the class ID would look similar to 1234123412341234123.codelab_class
). The output logs will also include the response from the Google Wallet API.
4. Open the project in Android Studio
The GitHub repository you cloned contains an Android project with an empty activity. In this step, you will edit in this activity to include an Add to Google Wallet button on a product page.
- Open Android Studio
- Select File, then Open
- Select the
android
directory in the repository - Select Open
Add the Google Wallet SDK to your app
- Open the module-level Gradle build file (
android/app/build.gradle
) - Add the Google Wallet SDK to the
dependencies
section// 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"
- Save the file
- Select File, then Sync Project with Gradle Files
5. Create the Add to Google Wallet button
In this step, you will create an Add to Google Wallet button and add it to an existing activity. The assets for the button have already been included in the project. To include the button, you will create a separate layout file. Once added, the button will look like the following.
- Create a new layout file:
app/src/main/res/layout/add_to_google_wallet_button.xml
- Add the following content to the new layout file
<?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>
- Include the
add_to_google_wallet_button.xml
layout in the checkout activity layout file (app/src/main/res/layout/activity_checkout.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. Check if the Google Wallet API is available
If a user opens your app on a device that does not support the Google Wallet API, it may create a negative experience when they try to add the pass. If the user's device does not support the Google Wallet API, hiding the Add to Google Wallet button avoids potential confusion. There are various reasons why the API may be unavailable, such as the Android or Google Play Services versions being out of date or Google Wallet being unavailable in the user's country.
In this step, you will add logic to your app that checks if the Google Wallet API is available on the device. If so, the button will be rendered in the activity. Otherwise, the button will be hidden.
- Open the
CheckoutActivity.kt
file inapp/src/main/java/com/google/android/gms/samples/wallet/activity/
- Create a class property for the
PayClient
instance// TODO: Create a client to interact with the Google Wallet API private lateinit var walletClient: PayClient
- Instantiate the
PayClient
property in theonCreate
method// TODO: Instantiate the client walletClient = Pay.getClient(this)
- Create a method that checks if the Google Wallet SDK and API are available on the device and handle the result
// 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 } }
- Call the
fetchCanUseGoogleWalletApi
method in theonCreate
method to check whether the Google Wallet API is available// TODO: Check if the Google Wallet API is available fetchCanUseGoogleWalletApi()
When you run the app, you should now see the Add to Google Wallet button in the UI.
7. Create a Generic pass object
Now that you have verified that the Google Wallet API is available, you can create a pass and prompt your user to add it to their wallet. There are two flows for creating pass objects for users.
Create the pass object on the backend server
In this approach, the pass object is created on a backend server and returned to the client app as a signed JWT. This is best suited for cases where user adoption is high, as it ensures the object exists before the user tries to add it to their wallet.
Create the pass object when the user adds it to their wallet
In this approach, the pass object is defined and encoded into a signed JWT on the backend server. An Add to Google Wallet button is then rendered in the client app that references the JWT. When the user selects the button, the JWT is used to create the pass object. This is best suited for cases where user adoption is variable or unknown, as it prevents pass objects from being created and not used. This approach will be used in the codelab.
- Open the
backend/generic_pass.js
file - Replace the value of
issuerId
with your Issuer ID from the Google Pay & Wallet Console// TODO: Define Issuer ID let issuerId = 'ISSUER_ID';
- In your terminal or command-line prompt, run the
generic_pass.js
filenode generic_pass.js
- Copy the output token to your clipboard or a text editor
When your code runs, it will define a new pass object and embed it in a JWT. The JWT is then signed by the service account key you created previously. This authenticates the request to the Google Wallet API so that credentials do not need to be stored in the client app.
aside In a production environment, your backend system would be responsible for creating JWTs and returning them to clients. In this codelab, the generic_pass.js
script emulates this behavior and "returns" a token for you to use in the client app.
8. Add the pass to Google Wallet
Now that you have verified that the Google Wallet API is available and have created a signed JWT, you can prompt the user to add the pass to their wallet. In this step, you will add a listener to the Add to Google Wallet button that uses the Google Wallet API to save the pass in the user's wallet.
- Open the
app/src/main/CheckoutActivity.kt
file - Replace the value of
token
with the JWT you created previously// TODO: Save the JWT from the backend "response" private val token = "TOKEN"
- Create a class property to store the request code
// TODO: Add a request code for the save operation private val addToGoogleWalletRequestCode = 1000
- Set a listener for the Add to Google Wallet button
// TODO: Set an on-click listener on the "Add to Google Wallet" button addToGoogleWalletButton = layout.addToGoogleWalletButton. addToGoogleWalletButton.setOnClickListener { walletClient.savePassesJwt(token, this, addToGoogleWalletRequestCode) }
When a user selects the Add to Google Wallet button, the walletClient.savePassesJwt
method is called. This method prompts the user to add the new pass object to their Google Wallet.
9. Handle the savePassesJwt result
In the final step of this codelab, you will configure your app to handle the result of the walletClient.savePassesJwt
operation.
- Open the
app/src/main/CheckoutActivity.kt
file - Override the
onActivityResult
method to contain the following code// 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 } } } }
Now your app is able to handle the following scenarios:
- Successful pass addition
- User cancellation
- Unexpected errors
Run your app to confirm that you can add the pass and handle the result as expected.
10. Congratulations
Congratulations, you have successfully integrated the Google Wallet API on Android!
Learn more
Take a look at the complete integration in the google-pay/wallet-android-codelab GitHub repository.
Create passes and request production access
When you are ready to issue your own passes in production, go to the Google Pay & Wallet Console to request production access and authorize your Android app.
See the Android SDK Prerequisites to learn more.