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

  1. Save your service account key in the Laravel project:
storage/app/google-wallet/service-account.json
  1. 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!