Working with JSON Web Tokens (JWT)

JSON Web Tokens are a commonly used industry standard for securely transferring information as a JSON object. When using the Google Wallet API, you encode the details of the Passes Object you want to use to create a pass instance in JWT (pronounced "jot") format, then send that JWT in a request to the Google Wallet API.

JWTs are kept secure by signing them with a shared secret before they are sent to the Google Wallet API. If you are using the Google Wallet REST API, the signing secret is your Google Cloud service account key. If you are using the Google Wallet Android SDK, the signing secret is the SHA-1 fingerprint for your Android app.

Encode a pass in a JWT

When the EventObject is created, wrap it with an unsigned JWT with the payload.EventObjects attribute, as shown in the following snippet:

JSON

 {
  "iss": " OWNER_EMAIL_ADDRESS 
",
  "aud": "google",
  "typ": "savetowallet",
  "iat": " UNIX_TIME 
",
  "origins": [],
  "payload": {
      "eventticketObjects": [ NEW_OBJECT 
]
  }
} 

For more information on the expected format of JWTs, see the JWT reference .

Sign a JWT

JWTs are kept secure by signing them with a shared secret before they are sent to the Google Wallet API. If you are using the Google Wallet REST API, the signing secret is your Google Cloud service account key. If you are using the Google Wallet Android SDK, the signing secret is the SHA-1 fingerprint for your Android app.

Web, email, and SMS

The JWT must be signed using the service account key associated with the Google Cloud service account you authorized in the Google Wallet Business Console . The Google Wallet API will validate these claims by verifying the JWT signature.

Signing the JWT will produce a token that can then be used to create an 'Add to Google Wallet' link that can be used to issue the pass to a user:

Java

To start your integration in Java, refer to our complete code samples on GitHub .

 /** 
 * 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

To start your integration in PHP, refer to our complete code samples on GitHub .

 /** 
 * 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 EventTicketClass([ 
 'id' => "{$issuerId}.{$classSuffix}", 
 'issuerName' => 'Issuer name', 
 'reviewStatus' => 'UNDER_REVIEW', 
 '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 
 $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 TextModuleData([ 
 'header' => 'Text module header', 
 'body' => 'Text module body', 
 'id' => 'TEXT_MODULE_ID 
' ]) 
 ], 
 'linksModuleData' => new LinksModuleData([ 
 'uris' => [ 
 new Uri([ 
 'uri' => 'http://maps.google.com/', 
 'description' => 'Link module URI description', 
 'id' => 'LINK_MODULE_URI_ID 
' ]), 
 new Uri([ 
 'uri' => 'tel:6505555555', 
 'description' => 'Link module tel description', 
 'id' => 'LINK_MODULE_TEL_ID 
' ]) 
 ] 
 ]), 
 'imageModulesData' => [ 
 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 value 
' ]), 
 'locations' => [ 
 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 
' ]); 
 // 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

To start your integration in Python, refer to our complete code samples on GitHub .

 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_6e6 
 a3b6f49_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_3 
 dc3c20606_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#

To start your integration in C#, refer to our complete code samples on GitHub .

 /// <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

To start your integration in Node, refer to our complete code samples on GitHub .

 /** 
 * 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

To start your integration in Go, refer to our complete code samples on GitHub code samples on Github .

 // 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 
 ) 
  
 { 
  
 eventticketObject 
  
 := 
  
 new 
 ( 
 walletobjects 
 . 
 EventTicketObject 
 ) 
  
 eventticketObject 
 . 
 Id 
  
 = 
  
 fmt 
 . 
 Sprintf 
 ( 
" % 
 s 
 . 
 % 
 s 
" , 
  
 issuerId 
 , 
  
 objectSuffix 
 ) 
  
 eventticketObject 
 . 
 ClassId 
  
 = 
  
 fmt 
 . 
 Sprintf 
 ( 
" % 
 s 
 . 
 % 
 s 
" , 
  
 issuerId 
 , 
  
 classSuffix 
 ) 
  
 eventticketObject 
 . 
 TicketHolderName 
  
 = 
  
" Ticket 
  
 holder 
  
 name 
"  
 eventticketObject 
 . 
 TicketNumber 
  
 = 
  
" Ticket 
  
 number 
"  
 eventticketObject 
 . 
 State 
  
 = 
  
" ACTIVE 
"  
 eventticketJson 
 , 
  
 _ 
  
 := 
  
 json 
 . 
 Marshal 
 ( 
 eventticketObject 
 ) 
  
 var 
  
 payload 
  
 map 
 [ 
 string 
 ] 
 any 
  
 json 
 . 
 Unmarshal 
 ([] 
 byte 
 ( 
 fmt 
 . 
 Sprintf 
 ( 
 ` 
 { 
 "eventticketObjects": [%s] 
 } 
 ` 
 , 
  
 eventticketJson 
 )), 
  
& 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) 
 } 

Android apps

When the savePasses method is called to issue a pass to a user, the Google Wallet Android SDK automatically signs your JWT with the SHA-1 fingerprint of your app signing key that you provided in the Google Wallet Business Console . Alternatively, you may also issue the pass using a previously signed JWT using the savePassesJwt method of the Android SDK.

For more information, see Issuing passes with the Android SDK .