Flusso di sviluppo del pass di Google Wallet

L'API Google Wallet fornisce un insieme predefinito di tipi di tessere ottimizzate per casi d'uso specifici, ad esempio carte regalo, carte d'imbarco, biglietti per eventi e altro ancora. Esiste anche un tipo di tessera generico pensato per i casi d'uso in cui un tipo di tessera specifico non è disponibile.

Lo scopo di questo articolo è acquisire familiarità con i passaggi di base necessari per creare e emettere una tessera utilizzando l'API Google Wallet. Esistono diversi modi per eseguire alcuni dei passaggi descritti di seguito, ma a livello generale tutti i tipi di pass vengono creati seguendo lo stesso flusso di sviluppo di base.

Per una procedura dettagliata dettagliata sulla creazione di una tessera, consulta le guide per web, email e SMS o app per Android.

A cosa serve

Una classe dei pass definisce un insieme di proprietà comuni a più pass, in modo simile a un modello. Ad esempio, se emetti biglietti di un evento, la classe Pass definisce i campi uguali per tutti i biglietti, come il nome, la data e l'ora dell'evento.

Ogni pass che emetti deve fare riferimento a una classe Pass. Devi anche assegnare un ID univoco a ogni classe dei pass che crei, che verrà utilizzato come riferimento durante la creazione delle tessere.

Come si fa

Una classe dei pass è definita in formato JSON e può essere creata con l'API REST di Google Wallet, l'SDK Android o nella Business Console di Google Wallet.

Mostra un esempio di Pass Class

{
  "id": "ISSUER_ID.EVENT_CLASS_ID",
  "issuerName": "[TEST ONLY] Heraldic Event",
  "localizedIssuerName": {
    "defaultValue": {
      "language": "en-US",
      "value": "[TEST ONLY] Heraldic Event"
    }
  },
  "logo": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "LOGO_IMAGE_DESCRIPTION"
      }
    }
  },
  "eventName": {
    "defaultValue": {
      "language": "en-US",
      "value": "Google Live"
    }
  },
  "venue": {
    "name": {
      "defaultValue": {
        "language": "en-US",
        "value": "Shoreline Amphitheater"
      }
    },
    "address": {
      "defaultValue": {
        "language": "en-US",
        "value": "ADDRESS_OF_THE_VENUE"
      }
    }
  },
  "dateTime": {
    "start": "2023-04-12T11:30"
  },
  "reviewStatus": "UNDER_REVIEW",
  "hexBackgroundColor": "#264750",
  "heroImage": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "HERO_IMAGE_DESCRIPTION"
      }
    }
  }
}
    

A cosa serve

Un oggetto Passes definisce le proprietà di un pass univoco che verrà emesso per un utente specifico. Ad esempio, l'oggetto Pass per un biglietto per un evento definirà i campi univoci per un biglietto specifico, come il numero di posto o il codice QR di quel biglietto.

Quando viene creato un oggetto dei pass, l'API Google Wallet archivia un nuovo pass e lo associa al tuo account emittente. Questa tessera memorizzata è una combinazione delle proprietà univoche dell'oggetto Passes e delle proprietà del modello della classe Passes associata.

Devi anche assegnare a ogni oggetto dei pass un ID univoco, che viene utilizzato come riferimento quando emetti una tessera.

Come si fa

Un oggetto Passes è un formato JSON definito e può essere creato con l'API REST Google Wallet o l'SDK Android.

Mostra un esempio di passaggio di un oggetto

{
  "id": "ISSUER_ID.OBJECT_ID",
  "classId": "ISSUER_ID.EVENT_CLASS_ID",
  "state": "ACTIVE",
  "seatInfo": {
    "seat": {
      "defaultValue": {
        "language": "en-us",
        "value": "5"
      }
    },
    "row": {
      "defaultValue": {
        "language": "en-us",
        "value": "G"
      }
    },
    "section": {
      "defaultValue": {
        "language": "en-us",
        "value": "40"
      }
    },
    "gate": {
      "defaultValue": {
        "language": "en-us",
        "value": "3A"
      }
    }
  },
  "barcode": {
    "type": "QR_CODE",
    "value": "BARCODE_VALUE",
    "alternateText": ""
  }
}
    

A cosa serve

