Some checks failed
- Add wallet diagnostics page at /admin/loyalty/wallet-debug (super admin only) with explorer-sidebar pattern: config validation, class status, card inspector, save URL tester, recent enrollments, and Apple Wallet status panels - Fix Google Wallet fat JWT: include both loyaltyClasses and loyaltyObjects in payload, use UNDER_REVIEW instead of DRAFT for class reviewStatus - Fix StorefrontProgramResponse schema: accept google_class_id values while keeping exclude=True (was rejecting non-None values) - Standardize all module configs to read from .env file directly (env_file=".env", extra="ignore") matching core Settings pattern - Add MOD-026 architecture rule enforcing env_file in module configs - Add SVC-005 noqa support in architecture validator - Add test files for dev_tools domain_health and isolation_audit services - Add google_wallet_status.py script for querying Google Wallet API - Use table_wrapper macro in wallet-debug.html (FE-005 compliance) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
137 lines
4.3 KiB
Python
137 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Query Google Wallet API for class and object status.
|
|
|
|
Usage:
|
|
python scripts/google_wallet_status.py # List all classes
|
|
python scripts/google_wallet_status.py --class-id ID # Check specific class
|
|
python scripts/google_wallet_status.py --object-id ID # Check specific object
|
|
python scripts/google_wallet_status.py --fix-draft # Patch DRAFT classes to UNDER_REVIEW
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
from app.modules.loyalty.config import config
|
|
from app.modules.loyalty.services.google_wallet_service import GoogleWalletService
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Query Google Wallet API")
|
|
parser.add_argument("--class-id", help="Check a specific class ID")
|
|
parser.add_argument("--object-id", help="Check a specific object ID")
|
|
parser.add_argument(
|
|
"--fix-draft",
|
|
action="store_true",
|
|
help="Patch all DRAFT classes to UNDER_REVIEW for approval",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
svc = GoogleWalletService()
|
|
|
|
if not svc.is_configured:
|
|
print("Google Wallet is not configured.")
|
|
print(f" LOYALTY_GOOGLE_ISSUER_ID: {config.google_issuer_id or 'NOT SET'}")
|
|
print(f" LOYALTY_GOOGLE_SERVICE_ACCOUNT_JSON: {config.google_service_account_json or 'NOT SET'}")
|
|
sys.exit(1)
|
|
|
|
http = svc._get_http_client()
|
|
issuer_id = config.google_issuer_id
|
|
print(f"Issuer ID: {issuer_id}")
|
|
print()
|
|
|
|
if args.object_id:
|
|
_check_object(http, args.object_id)
|
|
return
|
|
|
|
if args.class_id:
|
|
_check_class(http, args.class_id)
|
|
return
|
|
|
|
# List all classes for this issuer
|
|
print("=== Loyalty Classes ===")
|
|
response = http.get(
|
|
"https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass",
|
|
params={"issuerId": issuer_id},
|
|
)
|
|
|
|
if response.status_code != 200:
|
|
print(f"Error: {response.status_code} - {response.text}")
|
|
sys.exit(1)
|
|
|
|
data = response.json()
|
|
classes = data.get("resources", [])
|
|
|
|
if not classes:
|
|
print("No loyalty classes found.")
|
|
return
|
|
|
|
for cls in classes:
|
|
status = cls.get("reviewStatus", "UNKNOWN")
|
|
class_id = cls.get("id")
|
|
program_name = cls.get("programName", "—")
|
|
issuer_name = cls.get("issuerName", "—")
|
|
color = cls.get("hexBackgroundColor", "—")
|
|
|
|
status_icon = {
|
|
"approved": "✅",
|
|
"draft": "⚠️",
|
|
"rejected": "❌",
|
|
"underReview": "🔄",
|
|
}.get(status, "❓")
|
|
|
|
print(f" {status_icon} {class_id}")
|
|
print(f" Program: {program_name}")
|
|
print(f" Issuer: {issuer_name}")
|
|
print(f" Status: {status}")
|
|
print(f" Color: {color}")
|
|
print()
|
|
|
|
if args.fix_draft and status == "draft":
|
|
print(" Patching to UNDER_REVIEW...")
|
|
patch_resp = http.patch(
|
|
f"https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/{class_id}",
|
|
json={"reviewStatus": "UNDER_REVIEW"},
|
|
)
|
|
if patch_resp.status_code == 200:
|
|
new_status = patch_resp.json().get("reviewStatus", "unknown")
|
|
print(f" ✅ Updated! New status: {new_status}")
|
|
else:
|
|
print(f" ❌ Failed: {patch_resp.status_code} - {patch_resp.text}")
|
|
print()
|
|
|
|
|
|
def _check_class(http, class_id):
|
|
print(f"=== Class: {class_id} ===")
|
|
response = http.get(
|
|
f"https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/{class_id}",
|
|
)
|
|
if response.status_code == 200:
|
|
print(json.dumps(response.json(), indent=2))
|
|
elif response.status_code == 404:
|
|
print("Class not found.")
|
|
else:
|
|
print(f"Error: {response.status_code} - {response.text}")
|
|
|
|
|
|
def _check_object(http, object_id):
|
|
print(f"=== Object: {object_id} ===")
|
|
response = http.get(
|
|
f"https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/{object_id}",
|
|
)
|
|
if response.status_code == 200:
|
|
print(json.dumps(response.json(), indent=2))
|
|
elif response.status_code == 404:
|
|
print("Object not found.")
|
|
else:
|
|
print(f"Error: {response.status_code} - {response.text}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|