Google Wallet.
Let members save loyalty cards, stamp cards, vouchers, and prepaid passes to Google Wallet for quick access.
Early Access: The Google Wallet integration is available for early access. Try it out and share your feedback. Your input shapes how this feature evolves. Some functionality may change as we refine the experience.
Google Wallet integration lets your members save their loyalty cards, stamp cards, vouchers, and prepaid passes to Google Wallet. Passes update when points change, stamps are earned, vouchers are redeemed, or pass visits are ticked off. No app download required.
What It Does
| Feature | Description |
|---|---|
| Add to Google Wallet | Members see a localized "Add to Google Wallet" button on their card, stamp card, or voucher view |
| Real-Time Updates | Pass data syncs automatically when points, stamps, or voucher status changes |
| Barcode/QR Support | Each pass includes a QR code that staff can scan |
| Deactivation Sync | When a card is deactivated or the toggle is turned off, passes are revoked from all members |
| Locale-Aware Buttons | The official Google button SVG is shown in the member's language |
How It Works
- Admin enables the system-wide feature flag (
FEATURE_GOOGLE_WALLET=true) and configures credentials - Admin grants Google Wallet permission to a partner via the partner settings
- Partner toggles "Google Wallet" on for individual cards, stamp cards, vouchers, or prepaid passes
- Members see the "Add to Google Wallet" button and save the pass to their phone
- System automatically updates passes when data changes (points earned, stamps added, voucher redeemed)
Roles & Permissions
| Role | Can Do |
|---|---|
| Admin | Enable feature flag, configure credentials, grant partner permission |
| Partner | Toggle Google Wallet on/off per card, stamp card, voucher, or prepaid pass |
| Member | Save passes to their Google Wallet, see real-time updates |
Admin Setup
1. Google Cloud Prerequisites
Before configuring Reward Loyalty, you need a Google Cloud project with a service account.
Create a project and enable the API:
- Go to the Google Cloud Console
- Create a new project (or use an existing one)
- Enable the Google Wallet API: navigate to APIs & Services → Library, search for "Google Wallet API", and click Enable
Create a service account:
- Open the ☰ navigation menu (top-left hamburger icon) and go to IAM & Admin → Service Accounts. Do not use the "Create credentials" button on the API page. That creates the wrong credential type.
- Click Create Service Account
- Enter a name (e.g.
reward-loyalty-wallet) and click Create and Continue - On the "Grant this service account access" step, skip it and click Continue. No roles are needed. The Wallet API uses its own issuer-level permissions.
- On the "Grant users access" step, skip it and click Done. This controls who else in your org can manage this service account.
Download the JSON key:
- You are now on the service accounts list. Click on the service account you created.
- Go to the Keys tab
- Click Add key → Create new key
- In the dialog that appears, select JSON and click Create
- A
.jsonfile downloads to your computer. Back up this file. You cannot download it again. - Open the JSON file and note the
client_emailvalue (e.g.[email protected]). You will need this in the next step.
For the official Google guide, see Google Wallet Prerequisites.
2. Google Wallet Issuer Account
Get your Issuer ID:
- Go to the Google Pay & Wallet Console
- Sign in with the Google account that owns your Cloud project
- In the left sidebar, click Google Wallet API (not Google Pay API). If this is your first time, click Build your first pass to initialize the Wallet API section.
- Your Issuer ID appears at the top of the page next to the heading. It is a long numeric value like
3388000000023138604. This is not the Merchant ID shown on the main dashboard (that alphanumeric code is for Google Pay, not Google Wallet).
Authorize your service account:
- In the left sidebar, click Users
- Click Invite a user
- Paste the service account email you noted in step 14 (the
client_emailfrom your JSON key file) - Set the Access level to Admin
- Click Invite
Add test accounts (demo mode only):
- While your account is in demo mode, only authorized test accounts can see passes on their phones. Go back to Google Wallet API in the left sidebar, click Set up test accounts, and add the personal Gmail addresses of anyone who needs to test. Console admins and developers can always test without being added here.
- Once you request and receive publishing access, all users can see passes and this step is no longer needed.
3. Configure Credentials
You need to give Reward Loyalty the JSON key file you downloaded. There are two ways to do this. Pick one.
Option A: Inline JSON in .env (recommended for Docker, cloud, and managed hosting)
- Open the downloaded
.jsonfile in a text editor - Remove all line breaks so the entire JSON is on one line. Most editors have a "Join Lines" command, or you can run this in a terminal:
cat ~/Downloads/your-key-file.json | tr -d '\n' | tr -s ' '
- Copy the single-line result and paste it into your
.envfile, wrapped in single quotes:
GOOGLE_WALLET_CREDENTIALS_JSON='{"type":"service_account","project_id":"your-project","private_key_id":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n","client_email":"...","client_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/...","universe_domain":"googleapis.com"}'
The single quotes are required. Without them, the double quotes inside the JSON break the
.envparser and cause a 500 error. Do not replace the internal double quotes. JSON requires them. The\ncharacters insideprivate_keyare literal escape sequences and should stay as-is.
Option B: File path (simpler for traditional server hosting)
- Create the credentials directory inside your Reward Loyalty installation:
mkdir -p storage/credentials
- Copy the downloaded
.jsonfile into that directory:
cp ~/Downloads/your-key-file.json storage/credentials/google-wallet-sa.json
- Add the path to your
.envfile:
GOOGLE_WALLET_CREDENTIALS_PATH=storage/credentials/google-wallet-sa.json
The path is relative to your project root. Do not place the file in the
public/directory.
Remaining .env variables
# Enable the feature
FEATURE_GOOGLE_WALLET=true
# Your issuer ID from the Google Pay & Wallet Console
GOOGLE_WALLET_ISSUER_ID=3388000000012345678
If both
GOOGLE_WALLET_CREDENTIALS_JSONandGOOGLE_WALLET_CREDENTIALS_PATHare set, the inline JSON takes priority.
After updating .env, clear the config cache:
php artisan config:clear
4. Grant Partner Permission
After configuring credentials, you need to grant Google Wallet access to each partner individually.
- Log in as Admin
- Go to Administration → Partners
- Click Edit on the partner you want to enable
- Go to the Permissions tab
- Enable the Google Wallet toggle
- Save
The partner can now see the Google Wallet toggle on their cards. Repeat for each partner who needs access.
5. Verify Configuration
Go to Settings → Integrations in the admin sidebar. The Google Wallet status card shows:
- Configured: issuer ID and credentials are set. The integration is ready to use.
- Not Configured: one or both are missing. Check your
.envfile and runphp artisan config:clear.
Partner Guide
Enabling Google Wallet on a Card
Once your admin has granted Google Wallet permission to your account, you can enable it on individual cards.
- Go to Loyalty Cards, Stamp Cards, or Vouchers
- Click Edit on the card you want to enable
- Go to the Details tab
- Find the Google Wallet toggle and switch it on
- Save
If you do not see the Google Wallet toggle, your admin has not yet enabled Google Wallet permission for your account. Contact your administrator.
Members who are enrolled in this card will now see an "Add to Google Wallet" button on their card view.
Pass Design — How Your Card Appears in Google Wallet
Google Wallet passes reuse the visual elements you already configured on your cards. No extra design work is needed. Here is exactly which fields are used for each pass type.
Loyalty Cards
┌─────────────────────────────────────┐
│ [Logo] Partner Name │ ← Logo image + partner name
│ │
│ Card Title │ ← Card title
│ │
│ points │
│ 2,000 │ ← Current point balance
│ │
│ ┌───────────┐ │
│ │ QR Code │ │ ← Staff earn-points URL
│ └───────────┘ │
│ Member Identifier │ ← Member code
│─────────────────────────────────────│
│ Background Image │ ← Background image (hero)
│ │
└─────────────────────────────────────┘
| Card Setting | Google Wallet Field | Notes |
|---|---|---|
| Logo | Pass logo (top-left circle) | Falls back to a default icon if not uploaded |
| Card title | Program name (large text) | Uses the member's current locale |
| Background color | Top half of the pass | The solid color area behind the title and QR code |
| Background image | Hero image (bottom half) | Displayed below the QR code. Optional — if not uploaded, the color fills the full card |
| Partner name | Issuer name (next to logo) | Taken from your partner/business name |
| Point balance | Points display | Updates automatically when points change |
| QR code | Barcode | Contains the staff earn-points URL — staff can scan directly from Google Wallet |
Logo and background image are the images you upload on the card's Media tab. See Creating Cards for image requirements.
Stamp Cards
┌─────────────────────────────────────┐
│ [Logo] Partner Name │ ← Logo image + partner name
│ │
│ Partner Name │ ← Subheader
│ Stamp Card Title │ ← Card title (large)
│ │
│ ┌───────────┐ │
│ │ QR Code │ │ ← Staff stamp-claim URL
│ └───────────┘ │
│ │
└─────────────────────────────────────┘
Progress: 3 / 10 ← Current stamps / required
Reward: Free Coffee ← Reward title
| Card Setting | Google Wallet Field | Notes |
|---|---|---|
| Logo | Pass logo (top-left circle) | Falls back to a default icon if not uploaded |
| Stamp card title | Header text (large) | Uses the member's current locale |
| Background color | Full pass background | The solid color behind everything |
| Reward title | "Reward" text module | Shows what the member earns when completed |
| Partner name | Card title + subheader | Displayed above and below the main title |
| Stamp progress | "Progress" text module | Shows e.g. "3 / 10" — updates when stamps are earned |
| QR code | Barcode | Contains the staff stamp URL — staff can scan directly from Google Wallet |
Stamp cards use Google's Generic pass type, which does not support a hero image. Only the background color and logo appear. See Designing Your Cards for logo specifications.
Prepaid Passes
┌─────────────────────────────────────┐
│ [Logo] Partner Name │ ← Logo image + partner name
│ │
│ Partner Name │ ← Subheader
│ Pass Name │ ← e.g. "10-Visit Wash Pass"
│ │
│ ┌───────────┐ │
│ │ QR Code │ │ ← Staff use-pass URL
│ └───────────┘ │
│ │
└─────────────────────────────────────┘
Visits left: 6 / 10 ← Remaining / total (or Unlimited)
Expires: Jul 10, 2026 ← Valid until date (if set)
| Card Setting | Google Wallet Field | Notes |
|---|---|---|
| Logo | Pass logo (top-left circle) | Tries the pass product logo, then a default icon |
| Pass name | Header text (large) | Uses the member's current locale |
| Background color | Full pass background | The solid color behind everything |
| Partner name | Card title + subheader | Displayed above and below the pass name |
| Visits left | "Visits left" text module | Updates after each scan; unlimited passes show Unlimited |
| Valid until | Expiry text module | Shown when the pass has a validity window |
| QR code | Barcode | Contains the staff use-pass URL — staff can scan directly from Google Wallet |
Prepaid passes use Google's Generic pass type, like stamp cards, so no hero image appears. Each sold pass is its own Google Wallet object: a member holding two passes of the same product can save both. Enable the toggle per pass product on its Details tab.
Vouchers
┌─────────────────────────────────────┐
│ [Logo] Partner Name │ ← Logo + partner name
│ │
│ Voucher Title │ ← e.g. "Free Pastry"
│ │
│ ┌───────────┐ │
│ │ QR Code │ │ ← Staff redemption URL
│ └───────────┘ │
│ Voucher Code │ ← e.g. CAFDCBAB6
│─────────────────────────────────────│
│ Background Image │ ← Background image (hero)
│ │
└─────────────────────────────────────┘
Expires: Feb 1, 2027 ← Valid until date
From: The Daily Grind ← Partner name
| Card Setting | Google Wallet Field | Notes |
|---|---|---|
| Logo | Pass logo (top-left circle) | Tries voucher logo → partner logo → default icon |
| Voucher title | Offer title (large text) | Uses the member's current locale |
| Background color | Top half of the pass | The solid color area behind the title and QR code |
| Background image | Hero image (bottom half) | Displayed below the QR code. Optional — if not uploaded, the color fills the full card |
| Voucher code | Barcode alternate text | Displayed below the QR code |
| Valid until | Expiration date | Shows when the voucher expires |
| QR code | Barcode | Contains the staff redemption URL — staff can scan directly from Google Wallet |
Logo and background image are the images you upload on the voucher's Media tab. See Voucher Card Design for image requirements.
Design Tips for Google Wallet
- Upload a logo. Passes without a logo show a generic icon or the first letter of your business name. A proper logo makes your pass instantly recognizable.
- Choose a good background color. This is the most visible element — it fills the top half (or full card for stamp cards). Use your brand color.
- Add a background image. For loyalty cards and vouchers, the background image appears as a large hero below the QR code. Use a high-quality, relevant photo (product shots, your storefront, lifestyle imagery).
- Images must be publicly accessible. Google fetches your images from your server. Images served from
localhostor private networks will not load. See Local Development below.
What Members See
- A localized "Add to Google Wallet" button on every card, stamp card, voucher, or prepaid pass that has Google Wallet enabled
- The button is always visible, even before the member has followed or enrolled in the card
- Tapping the button auto-enrolls the member (if not already enrolled) and opens Google Wallet
- The pass shows the card name, current points, stamp progress, or visits left, and a QR code
- Pass data updates when points are earned, stamps are collected, or a voucher is redeemed
No enrollment or transactions are required to see the button. The member does not need to follow the card first. Clicking the button handles enrollment automatically.
When the Button Does Not Appear
The "Add to Google Wallet" button has three conditions, all of which must be met:
- System feature flag:
FEATURE_GOOGLE_WALLET=truein.env - Partner permission: admin has granted Google Wallet permission to the partner
- Card toggle: partner has enabled Google Wallet on the specific card
If the button is missing, check these three conditions in order.
Button Behavior by Member State
| Member State | Button Behavior |
|---|---|
| Logged in, enrolled in card | Provisions the pass and redirects to Google Wallet |
| Logged in, not enrolled | Auto-enrolls the member, provisions the pass, then redirects to Google Wallet |
| Not logged in | Redirects to login page first, then continues the save flow |
Disabling Google Wallet
Toggle the switch off and save. All issued passes for that card will be revoked. Members' saved passes will show as inactive.
Member Guide
Saving a Card to Google Wallet
- Open any loyalty card, stamp card, or voucher
- Look for the "Add to Google Wallet" button below the card
- Tap the button
- If you are not logged in, you will be asked to log in first
- Confirm to save the pass in Google Wallet
Viewing Your Pass
- Open the Google Wallet app on your phone or visit wallet.google.com on desktop
- Your loyalty card, stamp card, or voucher appears with current details
- Data updates automatically when you earn points, collect stamps, or redeem a voucher
Pass States
| Event | What Happens |
|---|---|
| Points earned / stamps added | Pass updates with new balance |
| Voucher redeemed | Pass shows "Completed" |
| Voucher expired | Pass shows "Expired" |
| Card deactivated by partner | Pass shows "Inactive" |
Testing
Test Mode Checklist
- Set
FEATURE_GOOGLE_WALLET=truein.env - Configure your issuer ID and credentials
- Create a test card and enable Google Wallet
- Enroll a test member
- Verify the "Add to Google Wallet" button appears
- Save the pass and check it in Google Wallet
- Earn points or stamps and verify the pass updates
Common Issues
| Problem | Solution |
|---|---|
| Button doesn't appear | Check all three conditions: feature flag, partner permission, card toggle |
| "Google Wallet credentials not configured" | Verify GOOGLE_WALLET_ISSUER_ID and credential path/JSON in .env |
| "not a valid id" when clicking button | The pass was never created on Google's servers. Check the logs for provisioning errors. Most common cause: image URLs are not publicly accessible (see local development note below). Also verify your GOOGLE_WALLET_ISSUER_ID matches the Issuer ID in the Google Pay & Wallet Console. |
| "Image cannot be loaded" in logs | Google needs to fetch card images from a public URL. Local development URLs like http://localhost or http://app.test will fail. Use a tunnel (ngrok, Expose) or test on a publicly accessible staging server. |
| Pass doesn't update after earning points/stamps | If you use the sync queue driver (default), updates happen inline. If you use database or redis, make sure your queue worker processes the google-wallet queue: php artisan queue:work --queue=default,google-wallet |
| Pass shows wrong data | Trigger a manual update by toggling the card off and on |
Local Development
Google Wallet provisioning requires a publicly accessible server. Google's API fetches card images (logo, background) from your server. On local development, this fails because URLs like http://app.test are not reachable by Google.
What works locally:
- Configuring credentials and issuer ID
- Seeing the "Add to Google Wallet" button on the page
- Verifying the button generates a valid JWT
What requires a public URL:
- Actually saving a pass to Google Wallet (Google needs to fetch images)
- Pass provisioning (class and object creation)
To test the full flow, either deploy to a staging server or use a tunnel tool like ngrok to expose your local server.
Feedback & Bug Reports
If you encounter issues with Google Wallet passes:
- Note the specific card/stamp/voucher and member involved
- Check the application logs for
Google Walletentries - Report the issue through your usual support channel, including:
- What you expected to happen
- What actually happened
- The card type (loyalty, stamp, or voucher)
- Whether the pass was ever saved successfully
Technical Details
| Detail | Value |
|---|---|
| Queue | google-wallet (optional, only relevant if you run a dedicated queue worker with database or redis driver) |
| Retry policy | 3 attempts with exponential backoff (10s, 30s, 60s) |
| Save flow | Synchronous provisioning with async fallback. If Google's servers respond within the timeout, the member is redirected to Google Wallet. If provisioning times out, the system queues the job in the background and shows a retry message |
| Pass types | LoyaltyObject (loyalty cards), GenericObject (stamp cards), OfferObject (vouchers) |
| QR codes | Each pass contains a staff-facing URL (earn points, claim stamps, or redeem voucher) |
| Image source | Logo and background images are fetched by Google from your server — must be publicly accessible |