Google Wallet Loyalty Card Integration for Android: Turnkey
Users want loyalty cards on their phones. Google Wallet is the natural home on Android, installed on 1.5 billion devices. But integrating it is more complex than a simple 'Add to Wallet' button: you need to register an issuer, create a card class, generate JWT, and implement the client API. We have completed over 10 Google Wallet integrations and know all the pitfalls. We offer a turnkey implementation — from console to code, with guaranteed Google review approval in 1-3 days.
For example, for the CoffeeBoom coffee chain, we implemented Google Wallet integration with their bonus program, creating a personalized LoyaltyClass design and automatic point sync via CRM. The project took 3 days for development and 2 days for Google's review. Google Wallet integration ensures users always have their loyalty card handy, boosts engagement by 25–40%, and cuts plastic card production costs by 60–80%. However, stable operation requires proper JWT configuration, error handling, and adherence to Google's rules.
Official documentation: Google Wallet Loyalty API
Integration Steps
Integration proceeds in several stages:
- Create an issuer account in the Google Pay & Wallet Console.
- Create a LoyaltyClass — a card template with logo, colors, and fields.
- Generate a LoyaltyObject for each user server-side.
- Prepare a JWT for transmission to the client.
- Implement
PayClient.savePassesin the Android app. - Handle the add result and update data.
What to Prepare Before Integration?
Before writing code — three steps in the console:
- Create an Issuer Account
- Create a
LoyaltyClass— card template - Obtain service account credentials for server calls
issuerId is the numeric issuer identifier, e.g. 3388000000022142. classId is formed as {issuerId}.{classPostfix}, e.g. 3388000000022142.loyalty_main.
Here are the minimal fields for a LoyaltyClass:
| Field | Type | Example |
|---|---|---|
| id | string | 3388000000022142.loyalty_main |
| issuerName | string | YourShop |
| programName | localized | YourShop Loyalty Program |
| programLogo | Image | https://yourshop.com/logo.png |
| hexBackgroundColor | string | #1E5AC8 |
| countryCode | string | RU |
How to Generate a JWT for Each User?
Each user gets a separate LoyaltyObject. We create it server-side and package it into a JWT:
import jwt import time loyalty_object = { "id": f"3388000000022142.user_{user_id}", "classId": "3388000000022142.loyalty_main", "state": "ACTIVE", "loyaltyPoints": { "label": "Points", "balance": { "int": user_points } }, "barcode": { "type": "QR_CODE", "value": f"USER-{user_id}", "alternateText": f"USER-{user_id}" }, "textModulesData": [ { "header": "Tier", "body": user_tier, "id": "tier" } ] } # Create the object via API service.loyaltyobject().insert(body=loyalty_object).execute() # Generate JWT for transmission to client payload = { "iss": service_account_email, "aud": "google", "typ": "savetowallet", "iat": int(time.time()), "payload": { "loyaltyObjects": [{ "id": loyalty_object["id"] }] } } token = jwt.encode(payload, private_key, algorithm="RS256") The JWT is passed to the mobile app. JWT lifetime is at most 1 hour, so generate it just before sending.
How to Add a Card in Android via PayClient?
import com.google.android.gms.pay.Pay import com.google.android.gms.pay.PayApiAvailabilityStatus import com.google.android.gms.pay.PayClient private lateinit var walletClient: PayClient override fun onCreate(savedInstanceState: Bundle?) { walletClient = Pay.getClient(this) checkWalletAvailability() } private fun checkWalletAvailability() { walletClient .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES) .addOnSuccessListener { status -> if (status == PayApiAvailabilityStatus.AVAILABLE) { showAddToWalletButton() } } } private fun saveToWallet(jwt: String) { walletClient.savePasses(jwt, this, ADD_TO_GOOGLE_WALLET_REQUEST_CODE) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == ADD_TO_GOOGLE_WALLET_REQUEST_CODE) { when (resultCode) { RESULT_OK -> handleSuccess() RESULT_CANCELED -> handleCanceled() PayClient.SavePassesResult.SAVE_ERROR -> data?.let { handleError(it.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)) } } } } PayClient.RequestType.SAVE_PASSES checks that Google Wallet is installed and working. On devices without GMS (Huawei), Google Wallet is unavailable — provide a fallback.
How to Update Card Data After Issuance?
To change the points balance — send a PATCH request to the existing object:
patch_body = { "loyaltyPoints": { "balance": { "int": new_points_value } } } service.loyaltyobject().patch( resourceId=f"3388000000022142.user_{user_id}", body=patch_body ).execute() Google Wallet syncs changes to the device within 2-5 minutes. No push notifications needed — the system updates the card automatically.
Google Wallet or PassKit: Which to Choose?
| Criterion | Google Wallet | PassKit (iOS) |
|---|---|---|
| Format | REST API, JSON | PKPass Archive |
| Development time | 2-3 days | 4-5 days |
| Offline work | Requires network for sync | Full offline support |
| Data update | Automatic via API | Requires push notification |
Google Wallet doesn't require a file archive — everything is through REST API. This speeds up development by 2x and simplifies maintenance. However, on iOS, PassKit works faster offline.
What Our Work Includes?
- Server-side: LoyaltyClass creation, LoyaltyObject and JWT generation, API for data updates
- Client-side: PayClient integration in the Android app, handling add results
- Testing: verification on devices with different Android versions, including Google Wallet emulation
- Documentation: description of all endpoints and developer instructions
- Post-launch support: assistance with Google review, error monitoring
Common Integration Mistakes
- Incorrect classId format: must be
{issuerId}.{postfix}, otherwise Google rejects the request. - Expired JWT: lifetime must not exceed 1 hour, otherwise the client gets an error.
- Missing service account: without correct credentials, the API won't authorize requests.
- Ignoring reviewStatus: while the class is in UNDER_REVIEW status, cards cannot be added to real devices.
Ensure all fields are filled and the server script uses the correct issuerId.
Timeline
2–3 days: LoyaltyClass creation, server-side object and JWT generation, PayClient integration in the Android app. Plus 1–3 days for Google's class review. Pricing is calculated individually. Order a turnkey integration — we'll assess your project and provide a timeline.
Our experience — 5+ years in mobile development, over 10 Google Wallet integrations, hundreds of successfully added cards. We guarantee correct setup on the first try and review approval. Contact us, and we'll find the optimal solution for your business.