Per emettere una tessera per un utente, le classi Passes e gli oggetti Passes devono essere codificati in un token JWT (JSON Web Token). Il formato JWT è uno standard comune e aperto per la rappresentazione delle rivendicazioni tra due parti. Nel caso in cui vengano rilasciate tessere tramite l'API Google Wallet, i JWT vengono utilizzati per inviare una richiesta in cui si afferma che un utente ha il diritto di accedere a una tessera specifica associata all'account dell'emittente.

Quando viene inviato un token JWT all'API Google Wallet, i dati codificati vengono utilizzati per identificare una tessera specifica e rilasciarla all'utente. Se la tessera è già stata rilasciata, questi dati consentono inoltre all'API Google Wallet di identificare che si tratta di un duplicato, in modo che non venga aggiunta più di una volta a Google Wallet dell'utente.

Come si fa

I JWT vengono definiti in formato JSON in base alla specifica JWT. Per definire un JWT per l'emissione di una tessera con l'API Google Wallet, devi fornire le informazioni sulla tessera che vuoi emettere nella proprietà payload del JWT.

Mostra JWT di esempio

{
  "iss": "issuer@example.com",
  "aud": "google",
  "typ": "savetowallet",
  "iat": 1696877738,
  "origins": [
    "www.example.com"
  ],
  "payload": {
    "eventTicketObjects": [
      {
        "id": "ISSUER_ID.LOYALTY_OBJECT_SUFFIX"
      }
    ]
  }
}
    

A cosa serve

Tutti i JWT inviati all'API Google Wallet per emettere una tessera devono essere firmati con le credenziali che hai fornito in precedenza nella Business Console di Google Wallet. La firma utilizza le tue credenziali per criptare il JWT in modo che i pass rimangano protetti e per consentire all'API Google Wallet di autenticare la validità dei dettagli del pass codificati al suo interno e di essere associati al tuo account emittente.

Come si fa

Le librerie client di Google Wallet e l'SDK Android offrono metodi pratici per firmare i JWT. Sono inoltre disponibili numerose librerie open source che gestiscono la complessità della firma del codice tra cui scegliere.

Per coloro che utilizzano l'API REST di Google Wallet per emettere le tessere, il JWT viene firmato con una chiave dell'account di servizio Google Cloud. Per coloro che utilizzano l'SDK Google Wallet per Android, l'SDK gestisce automaticamente la firma del JWT con l'impronta SHA-1 del certificato di firma della tua app.

Per proteggere le tue credenziali, i JWT devono essere firmati solo sul tuo server o utilizzando l'SDK Google Wallet per Android nella tua app.

Mostra esempio di firma del codice

Java

  // Create the JWT as a HashMap object
  HashMap claims = new HashMap();
  claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail());
  claims.put("aud", "google");
  claims.put("origins", Arrays.asList("www.example.com"));
  claims.put("typ", "savetowallet");

  // Create the Google Wallet payload and add to the JWT
  HashMap payload = new HashMap();
  payload.put("eventTicketObjects", Arrays.asList(newObject));
  claims.put("payload", payload);

  // Google Cloud service account credentials are used to sign the JWT
  Algorithm algorithm =
      Algorithm.RSA256(
          null, (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey());
  String token = JWT.create().withPayload(claims).sign(algorithm);
        

Node.JS

  // Create the JWT claims
  let claims = {
    iss: this.credentials.client_email,
    aud: 'google',
    origins: ['www.example.com'],
    typ: 'savetowallet',
    payload: {
      eventTicketObjects: [newObject]
    },
  };

  // The service account credentials are used to sign the JWT
  let token = jwt.sign(claims, this.credentials.private_key, { algorithm: 'RS256' });
        

Python

  # Create the JWT claims
  claims = {
      'iss': self.credentials.service_account_email,
      'aud': 'google',
      'origins': ['www.example.com'],
      'typ': 'savetowallet',
      'payload': {
          # The listed classes and objects will be created
          'eventTicketObjects': [new_object]
      }
  }

  # The service account credentials are used to sign the JWT
  signer = crypt.RSASigner.from_service_account_file(self.key_file_path)
  token = jwt.encode(signer, claims).decode('utf-8')
        

A cosa serve

Dopo aver creato un JWT firmato, puoi emettere il pass per un utente di Google Wallet. A questo scopo, presenta all'utente un pulsante o un link "Aggiungi a Google Wallet". Quando un utente fa clic sul pulsante o sul link ipertestuale, il JWT firmato viene inviato all'API Google Wallet, che poi lo decripta utilizzando le tue credenziali salvate. Una volta autenticata la firma JWT, la tessera verrà inviata all'utente per il salvataggio nel proprio Google Wallet.

Come si fa

Per creare un pulsante "Aggiungi a Google Wallet" per un'app Android, utilizza l'SDK Android di Google Wallet, che fornisce metodi per generare il pulsante. Per tutte le altre piattaforme, inclusi web, email e SMS, crea un link ipertestuale nel formato https://pay.google.com/gp/v/save/<signed_jwt>. Se possibile, è meglio fornire all'utente questo link sotto forma di pulsante "Aggiungi a Google Wallet".

Per ulteriori informazioni sull'utilizzo del pulsante "Aggiungi a Google Wallet", consulta le linee guida per il branding dell'API Google Wallet

Mostra codice di esempio

  https://pay.google.com/gp/v/save/<signed_jwt>
        

SDK Android

  private lateinit var walletClient: PayClient
  private val addToGoogleWalletRequestCode = 1000
  private lateinit var addToGoogleWalletButton: View

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    walletClient = Pay.getClient(this)
    addToGoogleWalletButton.setOnClickListener {
      walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
    }
  }
        

