If you're building a loyalty program and want to offer your users a modern, digital wallet experience, Google Wallet is a fantastic choice. In this post, I’ll walk you through how to generate and save a digital loyalty card with Google Wallet using Laravel.
By the end, you’ll be able to generate a “Save to Google Wallet” link your users can click to store their loyalty card — complete with a QR code, points, and branding — directly on their phones.
🔧 What We'll Cover
- Setting up the Google Wallet API
- Creating a Laravel service to generate loyalty cards
- Building the "Save to Google Wallet" link
Let’s get started. 🚀
🧰 Prerequisites
Before we dive into code, here’s what you’ll need:
✅ A Google Cloud Project
✅ Google Wallet API enabled
✅ A Service Account Key
✅ Your Issuer ID (from Google Wallet Console)
Make sure your project has the Google Wallet API enabled, and your service account has the necessary permissions.
📁 Laravel Project Setup
- Save your service account key in the Laravel project:
storage/app/google-wallet/service-account.json
- Install required libraries:
composer require google/apiclient firebase/php-jwt
These packages help with Google API authentication and JWT generation.
🧠 Create the Google Wallet Service
Let’s encapsulate all logic in a single Laravel service class.
Create a file at:
app/Services/GoogleWalletService.php
namespace App\Services;
use Google\Client;
use Google\Service\Walletobjects\{LoyaltyClass, LoyaltyObject, Image, Barcode, LoyaltyPoints, LoyaltyPointsBalance};
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class GoogleWalletService
{
protected $credentialsPath;
public function __construct()
{
$this->credentialsPath = storage_path('app/google-wallet/service-account.json');
}
protected function getClient()
{
$client = new Client();
$client->setAuthConfig($this->credentialsPath);
$client->addScope('https://www.googleapis.com/auth/wallet_object.issuer');
return $client;
}
public function createLoyaltyCardForMember($user, $programName, $issuerName, $logoUri, $qrCode, $points, $uniqueId)
{
$client = $this->getClient();
$service = new \Google\Service\Walletobjects($client);
$issuerId = 'YOUR_ISSUER_ID'; // Replace with actual
$classId = "{$issuerId}.{$programName}";
$objectId = "{$issuerId}.member-{$uniqueId}";
// Loyalty Class (template, one-time setup)
try {
$loyaltyClass = new LoyaltyClass([
'id' => $classId,
'issuerName' => $issuerName,
'programName' => $programName,
'programLogo' => new Image(['sourceUri' => ['uri' => $logoUri]]),
'reviewStatus' => 'UNDER_REVIEW',
]);
$service->loyaltyclass->insert($loyaltyClass);
} catch (\Google\Service\Exception $e) {
if ($e->getCode() != 409) throw $e; // Already exists is fine
}
// Loyalty Object (user card)
$loyaltyObject = new LoyaltyObject([
'id' => $objectId,
'classId' => $classId,
'state' => 'active',
'accountName' => $user->name,
'accountId' => "USER-{$uniqueId}",
'barcode' => new Barcode([
'type' => 'qrCode',
'value' => $qrCode,
'alternateText' => 'Scan to redeem',
]),
'loyaltyPoints' => new LoyaltyPoints([
'balance' => new LoyaltyPointsBalance(['int' => $points]),
'label' => 'Points',
]),
]);
$service->loyaltyobject->patch($objectId, $loyaltyObject);
// Create JWT for Save to Google Wallet
$claims = [
'iss' => json_decode(file_get_contents($this->credentialsPath), true)['client_email'],
'aud' => 'google',
'typ' => 'savetowallet',
'payload' => [
'loyaltyObjects' => [
['id' => $objectId]
]
]
];
$jwt = JWT::encode(
$claims,
file_get_contents($this->credentialsPath),
'RS256'
);
return "https://pay.google.com/gp/v/save/{$jwt}";
}
}
🚀 Call It from Your Controller
Now let’s trigger the card generation from a controller:
use App\Services\GoogleWalletService;
public function generateLoyaltyCard(Request $request)
{
$user = auth()->user();
$service = new GoogleWalletService();
$url = $service->createLoyaltyCardForMember(
$user,
'MyProgram', // Program name
'My Company Inc.', // Issuer name
'https://mydomain.com/logo.png',
'1234567890', // QR value
100, // Loyalty points
$user->id
);
return redirect($url); // or return ['url' => $url];
}
🔐 What Does the Save URL Look Like?
The JWT generates a URL like:
https://pay.google.com/gp/v/save/eyJhbGciOiJSUzI1...
When the user opens it, Google Wallet lets them save the card instantly on their Android device.
✅ Tips
- Loyalty Class is created once — you'll get a
409 Conflict
if you try to re-insert. - Use a unique Object ID per user (e.g.,
member-USERID
). - You can update the object later to change points, barcode, etc.
- Set
'reviewStatus' => 'APPROVED'
once your template is verified by Google.
🎉 Example Output
A user's loyalty card in Google Wallet will show:
- Their name and account number
- Current loyalty point balance
- Scannable QR code
- Your logo and brand color
All securely saved to their Android device — no app required.
🧠 Final Thoughts
Integrating Google Wallet in Laravel takes a bit of setup, but the result is a seamless, modern loyalty experience your users will love. You’re giving them a scannable, branded card that lives in their digital wallet — ready at checkout.
Want an Apple Wallet version too? Drop a comment below and I’ll create that next!
💬 Let’s Connect
Got questions or ideas?
Let me know in the comments — or follow me for more Laravel + fintech tutorials!