Zanim zaczniesz korzystać z Web API, sprawdź, czy spełniasz wymagania wstępne. Aby nadal korzystać z interfejsu Web API, musisz mieć konto usługi i klucz konta usługi oraz przyznać dostęp do swojego konta usługi w celu wywoływania interfejsu Google Wallet API.
Pobierz przykładowy kod z GitHuba, aby uruchomić fragmenty kodu, do których odwołano się w poniższych krokach.
Uwierzytelnianie i autoryzacja
Żądania wysyłane do interfejsu Google Wallet API muszą być uwierzytelnione, aby interfejs Google Wallet API mógł zidentyfikować żądanie wysyłane przez Twoją aplikację. Jest to możliwe dzięki użyciu klucza konta usługi do uzyskania tokena dostępu.
Najpierw wykonaj niezbędne importy bibliotek i zdefiniuj zmienne dla pliku JSON konta usługi oraz identyfikatory wydawcy, klasy, unikalnego użytkownika i obiektu, które zostaną zapisane.
Java
Aby rozpocząć integrację w Javie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.google.api.client.googleapis.batch.BatchRequest; import com.google.api.client.googleapis.batch.json.JsonBatchCallback; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.googleapis.json.GoogleJsonError; import com.google.api.client.googleapis.json.GoogleJsonResponseException; import com.google.api.client.http.*; import com.google.api.client.json.gson.GsonFactory; import com.google.api.services.walletobjects.Walletobjects; import com.google.api.services.walletobjects.model.*; import com.google.auth.http.HttpCredentialsAdapter; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import java.io.*; import java.security.interfaces.RSAPrivateKey; import java.util.*; /** Demo class for creating and managing Event tickets in Google Wallet. */ public class DemoEventTicket { /** * Path to service account key file from Google Cloud Console. Environment variable: * GOOGLE_APPLICATION_CREDENTIALS. */ public static String keyFilePath; /** Service account credentials for Google Wallet APIs. */ public static GoogleCredentials credentials; /** Google Wallet service client. */ public static Walletobjects service; public DemoEventTicket() throws Exception { keyFilePath = System.getenv().getOrDefault("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json"); auth(); }
PHP
Aby rozpocząć integrację w języku PHP, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Client as Google_Client; /** Demo class for creating and managing Event tickets in Google Wallet. */ class DemoEventTicket { /** * Path to service account key file from Google Cloud Console. Environment * variable: GOOGLE_APPLICATION_CREDENTIALS. */ public string $keyFilePath; /** * Service account credentials for Google Wallet APIs. */ public ServiceAccountCredentials $credentials; /** * Google Wallet service client. */ public Google_Service_Walletobjects $service; public function __construct() { $this->keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; $this->auth(); }
Python
Aby rozpocząć integrację w Pythonie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
import json import os import uuid from google.auth.transport.requests import AuthorizedSession from google.oauth2.service_account import Credentials from google.auth import jwt, crypt class DemoEventTicket: """Demo class for creating and managing Event tickets in Google Wallet. Attributes: key_file_path: Path to service account key file from Google Cloud Console. Environment variable: GOOGLE_APPLICATION_CREDENTIALS. base_url: Base URL for Google Wallet API requests. """ def __init__(self): self.key_file_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS', '/path/to/key.json') self.base_url = 'https://walletobjects.googleapis.com/walletobjects/v1' self.batch_url = 'https://walletobjects.googleapis.com/batch' self.class_url = f'{self.base_url}/eventTicketClass' self.object_url = f'{self.base_url}/eventTicketObject' # Set up authenticated client self.auth()
C#
Aby rozpocząć integrację w języku C#, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
using System.IdentityModel.Tokens.Jwt; using System.Net.Http.Headers; using System.Text.RegularExpressions; using Google.Apis.Auth.OAuth2; using Google.Apis.Services; using Google.Apis.Walletobjects.v1; using Google.Apis.Walletobjects.v1.Data; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using Newtonsoft.Json.Linq; /// <summary> /// Demo class for creating and managing Event tickets in Google Wallet. /// </summary> class DemoEventTicket { /// <summary> /// Path to service account key file from Google Cloud Console. Environment /// variable: GOOGLE_APPLICATION_CREDENTIALS. /// </summary> public static string keyFilePath; /// <summary> /// Service account credentials for Google Wallet APIs /// </summary> public static ServiceAccountCredential credentials; /// <summary> /// Google Wallet service client /// </summary> public static WalletobjectsService service; public DemoEventTicket() { keyFilePath = Environment.GetEnvironmentVariable( "GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; Auth(); }
Node.js
Aby rozpocząć integrację w Node, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); const { v4: uuidv4 } = require('uuid'); /** * Demo class for creating and managing Event tickets in Google Wallet. */ class DemoEventTicket { constructor() { /** * Path to service account key file from Google Cloud Console. Environment * variable: GOOGLE_APPLICATION_CREDENTIALS. */ this.keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; this.baseUrl = 'https://walletobjects.googleapis.com/walletobjects/v1'; this.batchUrl = 'https://walletobjects.googleapis.com/batch'; this.classUrl = `${this.baseUrl}/eventTicketClass`; this.objectUrl = `${this.baseUrl}/eventTicketObject`; this.auth(); }
Go
Aby rozpocząć integrację w Go, zapoznaj się z kompletnymi przykładami kodu na GitHubie z przykładowym kodem.
package main import ( "bytes" "encoding/json" "fmt" "github.com/golang-jwt/jwt" "github.com/google/uuid" "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" "io" "net/http" "os" "strings" ) const ( batchUrl = "https://walletobjects.googleapis.com/batch" classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass" objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject" )
Następnie użyj jednej z bibliotek platformy, aby pobrać dane logowania niezbędne do wywołania Google Wallet API.
Java
Aby rozpocząć integrację w Javie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Create authenticated HTTP client using a service account file. * */ public void auth() throws Exception { String scope = "https://www.googleapis.com/auth/wallet_object.issuer"; credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) .createScoped(List.of(scope)); credentials.refresh(); HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); // Initialize Google Wallet API service service = new Walletobjects.Builder( httpTransport, GsonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credentials)) .setApplicationName("APPLICATION_NAME") .build(); }
PHP
Aby rozpocząć integrację w języku PHP, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Create authenticated HTTP client using a service account file. */ public function auth() { $scope = 'https://www.googleapis.com/auth/wallet_object.issuer'; $this->credentials = new ServiceAccountCredentials( $scope, $this->keyFilePath ); // Initialize Google Wallet API service $this->client = new Google_Client(); $this->client->setApplicationName('APPLICATION_NAME'); $this->client->setScopes($scope); $this->client->setAuthConfig($this->keyFilePath); $this->service = new Google_Service_Walletobjects($this->client); }
Python
Aby rozpocząć integrację w Pythonie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
def auth(self): """Create authenticated HTTP client using a service account file.""" self.credentials = Credentials.from_service_account_file( self.key_file_path, scopes=['https://www.googleapis.com/auth/wallet_object.issuer']) self.http_client = AuthorizedSession(self.credentials)
C#
Aby rozpocząć integrację w języku C#, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/// <summary> /// Create authenticated service client using a service account file. /// </summary> public void Auth() { credentials = (ServiceAccountCredential)GoogleCredential .FromFile(keyFilePath) .CreateScoped(new List<string> { "https://www.googleapis.com/auth/wallet_object.issuer" }) .UnderlyingCredential; service = new WalletobjectsService( new BaseClientService.Initializer() { HttpClientInitializer = credentials }); }
Node.js
Aby rozpocząć integrację w Node, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Create authenticated HTTP client using a service account file. */ auth() { this.credentials = require(this.keyFilePath); this.httpClient = new GoogleAuth({ credentials: this.credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' }); }
Go
Aby rozpocząć integrację w Go, zapoznaj się z kompletnymi przykładami kodu na GitHubie z przykładowym kodem.
// Create authenticated HTTP client using a service account file. func (d *demoEventticket) auth() { b, _ := os.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) credentials, _ := google.JWTConfigFromJSON(b, "https://www.googleapis.com/auth/wallet_object.issuer") d.credentials = credentials d.httpClient = d.credentials.Client(oauth2.NoContext) }
Tworzenie obiektu kart
Obiekt kart jest instancją klasy kart. Aby utworzyć obiekt kart, musisz podać te atrybuty:
classId
:id
klasy biletówid
: unikalny identyfikator klienta
Więcej informacji o sposobie przedstawiania tych atrybutów w bilecie znajdziesz w wytycznych dotyczących szablonów.
Przykładowy kod pozwalający utworzyć obiekt kart:
Java
Aby rozpocząć integrację w Javie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Create an object. * * @param issuerId The issuer ID being used for this request. * @param classSuffix Developer-defined unique ID for this pass class. * @param objectSuffix Developer-defined unique ID for this pass object. * @return The pass object ID: "{issuerId}.{objectSuffix}" */ public String createObject(String issuerId, String classSuffix, String objectSuffix) throws IOException { // Check if the object exists try { service.eventticketobject().get(String.format("%s.%s", issuerId, objectSuffix)).execute(); System.out.printf("Object %s.%s already exists!%n", issuerId, objectSuffix); return String.format("%s.%s", issuerId, objectSuffix); } catch (GoogleJsonResponseException ex) { if (ex.getStatusCode() != 404) { // Something else went wrong... ex.printStackTrace(); return String.format("%s.%s", issuerId, objectSuffix); } } // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject EventTicketObject newObject = new EventTicketObject() .setId(String.format("%s.%s", issuerId, objectSuffix)) .setClassId(String.format("%s.%s", issuerId, classSuffix)) .setState("ACTIVE") .setHeroImage( new Image() .setSourceUri( new ImageUri() .setUri( "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Hero image description")))) .setTextModulesData( List.of( new TextModuleData() .setHeader("Text module header") .setBody("Text module body") .setId("TEXT_MODULE_ID"))) .setLinksModuleData( new LinksModuleData() .setUris( Arrays.asList( new Uri() .setUri("http://maps.google.com/") .setDescription("Link module URI description") .setId("LINK_MODULE_URI_ID"), new Uri() .setUri("tel:6505555555") .setDescription("Link module tel description") .setId("LINK_MODULE_TEL_ID")))) .setImageModulesData( List.of( new ImageModuleData() .setMainImage( new Image() .setSourceUri( new ImageUri() .setUri( "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Image module description")))) .setId("IMAGE_MODULE_ID"))) .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value")) .setLocations( List.of( new LatLongPoint() .setLatitude(37.424015499999996) .setLongitude(-122.09259560000001))) .setSeatInfo( new EventSeat() .setSeat( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("42"))) .setRow( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("G3"))) .setSection( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("5"))) .setGate( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("A")))) .setTicketHolderName("Ticket holder name") .setTicketNumber("Ticket number"); EventTicketObject response = service.eventticketobject().insert(newObject).execute(); System.out.println("Object insert response"); System.out.println(response.toPrettyString()); return response.getId(); }
PHP
Aby rozpocząć integrację w języku PHP, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Create an object. * * @param string $issuerId The issuer ID being used for this request. * @param string $classSuffix Developer-defined unique ID for this pass class. * @param string $objectSuffix Developer-defined unique ID for this pass object. * * @return string The pass object ID: "{$issuerId}.{$objectSuffix}" */ public function createObject(string $issuerId, string $classSuffix, string $objectSuffix) { // Check if the object exists try { $this->service->eventticketobject->get("{$issuerId}.{$objectSuffix}"); print("Object {$issuerId}.{$objectSuffix} already exists!"); return "{$issuerId}.{$objectSuffix}"; } catch (Google\Service\Exception $ex) { if (empty($ex->getErrors()) || $ex->getErrors()[0]['reason'] != 'resourceNotFound') { // Something else went wrong... print_r($ex); return "{$issuerId}.{$objectSuffix}"; } } // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject $newObject = new Google_Service_Walletobjects_EventTicketObject([ 'id' => "{$issuerId}.{$objectSuffix}", 'classId' => "{$issuerId}.{$classSuffix}", 'state' => 'ACTIVE', 'heroImage' => new Google_Service_Walletobjects_Image([ 'sourceUri' => new Google_Service_Walletobjects_ImageUri([ 'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' ]), 'contentDescription' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'Hero image description' ]) ]) ]), 'textModulesData' => [ new Google_Service_Walletobjects_TextModuleData([ 'header' => 'Text module header', 'body' => 'Text module body', 'id' => 'TEXT_MODULE_ID' ]) ], 'linksModuleData' => new Google_Service_Walletobjects_LinksModuleData([ 'uris' => [ new Google_Service_Walletobjects_Uri([ 'uri' => 'http://maps.google.com/', 'description' => 'Link module URI description', 'id' => 'LINK_MODULE_URI_ID' ]), new Google_Service_Walletobjects_Uri([ 'uri' => 'tel:6505555555', 'description' => 'Link module tel description', 'id' => 'LINK_MODULE_TEL_ID' ]) ] ]), 'imageModulesData' => [ new Google_Service_Walletobjects_ImageModuleData([ 'mainImage' => new Google_Service_Walletobjects_Image([ 'sourceUri' => new Google_Service_Walletobjects_ImageUri([ 'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' ]), 'contentDescription' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'Image module description' ]) ]) ]), 'id' => 'IMAGE_MODULE_ID' ]) ], 'barcode' => new Google_Service_Walletobjects_Barcode([ 'type' => 'QR_CODE', 'value' => 'QR code value' ]), 'locations' => [ new Google_Service_Walletobjects_LatLongPoint([ 'latitude' => 37.424015499999996, 'longitude' => -122.09259560000001 ]) ], 'seatInfo' => new Google_Service_Walletobjects_EventSeat([ 'seat' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => '42' ]) ]), 'row' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'G3' ]) ]), 'section' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => '5' ]) ]), 'gate' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'A' ]) ]) ]), 'ticketHolderName' => 'Ticket holder name', 'ticketNumber' => 'Ticket number' ]); $response = $this->service->eventticketobject->insert($newObject); print "Object insert response\n"; print_r($response); return $response->id; }
Python
Aby rozpocząć integrację w Pythonie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
def create_object(self, issuer_id: str, class_suffix: str, object_suffix: str) -> str: """Create an object. Args: issuer_id (str): The issuer ID being used for this request. class_suffix (str): Developer-defined unique ID for the pass class. object_suffix (str): Developer-defined unique ID for the pass object. Returns: The pass object ID: f"{issuer_id}.{object_suffix}" """ # Check if the object exists response = self.http_client.get( url=f'{self.object_url}/{issuer_id}.{object_suffix}') if response.status_code == 200: print(f'Object {issuer_id}.{object_suffix} already exists!') print(response.text) return f'{issuer_id}.{object_suffix}' elif response.status_code != 404: # Something else went wrong... print(response.text) return f'{issuer_id}.{object_suffix}' # See link below for more information on required properties # https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject new_object = { 'id': f'{issuer_id}.{object_suffix}', 'classId': f'{issuer_id}.{class_suffix}', 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [{ 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' }], 'linksModuleData': { 'uris': [{ 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' }] }, 'imageModulesData': [{ 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' }], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [{ 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 }], 'seatInfo': { 'seat': { 'defaultValue': { 'language': 'en-US', 'value': '42' } }, 'row': { 'defaultValue': { 'language': 'en-US', 'value': 'G3' } }, 'section': { 'defaultValue': { 'language': 'en-US', 'value': '5' } }, 'gate': { 'defaultValue': { 'language': 'en-US', 'value': 'A' } } }, 'ticketHolderName': 'Ticket holder name', 'ticketNumber': 'Ticket number' } # Create the object response = self.http_client.post(url=self.object_url, json=new_object) print('Object insert response') print(response.text) return response.json().get('id')
C#
Aby rozpocząć integrację w języku C#, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/// <summary> /// Create an object. /// </summary> /// <param name="issuerId">The issuer ID being used for this request.</param> /// <param name="classSuffix">Developer-defined unique ID for this pass class.</param> /// <param name="objectSuffix">Developer-defined unique ID for this pass object.</param> /// <returns>The pass object ID: "{issuerId}.{objectSuffix}"</returns> public string CreateObject(string issuerId, string classSuffix, string objectSuffix) { // Check if the object exists Stream responseStream = service.Eventticketobject .Get($"{issuerId}.{objectSuffix}") .ExecuteAsStream(); StreamReader responseReader = new StreamReader(responseStream); JObject jsonResponse = JObject.Parse(responseReader.ReadToEnd()); if (!jsonResponse.ContainsKey("error")) { Console.WriteLine($"Object {issuerId}.{objectSuffix} already exists!"); return $"{issuerId}.{objectSuffix}"; } else if (jsonResponse["error"].Value<int>("code") != 404) { // Something else went wrong... Console.WriteLine(jsonResponse.ToString()); return $"{issuerId}.{objectSuffix}"; } // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject EventTicketObject newObject = new EventTicketObject { Id = $"{issuerId}.{objectSuffix}", ClassId = $"{issuerId}.{classSuffix}", State = "ACTIVE", HeroImage = new Image { SourceUri = new ImageUri { Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Hero image description" } } }, TextModulesData = new List<TextModuleData> { new TextModuleData { Header = "Text module header", Body = "Text module body", Id = "TEXT_MODULE_ID" } }, LinksModuleData = new LinksModuleData { Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri> { new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "http://maps.google.com/", Description = "Link module URI description", Id = "LINK_MODULE_URI_ID" }, new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "tel:6505555555", Description = "Link module tel description", Id = "LINK_MODULE_TEL_ID" } } }, ImageModulesData = new List<ImageModuleData> { new ImageModuleData { MainImage = new Image { SourceUri = new ImageUri { Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Image module description" } } }, Id = "IMAGE_MODULE_ID" } }, Barcode = new Barcode { Type = "QR_CODE", Value = "QR code" }, Locations = new List<LatLongPoint> { new LatLongPoint { Latitude = 37.424015499999996, Longitude = -122.09259560000001 } }, SeatInfo = new EventSeat { Seat = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "42" } }, Row = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "G3" } }, Section = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "5" } }, Gate = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "A" } } }, TicketHolderName = "Ticket holder name", TicketNumber = "Ticket number" }; responseStream = service.Eventticketobject .Insert(newObject) .ExecuteAsStream(); responseReader = new StreamReader(responseStream); jsonResponse = JObject.Parse(responseReader.ReadToEnd()); Console.WriteLine("Object insert response"); Console.WriteLine(jsonResponse.ToString()); return $"{issuerId}.{objectSuffix}"; }
Node.js
Aby rozpocząć integrację w Node, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Create an object. * * @param {string} issuerId The issuer ID being used for this request. * @param {string} classSuffix Developer-defined unique ID for the pass class. * @param {string} objectSuffix Developer-defined unique ID for the pass object. * * @returns {string} The pass object ID: `${issuerId}.${objectSuffix}` */ async createObject(issuerId, classSuffix, objectSuffix) { let response; // Check if the object exists try { response = await this.httpClient.request({ url: `${this.objectUrl}/${issuerId}.${objectSuffix}`, method: 'GET' }); console.log(`Object ${issuerId}.${objectSuffix} already exists!`); return `${issuerId}.${objectSuffix}`; } catch (err) { if (err.response && err.response.status !== 404) { // Something else went wrong... console.log(err); return `${issuerId}.${objectSuffix}`; } } // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject let newObject = { 'id': `${issuerId}.${objectSuffix}`, 'classId': `${issuerId}.${classSuffix}`, 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [ { 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' } ], 'linksModuleData': { 'uris': [ { 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' } ] }, 'imageModulesData': [ { 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' } ], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [ { 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 } ], 'seatInfo': { 'seat': { 'defaultValue': { 'language': 'en-US', 'value': '42' } }, 'row': { 'defaultValue': { 'language': 'en-US', 'value': 'G3' } }, 'section': { 'defaultValue': { 'language': 'en-US', 'value': '5' } }, 'gate': { 'defaultValue': { 'language': 'en-US', 'value': 'A' } } }, 'ticketHolderName': 'Ticket holder name', 'ticketNumber': 'Ticket number' }; response = await this.httpClient.request({ url: this.objectUrl, method: 'POST', data: newObject }); console.log('Object insert response'); console.log(response); return `${issuerId}.${objectSuffix}`; }
Go
Aby rozpocząć integrację w Go, zapoznaj się z kompletnymi przykładami kodu na GitHubie z przykładowym kodem.
// Create an object. func (d *demoEventticket) createObject(issuerId, classSuffix, objectSuffix string) { newObject := fmt.Sprintf(` { "classId": "%s.%s", "ticketHolderName": "Ticket holder name", "heroImage": { "contentDescription": { "defaultValue": { "value": "Hero image description", "language": "en-US" } }, "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" } }, "barcode": { "type": "QR_CODE", "value": "QR code" }, "locations": [ { "latitude": 37.424015499999996, "longitude": -122.09259560000001 } ], "state": "ACTIVE", "linksModuleData": { "uris": [ { "id": "LINK_MODULE_URI_ID", "uri": "http://maps.google.com/", "description": "Link module URI description" }, { "id": "LINK_MODULE_TEL_ID", "uri": "tel:6505555555", "description": "Link module tel description" } ] }, "ticketNumber": "Ticket number", "imageModulesData": [ { "id": "IMAGE_MODULE_ID", "mainImage": { "contentDescription": { "defaultValue": { "value": "Image module description", "language": "en-US" } }, "sourceUri": { "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg" } } } ], "textModulesData": [ { "body": "Text module body", "header": "Text module header", "id": "TEXT_MODULE_ID" } ], "seatInfo": { "gate": { "defaultValue": { "value": "A", "language": "en-US" } }, "section": { "defaultValue": { "value": "5", "language": "en-US" } }, "row": { "defaultValue": { "value": "G3", "language": "en-US" } }, "seat": { "defaultValue": { "value": "42", "language": "en-US" } } }, "id": "%s.%s" } `, issuerId, classSuffix, issuerId, objectSuffix) res, err := d.httpClient.Post(objectUrl, "application/json", bytes.NewBuffer([]byte(newObject))) if err != nil { fmt.Println(err) } else { b, _ := io.ReadAll(res.Body) fmt.Printf("Object insert response:\n%s\n", b) } }
Gdy to zrobisz, na serwerze zostanie utworzony obiekt kart klienta. Jednak na tym etapie obiekt Karty nie jest połączony z użytkownikiem Google ani jego urządzeniem. Aby karta została powiązana z użytkownikiem Portfela Google, użytkownik musi najpierw dodać ją do Portfela Google.
Dodaję do Portfela Google
Dodanie karty do Portfela Google powoduje połączenie obiektu kart z użytkownikiem Google i może być zainicjowane tylko w kontekście tożsamości zarejestrowanej w Google. Użytkownik może to zrobić, przekierowując użytkownika do adresu URL Dodaj do Portfela Google.
Adres URL Dodaj do Portfela Google to generowany dynamicznie adres URL, który zawiera poniższe informacje o identyfikatorze obiektu karty utworzonym w poprzednim kroku. Te informacje są zakodowane jako token sieciowy JSON (JWT).
Token internetowy JSON (JWT)
Token JWT zawiera zgłoszone przez Ciebie (wydawcy) deklaracje dotyczące obiektu kart, które zostaną zapisane przez użytkownika. Token JWT musi być podpisany za pomocą klucza private_key z klucza konta usługi uzyskanego w kroku tworzenia konta usługi. Google zweryfikuje te deklaracje, weryfikując podpis JWT.
Deklaracje JWT powinny mieć taką strukturę:
{
"aud": "google",
"origins": ["https://example.com"],
"iss": "my-service-account@my-project-id.iam.gserviceaccount.com",
"typ": "savetowallet",
"payload": {
"eventTicketObjects": [
{
"id": "PASSES_OBJECT_ID_1234567890"
}
]
}
}
Utwórz token JWT claims
(krok 1) i uzyskaj token
, podpisując deklaracje kluczem konta usługi private_key
(krok 2):
Java
Aby rozpocząć integrację w Javie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Generate a signed JWT that creates a new pass class and object. * * <p>When the user opens the "Add to Google Wallet" URL and saves the pass to their wallet, the * pass class and object defined in the JWT are created. This allows you to create multiple pass * classes and objects in one API call when the user saves the pass to their wallet. * * @param issuerId The issuer ID being used for this request. * @param classSuffix Developer-defined unique ID for this pass class. * @param objectSuffix Developer-defined unique ID for the pass object. * @return An "Add to Google Wallet" link. */ public String createJWTNewObjects(String issuerId, String classSuffix, String objectSuffix) { // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketclass EventTicketClass newClass = new EventTicketClass() .setId(String.format("%s.%s", issuerId, classSuffix)) .setIssuerName("Issuer name") .setReviewStatus("UNDER_REVIEW") .setEventName( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("Event name"))); // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject EventTicketObject newObject = new EventTicketObject() .setId(String.format("%s.%s", issuerId, objectSuffix)) .setClassId(String.format("%s.%s", issuerId, classSuffix)) .setState("ACTIVE") .setHeroImage( new Image() .setSourceUri( new ImageUri() .setUri( "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Hero image description")))) .setTextModulesData( List.of( new TextModuleData() .setHeader("Text module header") .setBody("Text module body") .setId("TEXT_MODULE_ID"))) .setLinksModuleData( new LinksModuleData() .setUris( Arrays.asList( new Uri() .setUri("http://maps.google.com/") .setDescription("Link module URI description") .setId("LINK_MODULE_URI_ID"), new Uri() .setUri("tel:6505555555") .setDescription("Link module tel description") .setId("LINK_MODULE_TEL_ID")))) .setImageModulesData( List.of( new ImageModuleData() .setMainImage( new Image() .setSourceUri( new ImageUri() .setUri( "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Image module description")))) .setId("IMAGE_MODULE_ID"))) .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value")) .setLocations( List.of( new LatLongPoint() .setLatitude(37.424015499999996) .setLongitude(-122.09259560000001))) .setSeatInfo( new EventSeat() .setSeat( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("42"))) .setRow( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("G3"))) .setSection( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("5"))) .setGate( new LocalizedString() .setDefaultValue( new TranslatedString().setLanguage("en-US").setValue("A")))) .setTicketHolderName("Ticket holder name") .setTicketNumber("Ticket number"); // Create the JWT as a HashMap object HashMap<String, Object> claims = new HashMap<String, Object>(); claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", List.of("www.example.com")); claims.put("typ", "savetowallet"); // Create the Google Wallet payload and add to the JWT HashMap<String, Object> payload = new HashMap<String, Object>(); payload.put("eventTicketClasses", List.of(newClass)); payload.put("eventTicketObjects", List.of(newObject)); claims.put("payload", payload); // The 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); System.out.println("Add to Google Wallet link"); System.out.printf("https://pay.google.com/gp/v/save/%s%n", token); return String.format("https://pay.google.com/gp/v/save/%s", token); }
PHP
Aby rozpocząć integrację w języku PHP, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Generate a signed JWT that creates a new pass class and object. * * When the user opens the "Add to Google Wallet" URL and saves the pass to * their wallet, the pass class and object defined in the JWT are * created. This allows you to create multiple pass classes and objects in * one API call when the user saves the pass to their wallet. * * @param string $issuerId The issuer ID being used for this request. * @param string $classSuffix Developer-defined unique ID for the pass class. * @param string $objectSuffix Developer-defined unique ID for the pass object. * * @return string An "Add to Google Wallet" link. */ public function createJwtNewObjects(string $issuerId, string $classSuffix, string $objectSuffix) { // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketclass $newClass = new Google_Service_Walletobjects_EventTicketClass([ 'id' => "{$issuerId}.{$classSuffix}", 'issuerName' => 'Issuer name', 'reviewStatus' => 'UNDER_REVIEW', 'eventName' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'Event name' ]) ]) ]); // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject $newObject = new Google_Service_Walletobjects_EventTicketObject([ 'id' => "{$issuerId}.{$objectSuffix}", 'classId' => "{$issuerId}.{$classSuffix}", 'state' => 'ACTIVE', 'heroImage' => new Google_Service_Walletobjects_Image([ 'sourceUri' => new Google_Service_Walletobjects_ImageUri([ 'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' ]), 'contentDescription' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'Hero image description' ]) ]) ]), 'textModulesData' => [ new Google_Service_Walletobjects_TextModuleData([ 'header' => 'Text module header', 'body' => 'Text module body', 'id' => 'TEXT_MODULE_ID' ]) ], 'linksModuleData' => new Google_Service_Walletobjects_LinksModuleData([ 'uris' => [ new Google_Service_Walletobjects_Uri([ 'uri' => 'http://maps.google.com/', 'description' => 'Link module URI description', 'id' => 'LINK_MODULE_URI_ID' ]), new Google_Service_Walletobjects_Uri([ 'uri' => 'tel:6505555555', 'description' => 'Link module tel description', 'id' => 'LINK_MODULE_TEL_ID' ]) ] ]), 'imageModulesData' => [ new Google_Service_Walletobjects_ImageModuleData([ 'mainImage' => new Google_Service_Walletobjects_Image([ 'sourceUri' => new Google_Service_Walletobjects_ImageUri([ 'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' ]), 'contentDescription' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'Image module description' ]) ]) ]), 'id' => 'IMAGE_MODULE_ID' ]) ], 'barcode' => new Google_Service_Walletobjects_Barcode([ 'type' => 'QR_CODE', 'value' => 'QR code value' ]), 'locations' => [ new Google_Service_Walletobjects_LatLongPoint([ 'latitude' => 37.424015499999996, 'longitude' => -122.09259560000001 ]) ], 'seatInfo' => new Google_Service_Walletobjects_EventSeat([ 'seat' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => '42' ]) ]), 'row' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'G3' ]) ]), 'section' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => '5' ]) ]), 'gate' => new Google_Service_Walletobjects_LocalizedString([ 'defaultValue' => new Google_Service_Walletobjects_TranslatedString([ 'language' => 'en-US', 'value' => 'A' ]) ]) ]), 'ticketHolderName' => 'Ticket holder name', 'ticketNumber' => 'Ticket number' ]); // The service account credentials are used to sign the JWT $serviceAccount = json_decode(file_get_contents($this->keyFilePath), true); // Create the JWT as an array of key/value pairs $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', 'payload' => [ 'eventTicketClasses' => [ $newClass ], 'eventTicketObjects' => [ $newObject ] ] ]; $token = JWT::encode( $claims, $serviceAccount['private_key'], 'RS256' ); print "Add to Google Wallet link\n"; print "https://pay.google.com/gp/v/save/{$token}"; return "https://pay.google.com/gp/v/save/{$token}"; }
Python
Aby rozpocząć integrację w Pythonie, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
def create_jwt_new_objects(self, issuer_id: str, class_suffix: str, object_suffix: str) -> str: """Generate a signed JWT that creates a new pass class and object. When the user opens the "Add to Google Wallet" URL and saves the pass to their wallet, the pass class and object defined in the JWT are created. This allows you to create multiple pass classes and objects in one API call when the user saves the pass to their wallet. Args: issuer_id (str): The issuer ID being used for this request. class_suffix (str): Developer-defined unique ID for the pass class. object_suffix (str): Developer-defined unique ID for the pass object. Returns: An "Add to Google Wallet" link. """ # See link below for more information on required properties # https://developers.google.com/wallet/tickets/events/rest/v1/eventticketclass new_class = { 'id': f'{issuer_id}.{class_suffix}', 'issuerName': 'Issuer name', 'reviewStatus': 'UNDER_REVIEW', 'eventName': { 'defaultValue': { 'language': 'en-US', 'value': 'Event name' } } } # See link below for more information on required properties # https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject new_object = { 'id': f'{issuer_id}.{object_suffix}', 'classId': f'{issuer_id}.{class_suffix}', 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [{ 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' }], 'linksModuleData': { 'uris': [{ 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' }] }, 'imageModulesData': [{ 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' }], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [{ 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 }], 'seatInfo': { 'seat': { 'defaultValue': { 'language': 'en-US', 'value': '42' } }, 'row': { 'defaultValue': { 'language': 'en-US', 'value': 'G3' } }, 'section': { 'defaultValue': { 'language': 'en-US', 'value': '5' } }, 'gate': { 'defaultValue': { 'language': 'en-US', 'value': 'A' } } }, 'ticketHolderName': 'Ticket holder name', 'ticketNumber': 'Ticket number' } # 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 'eventTicketClasses': [new_class], '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') print('Add to Google Wallet link') print(f'https://pay.google.com/gp/v/save/{token}') return f'https://pay.google.com/gp/v/save/{token}'
C#
Aby rozpocząć integrację w języku C#, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/// <summary> /// Generate a signed JWT that creates a new pass class and object. /// <para /> /// When the user opens the "Add to Google Wallet" URL and saves the pass to /// their wallet, the pass class and object defined in the JWT are created. /// This allows you to create multiple pass classes and objects in one API /// call when the user saves the pass to their wallet. /// <para /> /// The Google Wallet C# library uses Newtonsoft.Json.JsonPropertyAttribute /// to specify the property names when converting objects to JSON. The /// Newtonsoft.Json.JsonConvert.SerializeObject method will automatically /// serialize the object with the right property names. /// </summary> /// <param name="issuerId">The issuer ID being used for this request.</param> /// <param name="classSuffix">Developer-defined unique ID for this pass class.</param> /// <param name="objectSuffix">Developer-defined unique ID for the pass object.</param> /// <returns>An "Add to Google Wallet" link.</returns> public string CreateJWTNewObjects(string issuerId, string classSuffix, string objectSuffix) { // Ignore null values when serializing to/from JSON JsonSerializerSettings excludeNulls = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }; // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketclass EventTicketClass newClass = new EventTicketClass { Id = $"{issuerId}.{classSuffix}", IssuerName = "Issuer name", ReviewStatus = "UNDER_REVIEW", EventId = classSuffix, EventName = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Event name" } } }; // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject EventTicketObject newObject = new EventTicketObject { Id = $"{issuerId}.{objectSuffix}", ClassId = $"{issuerId}.{classSuffix}", State = "ACTIVE", HeroImage = new Image { SourceUri = new ImageUri { Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Hero image description" } } }, TextModulesData = new List<TextModuleData> { new TextModuleData { Header = "Text module header", Body = "Text module body", Id = "TEXT_MODULE_ID" } }, LinksModuleData = new LinksModuleData { Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri> { new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "http://maps.google.com/", Description = "Link module URI description", Id = "LINK_MODULE_URI_ID" }, new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "tel:6505555555", Description = "Link module tel description", Id = "LINK_MODULE_TEL_ID" } } }, ImageModulesData = new List<ImageModuleData> { new ImageModuleData { MainImage = new Image { SourceUri = new ImageUri { Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Image module description" } } }, Id = "IMAGE_MODULE_ID" } }, Barcode = new Barcode { Type = "QR_CODE", Value = "QR code" }, Locations = new List<LatLongPoint> { new LatLongPoint { Latitude = 37.424015499999996, Longitude = -122.09259560000001 } }, SeatInfo = new EventSeat { Seat = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "42" } }, Row = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "G3" } }, Section = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "5" } }, Gate = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "A" } } }, TicketHolderName = "Ticket holder name", TicketNumber = "Ticket number" }; // Create JSON representations of the class and object JObject serializedClass = JObject.Parse( JsonConvert.SerializeObject(newClass, excludeNulls)); JObject serializedObject = JObject.Parse( JsonConvert.SerializeObject(newObject, excludeNulls)); // Create the JWT as a JSON object JObject jwtPayload = JObject.Parse(JsonConvert.SerializeObject(new { iss = credentials.Id, aud = "google", origins = new List<string> { "www.example.com" }, typ = "savetowallet", payload = JObject.Parse(JsonConvert.SerializeObject(new { // The listed classes and objects will be created // when the user saves the pass to their wallet eventTicketClasses = new List<JObject> { serializedClass }, eventTicketObjects = new List<JObject> { serializedObject } })) })); // Deserialize into a JwtPayload JwtPayload claims = JwtPayload.Deserialize(jwtPayload.ToString()); // The service account credentials are used to sign the JWT RsaSecurityKey key = new RsaSecurityKey(credentials.Key); SigningCredentials signingCredentials = new SigningCredentials( key, SecurityAlgorithms.RsaSha256); JwtSecurityToken jwt = new JwtSecurityToken( new JwtHeader(signingCredentials), claims); string token = new JwtSecurityTokenHandler().WriteToken(jwt); Console.WriteLine("Add to Google Wallet link"); Console.WriteLine($"https://pay.google.com/gp/v/save/{token}"); return $"https://pay.google.com/gp/v/save/{token}"; }
Node.js
Aby rozpocząć integrację w Node, zapoznaj się z kompletnymi przykładami kodu w GitHubie.
/** * Generate a signed JWT that creates a new pass class and object. * * When the user opens the "Add to Google Wallet" URL and saves the pass to * their wallet, the pass class and object defined in the JWT are * created. This allows you to create multiple pass classes and objects in * one API call when the user saves the pass to their wallet. * * @param {string} issuerId The issuer ID being used for this request. * @param {string} classSuffix Developer-defined unique ID for the pass class. * @param {string} objectSuffix Developer-defined unique ID for the pass object. * * @returns {string} An "Add to Google Wallet" link. */ createJwtNewObjects(issuerId, classSuffix, objectSuffix) { // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketclass let newClass = { 'id': `${issuerId}.${classSuffix}`, 'issuerName': 'Issuer name', 'reviewStatus': 'UNDER_REVIEW', 'eventName': { 'defaultValue': { 'language': 'en-US', 'value': 'Event name' } } }; // See link below for more information on required properties // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject let newObject = { 'id': `${issuerId}.${objectSuffix}`, 'classId': `${issuerId}.${classSuffix}`, 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [ { 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' } ], 'linksModuleData': { 'uris': [ { 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' } ] }, 'imageModulesData': [ { 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' } ], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [ { 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 } ], 'seatInfo': { 'seat': { 'defaultValue': { 'language': 'en-US', 'value': '42' } }, 'row': { 'defaultValue': { 'language': 'en-US', 'value': 'G3' } }, 'section': { 'defaultValue': { 'language': 'en-US', 'value': '5' } }, 'gate': { 'defaultValue': { 'language': 'en-US', 'value': 'A' } } }, 'ticketHolderName': 'Ticket holder name', 'ticketNumber': 'Ticket number' }; // Create the JWT claims let claims = { iss: this.credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { // The listed classes and objects will be created eventTicketClasses: [newClass], eventTicketObjects: [newObject] } }; // The service account credentials are used to sign the JWT let token = jwt.sign(claims, this.credentials.private_key, { algorithm: 'RS256' }); console.log('Add to Google Wallet link'); console.log(`https://pay.google.com/gp/v/save/${token}`); return `https://pay.google.com/gp/v/save/${token}`; }
Go
Aby rozpocząć integrację w Go, zapoznaj się z kompletnymi przykładami kodu na GitHubie z przykładowym kodem.
// Generate a signed JWT that creates a new pass class and object. // // When the user opens the "Add to Google Wallet" URL and saves the pass to // their wallet, the pass class and object defined in the JWT are // created. This allows you to create multiple pass classes and objects in // one API call when the user saves the pass to their wallet. func (d *demoEventticket) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { newClass := fmt.Sprintf(` { "eventId": "EVENT_ID", "eventName": { "defaultValue": { "value": "Event name", "language": "en-US" } }, "issuerName": "Issuer name", "id": "%s.%s", "reviewStatus": "UNDER_REVIEW" } `, issuerId, classSuffix) newObject := fmt.Sprintf(` { "classId": "%s.%s", "ticketHolderName": "Ticket holder name", "heroImage": { "contentDescription": { "defaultValue": { "value": "Hero image description", "language": "en-US" } }, "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" } }, "barcode": { "type": "QR_CODE", "value": "QR code" }, "locations": [ { "latitude": 37.424015499999996, "longitude": -122.09259560000001 } ], "state": "ACTIVE", "linksModuleData": { "uris": [ { "id": "LINK_MODULE_URI_ID", "uri": "http://maps.google.com/", "description": "Link module URI description" }, { "id": "LINK_MODULE_TEL_ID", "uri": "tel:6505555555", "description": "Link module tel description" } ] }, "ticketNumber": "Ticket number", "imageModulesData": [ { "id": "IMAGE_MODULE_ID", "mainImage": { "contentDescription": { "defaultValue": { "value": "Image module description", "language": "en-US" } }, "sourceUri": { "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg" } } } ], "textModulesData": [ { "body": "Text module body", "header": "Text module header", "id": "TEXT_MODULE_ID" } ], "seatInfo": { "gate": { "defaultValue": { "value": "A", "language": "en-US" } }, "section": { "defaultValue": { "value": "5", "language": "en-US" } }, "row": { "defaultValue": { "value": "G3", "language": "en-US" } }, "seat": { "defaultValue": { "value": "42", "language": "en-US" } } }, "id": "%s.%s" } `, issuerId, classSuffix, issuerId, objectSuffix) var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { "genericClasses": [%s], "genericObjects": [%s] } `, newClass, newObject)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", "origins": []string{"www.example.com"}, "typ": "savetowallet", "payload": payload, } // The service account credentials are used to sign the JWT key, _ := jwt.ParseRSAPrivateKeyFromPEM(d.credentials.PrivateKey) token, _ := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key) fmt.Println("Add to Google Wallet link") fmt.Println("https://pay.google.com/gp/v/save/" + token) }
Po uzyskaniu podpisanego tokena JWT możesz użyć tych informacji do utworzenia linku Dodaj do Portfela Google.
Link do Portfela Google
Link Dodaj do Portfela Google ma taki format:
https://pay.google.com/gp/v/save/{token}
Link ten możesz umieścić na stronie internetowej lub przesłać w wiadomości e-mail jako hiperlink. Można je też wysłać do klienta za pomocą innych kanałów, np. czatu lub SMS-ów.
Bezpieczna długość zakodowanego tokena JWT to 1800 znaków. Jeśli Twój token JWT jest mniejszy niż ten limit, podpisany token JWT może zawierać cały obiekt. Tokeny JWT nie powinny przekraczać tego limitu. Jeśli długość przekroczy 1800 znaków, dodanie karty do Portfela Google może nie zadziałać, ponieważ zostanie przycięty w przeglądarkach.
Przycisk Dodaj do Portfela Google
Aby uzyskać najlepsze wyniki, używaj zasobów przycisku Portfela Google na swojej stronie internetowej, w e-mailu lub w aplikacji na Androida.
Przycisk Portfela Google może być renderowany na dwa sposoby:
- Przycisku internetowego JavaScript można stosować w witrynach.
- Link JWT z przyciskiem może być używany w e-mailach, SMS-ach, aplikacjach i witrynach.
Bilety: [TEST ONLY]
Gdy jesteś w trybie demonstracyjnym, wszystkie utworzone przez Ciebie karty będą miały w tytule dodatkowy tekst „[TEST ONLY]”. Służy to odróżnieniu kart demonstracyjnych od karnetów aktywnych. Gdy nasz zespół zatwierdzi wersję produkcyjną, karnety w trybie demonstracyjnym nie będą już wyświetlać dodatkowego tekstu, gdy użytkownik ponownie otworzy aplikację portfela na połączonym urządzeniu.
Dalsze kroki
- Dostosuj wygląd biletu
- Prześlij proces UX do ostatecznego sprawdzenia, korzystając z formularza kontaktu z zespołem pomocy w Konsoli usług Google Pay i Portfela.
- Przetestuj integrację i opublikuj aplikację