feat: wire Google Wallet into loyalty enrollment, stamps, and points flows

Connect the fully-implemented Google Wallet service to the loyalty module:
- Create wallet class/object on customer enrollment
- Sync wallet passes on stamp and points operations
- Expose wallet URLs in storefront API responses
- Add conditional "Add to Google Wallet" buttons on dashboard and enroll-success pages
- Use platform-wide env var config (not per-merchant DB column)
- Add Google service account patterns to .gitignore
- Add LOYALTY_GOOGLE_* fields to app Settings
- Update deployment docs and add local testing guide

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 10:38:46 +01:00
parent 6c78827c7f
commit 32e4aa6564
13 changed files with 358 additions and 56 deletions

View File

@@ -203,14 +203,20 @@
<!-- Wallet Buttons -->
<div class="space-y-2 mb-4">
<button class="w-full flex items-center justify-center px-4 py-3 bg-black text-white rounded-lg hover:bg-gray-800 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Apple Wallet
</button>
<button class="w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Google Wallet
</button>
<template x-if="walletUrls.apple_wallet_url">
<a :href="walletUrls.apple_wallet_url" target="_blank" rel="noopener"
class="w-full flex items-center justify-center px-4 py-3 bg-black text-white rounded-lg hover:bg-gray-800 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Apple Wallet
</a>
</template>
<template x-if="walletUrls.google_wallet_url">
<a :href="walletUrls.google_wallet_url" target="_blank" rel="noopener"
class="w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Google Wallet
</a>
</template>
</div>
<button @click="showBarcode = false"

View File

@@ -29,14 +29,20 @@
Save your card to your phone for easy access:
</p>
<div class="space-y-2">
<button class="w-full flex items-center justify-center px-4 py-3 bg-black text-white rounded-lg hover:bg-gray-800 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Apple Wallet
</button>
<button class="w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Google Wallet
</button>
<template x-if="walletUrls.apple_wallet_url">
<a :href="walletUrls.apple_wallet_url" target="_blank" rel="noopener"
class="w-full flex items-center justify-center px-4 py-3 bg-black text-white rounded-lg hover:bg-gray-800 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Apple Wallet
</a>
</template>
<template x-if="walletUrls.google_wallet_url">
<a :href="walletUrls.google_wallet_url" target="_blank" rel="noopener"
class="w-full flex items-center justify-center px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
<span x-html="$icon('device-mobile', 'w-5 h-5 mr-2')"></span>
Add to Google Wallet
</a>
</template>
</div>
</div>
</div>
@@ -80,7 +86,19 @@
<script>
function customerLoyaltyEnrollSuccess() {
return {
...data()
...data(),
walletUrls: { google_wallet_url: null, apple_wallet_url: null },
async init() {
try {
const response = await apiClient.get('/storefront/loyalty/card');
if (response && response.wallet_urls) {
this.walletUrls = response.wallet_urls;
}
} catch (e) {
// Customer may not be authenticated (public enrollment)
console.log('Could not load wallet URLs:', e.message);
}
}
};
}
</script>