Una volta che l'utente ha salvato la tessera rilasciata, questa verrà visualizzata nell'app Google Wallet insieme a tutti gli altri pass salvati.

Creazione di Passes Objects e Passes Classes nel JWT

Le classi e gli oggetti dei pass possono essere creati in anticipo utilizzando l'API REST di Google Wallet o l'SDK Android. Una volta create, vengono utilizzate per emettere le tessere facendo riferimento al proprio ID.

In alternativa, puoi anche creare Passes Classes e Passes Objects "just in time" incorporando il relativo JSON direttamente nel JWT utilizzato per emettere il pass a un utente. Con questo metodo, le classi dei pass e gli oggetti dei pass vengono creati dall'API Google Wallet quando il JWT firmato viene inviato utilizzando un link o un pulsante "Aggiungi a Google Wallet".

Ad esempio, quanto segue mostra un JWT con una nuova classe Passes e un oggetto Pass definito utilizzando le proprietà payload.eventTicketClasses e payload.eventTicketObjects. Nota che queste proprietà sono array, quindi possono accettare una o più Passes Classes o Passes Objects. Puoi anche specificare un nuovo oggetto Passes nel JWT che fa riferimento a una classe Passes esistente in base al suo ID.

Mostra JWT di esempio

  {
    "iss": "issuer@example.com",
    "aud": "google",
    "typ": "savetowallet",
    "iat": 1696877738,
    "origins": [
      "www.example.com"
    ],
    "payload": {
      "eventTicketClasses": [{
        "id": "ISSUER_ID.EVENT_CLASS_ID",
        "issuerName": "[TEST ONLY] Heraldic Event",
        "localizedIssuerName": {
          "defaultValue": {
            "language": "en-US",
            "value": "[TEST ONLY] Heraldic Event"
          }
        },
        "logo": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "LOGO_IMAGE_DESCRIPTION"
            }
          }
        },
        "eventName": {
          "defaultValue": {
            "language": "en-US",
            "value": "Google Live"
          }
        },
        "venue": {
          "name": {
            "defaultValue": {
              "language": "en-US",
              "value": "Shoreline Amphitheater"
            }
          },
          "address": {
            "defaultValue": {
              "language": "en-US",
              "value": "ADDRESS_OF_THE_VENUE"
            }
          }
        },
        "dateTime": {
          "start": "2023-04-12T11:30"
        },
        "reviewStatus": "UNDER_REVIEW",
        "hexBackgroundColor": "#264750",
        "heroImage": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "HERO_IMAGE_DESCRIPTION"
            }
          }
        }
      }],
      "eventTicketObjects": [{
        "id": "ISSUER_ID.OBJECT_ID",
        "classId": "ISSUER_ID.EVENT_CLASS_ID",
        "state": "ACTIVE",
        "seatInfo": {
          "seat": {
            "defaultValue": {
              "language": "en-us",
              "value": "5"
            }
          },
          "row": {
            "defaultValue": {
              "language": "en-us",
              "value": "G"
            }
          },
          "section": {
            "defaultValue": {
              "language": "en-us",
              "value": "40"
            }
          },
          "gate": {
            "defaultValue": {
              "language": "en-us",
              "value": "3A"
            }
          }
        },
        "barcode": {
          "type": "QR_CODE",
          "value": "BARCODE_VALUE",
          "alternateText": ""
        }
      }]
    }
  }