Google Wallet pass integration in mobile app

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Google Wallet pass integration in mobile app
Medium
from 1 business day to 3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Google Wallet Integration for Access Passes in Mobile Apps

An access pass in Google Wallet is a GenericObject on top of GenericClass. Generic is the universal type for anything that isn't a ticket, boarding pass, or coupon: parking pass, membership card, loyalty card, subscription, work badge. In the API, it's the most flexible type: field structure is defined arbitrarily via textModulesData, linksModuleData, and imageModulesData.

GenericObject Structure

def create_access_pass(class_id: str, holder_name: str,
                        pass_id: str, access_level: str) -> dict:
    issuer_id = "YOUR_ISSUER_ID"

    return {
        "id": f"{issuer_id}.pass_{pass_id}",
        "classId": class_id,
        "state": "ACTIVE",
        "cardTitle": {
            "defaultValue": {"language": "en", "value": "Employee Pass"}
        },
        "subheader": {
            "defaultValue": {"language": "en", "value": "Access Level"}
        },
        "header": {
            "defaultValue": {"language": "en", "value": access_level}  # "A1 — all zones"
        },
        "textModulesData": [
            {
                "header": "Holder",
                "body": holder_name,
                "id": "holder"
            },
            {
                "header": "Pass ID",
                "body": pass_id,
                "id": "pass_id"
            },
            {
                "header": "Valid Until",
                "body": "12/31/2024",
                "id": "valid_until"
            }
        ],
        "barcode": {
            "type": "QR_CODE",
            "value": pass_id,
            "alternateText": pass_id[:8].upper()
        },
        "heroImage": {
            "sourceUri": {
                "uri": "https://yourcompany.com/office-photo.jpg"
            }
        },
        "validTimeInterval": {
            "start": {"date": "2024-01-01T00:00:00Z"},
            "end": {"date": "2024-12-31T23:59:59Z"}
        },
        "notifications": {
            "expiryNotification": {
                "enableNotification": True
            }
        }
    }

notifications.expiryNotification — Google Wallet automatically notifies the user 3 days before expiration. No additional server-side logic is required.

GenericClass: Minimal Configuration

def create_generic_class(class_suffix: str) -> dict:
    issuer_id = "YOUR_ISSUER_ID"

    return {
        "id": f"{issuer_id}.{class_suffix}",
        "issuerName": "Your Company",
        "reviewStatus": "UNDER_REVIEW",
        "enableSmartTap": False,  # True only if you have NFC readers
        "multipleDevicesAndHoldersAllowedStatus": "ONE_USER_ONE_DEVICE"
    }

ONE_USER_ONE_DEVICE — the pass cannot be transferred to another user or saved on multiple devices of one account. For corporate passes, this is the right restriction.

Creating Class via REST API Before First JWT

The class must be created once via API — you can only embed the object in JWT, not create the class via JWT:

from googleapiclient.discovery import build
from google.oauth2 import service_account

def ensure_generic_class_exists(class_data: dict) -> bool:
    creds = service_account.Credentials.from_service_account_file(
        'service-account.json',
        scopes=['https://www.googleapis.com/auth/wallet_object.issuer']
    )
    service = build('walletobjects', 'v1', credentials=creds)

    try:
        service.genericclass().get(resourceId=class_data["id"]).execute()
        return True  # already exists
    except HttpError as e:
        if e.resp.status == 404:
            service.genericclass().insert(body=class_data).execute()
            return True
    return False

Android: Complete Flow

class PassActivity : AppCompatActivity() {
    private val walletClient by lazy {
        Wallet.getWalletClient(this, WalletOptions.Builder()
            .setEnvironment(WalletConstants.ENVIRONMENT_PRODUCTION)
            .build())
    }

    private val savePassLauncher = registerForActivityResult(
        ActivityResultContracts.StartIntentSenderForResult()
    ) { result ->
        when (result.resultCode) {
            RESULT_OK -> {
                analytics.track("wallet_pass_added")
                binding.addToWalletBtn.text = "Already in Wallet"
                binding.addToWalletBtn.isEnabled = false
            }
            RESULT_CANCELED -> Unit
        }
    }

    fun onAddToWalletClicked() {
        viewModel.generatePassJwt().observe(this) { jwt ->
            walletClient.savePassesViaIntent(
                SavePassesRequest.newBuilder().setJwt(jwt).build()
            ) { result ->
                result.intentSender?.let {
                    savePassLauncher.launch(IntentSenderRequest.Builder(it).build())
                } ?: run {
                    // Already added
                    binding.addToWalletBtn.isEnabled = false
                }
            }
        }
    }
}

Updating Pass (Access Level Change)

def update_pass_access_level(object_id: str, new_level: str):
    service = build('walletobjects', 'v1', credentials=creds)
    service.genericobject().patch(
        resourceId=object_id,
        body={
            "header": {
                "defaultValue": {"language": "en", "value": new_level}
            }
        }
    ).execute()

Changes appear in the user's Wallet within minutes — without reissuing the pass.

Timeline

1–3 days. Basic pass with QR code and auto-expiration notification — 1.5 days. Updates via API + device transfer restrictions — 2–3 days. Pricing is calculated individually.