diff --git a/go/demo_eventticket.go b/go/demo_eventticket.go index ecc31d5..b4d2ed1 100644 --- a/go/demo_eventticket.go +++ b/go/demo_eventticket.go @@ -20,6 +20,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "github.com/golang-jwt/jwt" @@ -27,35 +28,34 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" - "net/http" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" - classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass" - objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject" -) - // [END setup] type demoEventticket struct { - credentials *oauthJwt.Config - httpClient *http.Client - batchUrl, classUrl, objectUrl string + credentials *oauthJwt.Config + service *walletobjects.Service } // [START auth] // 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") + credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + b, _ := os.ReadFile(credentialsFile) + credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) + if err != nil { + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) + } d.credentials = credentials - d.httpClient = d.credentials.Client(oauth2.NoContext) + d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) } // [END auth] @@ -63,28 +63,21 @@ func (d *demoEventticket) auth() { // [START createClass] // Create a class. func (d *demoEventticket) createClass(issuerId, classSuffix string) { - newClass := fmt.Sprintf(` - { - "eventId": "EVENT_ID", - "eventName": { - "defaultValue": { - "value": "Event name", - "language": "en-US" - } + eventticketClass := new(walletobjects.EventTicketClass) + eventticketClass.Id = fmt.Sprintf("%s.%s", issuerId, classSuffix) + eventticketClass.EventName = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Event name", }, - "issuerName": "Issuer name", - "id": "%s.%s", - "reviewStatus": "UNDER_REVIEW" } - `, issuerId, classSuffix) - - res, err := d.httpClient.Post(classUrl, "application/json", bytes.NewBuffer([]byte(newClass))) - + eventticketClass.IssuerName = "Issuer name" + eventticketClass.ReviewStatus = "UNDER_REVIEW" + res, err := d.service.Eventticketclass.Insert(eventticketClass).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert class: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Class insert response:\n%s\n", b) + fmt.Printf("Class insert id:\n%v\n", res.Id) } } @@ -93,107 +86,90 @@ func (d *demoEventticket) createClass(issuerId, classSuffix string) { // [START createObject] // 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" - } + 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" + eventticketObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + }, + } + eventticketObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", + } + eventticketObject.Locations = []*walletobjects.LatLongPoint{ + &walletobjects.LatLongPoint{ + Latitude: 37.424015499999996, + Longitude: -122.09259560000001, + }, + } + eventticketObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", + Description: "Link module URI description", + }, + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", + Description: "Link module tel description", + }, + }, + } + eventticketObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ + Id: "IMAGE_MODULE_ID", + MainImage: &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + }, + }, + }, + } + eventticketObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", + Header: "Text module header", + Id: "TEXT_MODULE_ID", + }, + } + eventticketObject.SeatInfo = &walletobjects.EventSeat{ + Gate: &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "A", + }, + }, + Section: &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "5", + }, + }, + Row: &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "G3", + }, + }, + Seat: &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "42", + }, }, - "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))) + res, err := d.service.Eventticketobject.Insert(eventticketObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object insert response:\n%s\n", b) + fmt.Printf("Object insert id:\n%s\n", res.Id) } } @@ -205,16 +181,14 @@ func (d *demoEventticket) createObject(issuerId, classSuffix, objectSuffix strin // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoEventticket) expireObject(issuerId, objectSuffix string) { - patchBody := `{"state": "EXPIRED"}` - url := fmt.Sprintf("%s/%s.%s", objectUrl, issuerId, objectSuffix) - req, _ := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer([]byte(patchBody))) - res, err := d.httpClient.Do(req) - + eventticketObject := &walletobjects.EventTicketObject{ + State: "EXPIRED", + } + res, err := d.service.Eventticketobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), eventticketObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to patch object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object expiration response:\n%s\n", b) + fmt.Printf("Object expiration id:\n%s\n", res.Id) } } @@ -228,123 +202,20 @@ func (d *demoEventticket) expireObject(issuerId, objectSuffix string) { // 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) + 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" - 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{} + eventticketJson, _ := json.Marshal(eventticketObject) + var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` { - "genericClasses": [%s], - "genericObjects": [%s] + "eventticketObjects": [%s] } - `, newClass, newObject)), &payload) - + `, eventticketJson)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -370,7 +241,7 @@ func (d *demoEventticket) createJwtNewObjects(issuerId, classSuffix, objectSuffi // their wallet, the pass objects defined in the JWT are added to the // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. -func (d *demoEventticket) createJwtExistingObjects(issuerId string) { +func (d *demoEventticket) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { @@ -394,7 +265,7 @@ func (d *demoEventticket) createJwtExistingObjects(issuerId string) { "classId": "%s.GIFT_CARD_CLASS_SUFFIX" }], - "loyaltyObjects": [{ + "eventticketObjects": [{ "id": "%s.LOYALTY_OBJECT_SUFFIX", "classId": "%s.LOYALTY_CLASS_SUFFIX" }], @@ -436,99 +307,15 @@ func (d *demoEventticket) batchCreateObjects(issuerId, classSuffix string) { for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - batchObject := 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) + 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) + batchObject := fmt.Sprintf("%s", eventticketJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" @@ -537,9 +324,7 @@ func (d *demoEventticket) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - - // batchUrl = 'https://walletobjects.googleapis.com/batch'; - res, err := d.httpClient.Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -552,11 +337,6 @@ func (d *demoEventticket) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_eventticket.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) @@ -568,6 +348,6 @@ func main() { d.createObject(issuerId, classSuffix, objectSuffix) d.expireObject(issuerId, objectSuffix) d.createJwtNewObjects(issuerId, classSuffix, objectSuffix) - d.createJwtExistingObjects(issuerId) + d.createJwtExistingObjects(issuerId, classSuffix, objectSuffix) d.batchCreateObjects(issuerId, classSuffix) } diff --git a/go/demo_flight.go b/go/demo_flight.go index d1a45e9..8707d51 100644 --- a/go/demo_flight.go +++ b/go/demo_flight.go @@ -20,6 +20,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "github.com/golang-jwt/jwt" @@ -27,35 +28,34 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" - "net/http" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" - classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightClass" - objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightObject" -) - // [END setup] type demoFlight struct { - credentials *oauthJwt.Config - httpClient *http.Client - batchUrl, classUrl, objectUrl string + credentials *oauthJwt.Config + service *walletobjects.Service } // [START auth] // Create authenticated HTTP client using a service account file. func (d *demoFlight) auth() { - b, _ := os.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) - credentials, _ := google.JWTConfigFromJSON(b, "https://www.googleapis.com/auth/wallet_object.issuer") + credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + b, _ := os.ReadFile(credentialsFile) + credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) + if err != nil { + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) + } d.credentials = credentials - d.httpClient = d.credentials.Client(oauth2.NoContext) + d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) } // [END auth] @@ -63,38 +63,33 @@ func (d *demoFlight) auth() { // [START createClass] // Create a class. func (d *demoFlight) createClass(issuerId, classSuffix string) { - newClass := fmt.Sprintf(` - { - "origin": { - "terminal": "1", - "gate": "A2", - "airportIataCode": "LAX" - }, - "flightHeader": { - "carrier": { - "carrierIataCode": "LX" - }, - "flightNumber": "123" - }, - "localScheduledDepartureDateTime": "2023-07-02T15:30:00", - "reviewStatus": "UNDER_REVIEW", - "issuerName": "Issuer name", - "destination": { - "terminal": "2", - "gate": "C3", - "airportIataCode": "SFO" - }, - "id": "%s.%s" + flightClass := new(walletobjects.FlightClass) + flightClass.Id = fmt.Sprintf("%s.%s", issuerId, classSuffix) + flightClass.ReviewStatus = "UNDER_REVIEW" + flightClass.IssuerName = "Issuer name" + flightClass.Origin = &walletobjects.AirportInfo{ + Terminal: "1", + Gate: "A2", + AirportIataCode: "LAX", } - `, issuerId, classSuffix) - - res, err := d.httpClient.Post(classUrl, "application/json", bytes.NewBuffer([]byte(newClass))) + flightClass.Destination = &walletobjects.AirportInfo{ + Terminal: "2", + Gate: "C3", + AirportIataCode: "SFO", + } + flightClass.FlightHeader = &walletobjects.FlightHeader{ + Carrier: &walletobjects.FlightCarrier{ + CarrierIataCode: "LX", + }, + FlightNumber: "123", + } + flightClass.LocalScheduledDepartureDateTime = "2023-06-12T23:20:50" + res, err := d.service.Flightclass.Insert(flightClass).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert class: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Class insert response:\n%s\n", b) + fmt.Printf("Class insert id:\n%v\n", res.Id) } } @@ -103,87 +98,70 @@ func (d *demoFlight) createClass(issuerId, classSuffix string) { // [START createObject] // Create an object. func (d *demoFlight) createObject(issuerId, classSuffix, objectSuffix string) { - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "passengerName": "Passenger 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 - } - ], - "boardingAndSeatingInfo": { - "boardingGroup": "B", - "seatNumber": "42" - }, - "reservationInfo": { - "confirmationCode": "Confirmation code" - }, - "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" - } - ] - }, - "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" - } - ], - "id": "%s.%s" + flightObject := new(walletobjects.FlightObject) + flightObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + flightObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + flightObject.State = "ACTIVE" + flightObject.PassengerName = "Passenger name" + flightObject.ReservationInfo = &walletobjects.ReservationInfo{ + ConfirmationCode: "Confirmation code", + } + flightObject.BoardingAndSeatingInfo = &walletobjects.BoardingAndSeatingInfo{ + BoardingGroup: "B", + SeatNumber: "42", + } + flightObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + }, + } + flightObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", + } + flightObject.Locations = []*walletobjects.LatLongPoint{ + &walletobjects.LatLongPoint{ + Latitude: 37.424015499999996, + Longitude: -122.09259560000001, + }, + } + flightObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", + Description: "Link module URI description", + }, + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", + Description: "Link module tel description", + }, + }, + } + flightObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ + Id: "IMAGE_MODULE_ID", + MainImage: &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + }, + }, + }, + } + flightObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", + Header: "Text module header", + Id: "TEXT_MODULE_ID", + }, } - `, issuerId, classSuffix, issuerId, objectSuffix) - - res, err := d.httpClient.Post(objectUrl, "application/json", bytes.NewBuffer([]byte(newObject))) + res, err := d.service.Flightobject.Insert(flightObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object insert response:\n%s\n", b) + fmt.Printf("Object insert id:\n%s\n", res.Id) } } @@ -195,16 +173,14 @@ func (d *demoFlight) createObject(issuerId, classSuffix, objectSuffix string) { // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoFlight) expireObject(issuerId, objectSuffix string) { - patchBody := `{"state": "EXPIRED"}` - url := fmt.Sprintf("%s/%s.%s", objectUrl, issuerId, objectSuffix) - req, _ := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer([]byte(patchBody))) - res, err := d.httpClient.Do(req) - + flightObject := &walletobjects.FlightObject{ + State: "EXPIRED", + } + res, err := d.service.Flightobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), flightObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to patch object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object expiration response:\n%s\n", b) + fmt.Printf("Object expiration id:\n%s\n", res.Id) } } @@ -218,113 +194,22 @@ func (d *demoFlight) expireObject(issuerId, objectSuffix string) { // 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 *demoFlight) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { - newClass := fmt.Sprintf(` - { - "origin": { - "terminal": "1", - "gate": "A2", - "airportIataCode": "LAX" - }, - "flightHeader": { - "carrier": { - "carrierIataCode": "LX" - }, - "flightNumber": "123" - }, - "localScheduledDepartureDateTime": "2023-07-02T15:30:00", - "reviewStatus": "UNDER_REVIEW", - "issuerName": "Issuer name", - "destination": { - "terminal": "2", - "gate": "C3", - "airportIataCode": "SFO" - }, - "id": "%s.%s" + flightObject := new(walletobjects.FlightObject) + flightObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + flightObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + flightObject.State = "ACTIVE" + flightObject.PassengerName = "Passenger name" + flightObject.ReservationInfo = &walletobjects.ReservationInfo{ + ConfirmationCode: "Confirmation code", } - `, issuerId, classSuffix) - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "passengerName": "Passenger 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 - } - ], - "boardingAndSeatingInfo": { - "boardingGroup": "B", - "seatNumber": "42" - }, - "reservationInfo": { - "confirmationCode": "Confirmation code" - }, - "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" - } - ] - }, - "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" - } - ], - "id": "%s.%s" - } - `, issuerId, classSuffix, issuerId, objectSuffix) - - var payload map[string]interface{} + flightJson, _ := json.Marshal(flightObject) + var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` { - "genericClasses": [%s], - "genericObjects": [%s] + "flightObjects": [%s] } - `, newClass, newObject)), &payload) - + `, flightJson)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -350,7 +235,7 @@ func (d *demoFlight) createJwtNewObjects(issuerId, classSuffix, objectSuffix str // their wallet, the pass objects defined in the JWT are added to the // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. -func (d *demoFlight) createJwtExistingObjects(issuerId string) { +func (d *demoFlight) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { @@ -379,7 +264,7 @@ func (d *demoFlight) createJwtExistingObjects(issuerId string) { "classId": "%s.LOYALTY_CLASS_SUFFIX" }], - "offerObjects": [{ + "flightObjects": [{ "id": "%s.OFFER_OBJECT_SUFFIX", "classId": "%s.OFFER_CLASS_SUFFIX" }], @@ -416,79 +301,17 @@ func (d *demoFlight) batchCreateObjects(issuerId, classSuffix string) { for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - batchObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "passengerName": "Passenger 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 - } - ], - "boardingAndSeatingInfo": { - "boardingGroup": "B", - "seatNumber": "42" - }, - "reservationInfo": { - "confirmationCode": "Confirmation code" - }, - "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" - } - ] - }, - "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" - } - ], - "id": "%s.%s" + flightObject := new(walletobjects.FlightObject) + flightObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + flightObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + flightObject.State = "ACTIVE" + flightObject.PassengerName = "Passenger name" + flightObject.ReservationInfo = &walletobjects.ReservationInfo{ + ConfirmationCode: "Confirmation code", } - `, issuerId, classSuffix, issuerId, objectSuffix) + + flightJson, _ := json.Marshal(flightObject) + batchObject := fmt.Sprintf("%s", flightJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" @@ -497,8 +320,7 @@ func (d *demoFlight) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - // batchUrl = 'https://walletobjects.googleapis.com/batch'; - res, err := d.httpClient.Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -511,11 +333,6 @@ func (d *demoFlight) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_flight.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) @@ -527,6 +344,6 @@ func main() { d.createObject(issuerId, classSuffix, objectSuffix) d.expireObject(issuerId, objectSuffix) d.createJwtNewObjects(issuerId, classSuffix, objectSuffix) - d.createJwtExistingObjects(issuerId) + d.createJwtExistingObjects(issuerId, classSuffix, objectSuffix) d.batchCreateObjects(issuerId, classSuffix) } diff --git a/go/demo_generic.go b/go/demo_generic.go index 1e69804..5dcfeaf 100644 --- a/go/demo_generic.go +++ b/go/demo_generic.go @@ -20,6 +20,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "github.com/golang-jwt/jwt" @@ -27,35 +28,34 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" - "net/http" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" - classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericClass" - objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericObject" -) - // [END setup] type demoGeneric struct { - credentials *oauthJwt.Config - httpClient *http.Client - batchUrl, classUrl, objectUrl string + credentials *oauthJwt.Config + service *walletobjects.Service } // [START auth] // Create authenticated HTTP client using a service account file. func (d *demoGeneric) auth() { - b, _ := os.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) - credentials, _ := google.JWTConfigFromJSON(b, "https://www.googleapis.com/auth/wallet_object.issuer") + credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + b, _ := os.ReadFile(credentialsFile) + credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) + if err != nil { + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) + } d.credentials = credentials - d.httpClient = d.credentials.Client(oauth2.NoContext) + d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) } // [END auth] @@ -63,19 +63,13 @@ func (d *demoGeneric) auth() { // [START createClass] // Create a class. func (d *demoGeneric) createClass(issuerId, classSuffix string) { - newClass := fmt.Sprintf(` - { - "id": "%s.%s" - } - `, issuerId, classSuffix) - - res, err := d.httpClient.Post(classUrl, "application/json", bytes.NewBuffer([]byte(newClass))) - + genericClass := new(walletobjects.GenericClass) + genericClass.Id = fmt.Sprintf("%s.%s", issuerId, classSuffix) + res, err := d.service.Genericclass.Insert(genericClass).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert class: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Class insert response:\n%s\n", b) + fmt.Printf("Class insert id:\n%v\n", res.Id) } } @@ -84,97 +78,68 @@ func (d *demoGeneric) createClass(issuerId, classSuffix string) { // [START createObject] // Create an object. func (d *demoGeneric) createObject(issuerId, classSuffix, objectSuffix string) { - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "cardTitle": { - "defaultValue": { - "value": "Generic card title", - "language": "en-US" - } - }, - "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" - }, - "header": { - "defaultValue": { - "value": "Generic header", - "language": "en-US" - } - }, - "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" - } - ] - }, - "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" - } - ], - "logo": { - "contentDescription": { - "defaultValue": { - "value": "Generic card logo", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" - } - }, - "hexBackgroundColor": "#4285f4", - "id": "%s.%s" + genericObject := new(walletobjects.GenericObject) + genericObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + genericObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + genericObject.State = "ACTIVE" + genericObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", + } + genericObject.CardTitle = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Card title", + }, + } + genericObject.Header = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Header", + }, + } + genericObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + }, + } + genericObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", + Description: "Link module URI description", + }, + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", + Description: "Link module tel description", + }, + }, + } + genericObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ + Id: "IMAGE_MODULE_ID", + MainImage: &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + }, + }, + }, + } + genericObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", + Header: "Text module header", + Id: "TEXT_MODULE_ID", + }, } - `, issuerId, classSuffix, issuerId, objectSuffix) - - res, err := d.httpClient.Post(objectUrl, "application/json", bytes.NewBuffer([]byte(newObject))) + res, err := d.service.Genericobject.Insert(genericObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object insert response:\n%s\n", b) + fmt.Printf("Object insert id:\n%s\n", res.Id) } } @@ -186,16 +151,14 @@ func (d *demoGeneric) createObject(issuerId, classSuffix, objectSuffix string) { // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoGeneric) expireObject(issuerId, objectSuffix string) { - patchBody := `{"state": "EXPIRED"}` - url := fmt.Sprintf("%s/%s.%s", objectUrl, issuerId, objectSuffix) - req, _ := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer([]byte(patchBody))) - res, err := d.httpClient.Do(req) - + genericObject := &walletobjects.GenericObject{ + State: "EXPIRED", + } + res, err := d.service.Genericobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), genericObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to patch object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object expiration response:\n%s\n", b) + fmt.Printf("Object expiration id:\n%s\n", res.Id) } } @@ -209,104 +172,34 @@ func (d *demoGeneric) expireObject(issuerId, objectSuffix string) { // 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 *demoGeneric) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { - newClass := fmt.Sprintf(` - { - "id": "%s.%s" + genericObject := new(walletobjects.GenericObject) + genericObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + genericObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + genericObject.State = "ACTIVE" + genericObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", } - `, issuerId, classSuffix) - - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "cardTitle": { - "defaultValue": { - "value": "Generic card title", - "language": "en-US" - } + genericObject.CardTitle = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Card title", + }, + } + genericObject.Header = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Header", }, - "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" - }, - "header": { - "defaultValue": { - "value": "Generic header", - "language": "en-US" - } - }, - "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" - } - ] - }, - "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" - } - ], - "logo": { - "contentDescription": { - "defaultValue": { - "value": "Generic card logo", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" - } - }, - "hexBackgroundColor": "#4285f4", - "id": "%s.%s" } - `, issuerId, classSuffix, issuerId, objectSuffix) - var payload map[string]interface{} + genericJson, _ := json.Marshal(genericObject) + var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` { - "genericClasses": [%s], "genericObjects": [%s] } - `, newClass, newObject)), &payload) - + `, genericJson)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -332,7 +225,7 @@ func (d *demoGeneric) createJwtNewObjects(issuerId, classSuffix, objectSuffix st // their wallet, the pass objects defined in the JWT are added to the // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. -func (d *demoGeneric) createJwtExistingObjects(issuerId string) { +func (d *demoGeneric) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { @@ -398,89 +291,29 @@ func (d *demoGeneric) batchCreateObjects(issuerId, classSuffix string) { for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - batchObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "cardTitle": { - "defaultValue": { - "value": "Generic card title", - "language": "en-US" - } - }, - "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" - }, - "header": { - "defaultValue": { - "value": "Generic header", - "language": "en-US" - } - }, - "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" - } - ] - }, - "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" - } - ], - "logo": { - "contentDescription": { - "defaultValue": { - "value": "Generic card logo", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" - } - }, - "hexBackgroundColor": "#4285f4", - "id": "%s.%s" + genericObject := new(walletobjects.GenericObject) + genericObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + genericObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + genericObject.State = "ACTIVE" + genericObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", } - `, issuerId, classSuffix, issuerId, objectSuffix) + genericObject.CardTitle = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Card title", + }, + } + genericObject.Header = &walletobjects.LocalizedString{ + DefaultValue: &walletobjects.TranslatedString{ + Language: "en-us", + Value: "Header", + }, + } + + genericJson, _ := json.Marshal(genericObject) + batchObject := fmt.Sprintf("%s", genericJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" @@ -489,8 +322,7 @@ func (d *demoGeneric) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - // batchUrl = 'https://walletobjects.googleapis.com/batch'; - res, err := d.httpClient.Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -503,11 +335,6 @@ func (d *demoGeneric) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_generic.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) @@ -519,6 +346,6 @@ func main() { d.createObject(issuerId, classSuffix, objectSuffix) d.expireObject(issuerId, objectSuffix) d.createJwtNewObjects(issuerId, classSuffix, objectSuffix) - d.createJwtExistingObjects(issuerId) + d.createJwtExistingObjects(issuerId, classSuffix, objectSuffix) d.batchCreateObjects(issuerId, classSuffix) } diff --git a/go/demo_giftcard.go b/go/demo_giftcard.go index 914a20b..1ad8c82 100644 --- a/go/demo_giftcard.go +++ b/go/demo_giftcard.go @@ -20,6 +20,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "github.com/golang-jwt/jwt" @@ -27,35 +28,34 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" - "net/http" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" - classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass" - objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject" -) - // [END setup] type demoGiftcard struct { - credentials *oauthJwt.Config - httpClient *http.Client - batchUrl, classUrl, objectUrl string + credentials *oauthJwt.Config + service *walletobjects.Service } // [START auth] // Create authenticated HTTP client using a service account file. func (d *demoGiftcard) auth() { - b, _ := os.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) - credentials, _ := google.JWTConfigFromJSON(b, "https://www.googleapis.com/auth/wallet_object.issuer") + credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + b, _ := os.ReadFile(credentialsFile) + credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) + if err != nil { + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) + } d.credentials = credentials - d.httpClient = d.credentials.Client(oauth2.NoContext) + d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) } // [END auth] @@ -63,21 +63,15 @@ func (d *demoGiftcard) auth() { // [START createClass] // Create a class. func (d *demoGiftcard) createClass(issuerId, classSuffix string) { - newClass := fmt.Sprintf(` - { - "issuerName": "Issuer name", - "id": "%s.%s", - "reviewStatus": "UNDER_REVIEW" - } - `, issuerId, classSuffix) - - res, err := d.httpClient.Post(classUrl, "application/json", bytes.NewBuffer([]byte(newClass))) - + giftcardClass := new(walletobjects.GiftCardClass) + giftcardClass.Id = fmt.Sprintf("%s.%s", issuerId, classSuffix) + giftcardClass.IssuerName = "Issuer name" + giftcardClass.ReviewStatus = "UNDER_REVIEW" + res, err := d.service.Giftcardclass.Insert(giftcardClass).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert class: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Class insert response:\n%s\n", b) + fmt.Printf("Class insert id:\n%v\n", res.Id) } } @@ -86,88 +80,71 @@ func (d *demoGiftcard) createClass(issuerId, classSuffix string) { // [START createObject] // Create an object. func (d *demoGiftcard) createObject(issuerId, classSuffix, objectSuffix string) { - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "pin": "1234", - "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 - } - ], - "balanceUpdateTime": { - "date": "2020-04-12T16:20:50.52-04:00" - }, - "state": "ACTIVE", - "cardNumber": "Card number", - "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" - } - ] - }, - "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" - } - ], - "balance": { - "micros": 20000000, - "currencyCode": "USD" - }, - "id": "%s.%s" + giftcardObject := new(walletobjects.GiftCardObject) + giftcardObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + giftcardObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + giftcardObject.State = "ACTIVE" + giftcardObject.CardNumber = "Card number" + giftcardObject.Pin = "1234" + giftcardObject.Balance = &walletobjects.Money{ + Micros: 20000000, + CurrencyCode: "USD", + } + giftcardObject.BalanceUpdateTime = &walletobjects.DateTime{ + Date: "2023-12-12T23:20:50.52Z", + } + giftcardObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + }, + } + giftcardObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", + } + giftcardObject.Locations = []*walletobjects.LatLongPoint{ + &walletobjects.LatLongPoint{ + Latitude: 37.424015499999996, + Longitude: -122.09259560000001, + }, + } + giftcardObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", + Description: "Link module URI description", + }, + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", + Description: "Link module tel description", + }, + }, + } + giftcardObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ + Id: "IMAGE_MODULE_ID", + MainImage: &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + }, + }, + }, + } + giftcardObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", + Header: "Text module header", + Id: "TEXT_MODULE_ID", + }, } - `, issuerId, classSuffix, issuerId, objectSuffix) - - res, err := d.httpClient.Post(objectUrl, "application/json", bytes.NewBuffer([]byte(newObject))) + res, err := d.service.Giftcardobject.Insert(giftcardObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object insert response:\n%s\n", b) + fmt.Printf("Object insert id:\n%s\n", res.Id) } } @@ -179,16 +156,14 @@ func (d *demoGiftcard) createObject(issuerId, classSuffix, objectSuffix string) // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoGiftcard) expireObject(issuerId, objectSuffix string) { - patchBody := `{"state": "EXPIRED"}` - url := fmt.Sprintf("%s/%s.%s", objectUrl, issuerId, objectSuffix) - req, _ := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer([]byte(patchBody))) - res, err := d.httpClient.Do(req) - + giftcardObject := &walletobjects.GiftCardObject{ + State: "EXPIRED", + } + res, err := d.service.Giftcardobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), giftcardObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to patch object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object expiration response:\n%s\n", b) + fmt.Printf("Object expiration id:\n%s\n", res.Id) } } @@ -202,97 +177,19 @@ func (d *demoGiftcard) expireObject(issuerId, objectSuffix string) { // 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 *demoGiftcard) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { - newClass := fmt.Sprintf(` - { - "issuerName": "Issuer name", - "id": "%s.%s", - "reviewStatus": "UNDER_REVIEW" - } - `, issuerId, classSuffix) + giftcardObject := new(walletobjects.GiftCardObject) + giftcardObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + giftcardObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + giftcardObject.State = "ACTIVE" + giftcardObject.CardNumber = "Card number" - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "pin": "1234", - "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 - } - ], - "balanceUpdateTime": { - "date": "2020-04-12T16:20:50.52-04:00" - }, - "state": "ACTIVE", - "cardNumber": "Card number", - "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" - } - ] - }, - "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" - } - ], - "balance": { - "micros": 20000000, - "currencyCode": "USD" - }, - "id": "%s.%s" - } - `, issuerId, classSuffix, issuerId, objectSuffix) - - var payload map[string]interface{} + giftcardJson, _ := json.Marshal(giftcardObject) + var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` { - "genericClasses": [%s], - "genericObjects": [%s] + "giftcardObjects": [%s] } - `, newClass, newObject)), &payload) - + `, giftcardJson)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -318,7 +215,7 @@ func (d *demoGiftcard) createJwtNewObjects(issuerId, classSuffix, objectSuffix s // their wallet, the pass objects defined in the JWT are added to the // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. -func (d *demoGiftcard) createJwtExistingObjects(issuerId string) { +func (d *demoGiftcard) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { @@ -347,7 +244,7 @@ func (d *demoGiftcard) createJwtExistingObjects(issuerId string) { "classId": "%s.LOYALTY_CLASS_SUFFIX" }], - "offerObjects": [{ + "giftcardObjects": [{ "id": "%s.OFFER_OBJECT_SUFFIX", "classId": "%s.OFFER_CLASS_SUFFIX" }], @@ -384,80 +281,14 @@ func (d *demoGiftcard) batchCreateObjects(issuerId, classSuffix string) { for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - batchObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "pin": "1234", - "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 - } - ], - "balanceUpdateTime": { - "date": "2020-04-12T16:20:50.52-04:00" - }, - "state": "ACTIVE", - "cardNumber": "Card number", - "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" - } - ] - }, - "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" - } - ], - "balance": { - "micros": 20000000, - "currencyCode": "USD" - }, - "id": "%s.%s" - } - `, issuerId, classSuffix, issuerId, objectSuffix) + giftcardObject := new(walletobjects.GiftCardObject) + giftcardObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + giftcardObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + giftcardObject.State = "ACTIVE" + giftcardObject.CardNumber = "Card number" + + giftcardJson, _ := json.Marshal(giftcardObject) + batchObject := fmt.Sprintf("%s", giftcardJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" @@ -466,8 +297,7 @@ func (d *demoGiftcard) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - // batchUrl = 'https://walletobjects.googleapis.com/batch'; - res, err := d.httpClient.Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -480,11 +310,6 @@ func (d *demoGiftcard) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_giftcard.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) @@ -496,6 +321,6 @@ func main() { d.createObject(issuerId, classSuffix, objectSuffix) d.expireObject(issuerId, objectSuffix) d.createJwtNewObjects(issuerId, classSuffix, objectSuffix) - d.createJwtExistingObjects(issuerId) + d.createJwtExistingObjects(issuerId, classSuffix, objectSuffix) d.batchCreateObjects(issuerId, classSuffix) } diff --git a/go/demo_loyalty.go b/go/demo_loyalty.go index 14e7d3a..c1f6310 100644 --- a/go/demo_loyalty.go +++ b/go/demo_loyalty.go @@ -20,35 +20,28 @@ package main import ( "bytes" - "context" + "context" "encoding/json" "fmt" - "log" - "github.com/golang-jwt/jwt" "github.com/google/uuid" "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" - "google.golang.org/api/option" - "google.golang.org/api/walletobjects/v1" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" -) - // [END setup] type demoLoyalty struct { credentials *oauthJwt.Config - service *walletobjects.Service - batchUrl string + service *walletobjects.Service } // [START auth] @@ -58,7 +51,8 @@ func (d *demoLoyalty) auth() { b, _ := os.ReadFile(credentialsFile) credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) if err != nil { - log.Fatalf("Unable to create credentials: %v", err) + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) } d.credentials = credentials d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) @@ -69,8 +63,8 @@ func (d *demoLoyalty) auth() { // [START createClass] // Create a class. func (d *demoLoyalty) createClass(issuerId, classSuffix string) { - logo := walletobjects.Image { - SourceUri: &walletobjects.ImageUri { + logo := walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ Uri: "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg", }, } @@ -90,73 +84,66 @@ func (d *demoLoyalty) createClass(issuerId, classSuffix string) { // [END createClass] -// [START setupObject] -// Build a full loyaltyObject. -func (d *demoLoyalty) setupObject(issuerId, classSuffix, objectSuffix string) *walletobjects.LoyaltyObject { +// [START createObject] +// Create an object. +func (d *demoLoyalty) createObject(issuerId, classSuffix, objectSuffix string) { loyaltyObject := new(walletobjects.LoyaltyObject) loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) loyaltyObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) loyaltyObject.AccountName = "Account name" loyaltyObject.AccountId = "Account id" loyaltyObject.State = "ACTIVE" - loyaltyObject.LoyaltyPoints = &walletobjects.LoyaltyPoints { - Balance: &walletobjects.LoyaltyPointsBalance { Int: 800 }, - Label: "Points", + loyaltyObject.LoyaltyPoints = &walletobjects.LoyaltyPoints{ + Balance: &walletobjects.LoyaltyPointsBalance{Int: 800}, + Label: "Points", } - loyaltyObject.HeroImage = &walletobjects.Image { - SourceUri: &walletobjects.ImageUri { + loyaltyObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", }, } - loyaltyObject.Barcode = &walletobjects.Barcode { - Type: "QR_CODE", + loyaltyObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", Value: "QR code", } - loyaltyObject.Locations = []*walletobjects.LatLongPoint { - &walletobjects.LatLongPoint { - Latitude: 37.424015499999996, + loyaltyObject.Locations = []*walletobjects.LatLongPoint{ + &walletobjects.LatLongPoint{ + Latitude: 37.424015499999996, Longitude: -122.09259560000001, }, } - loyaltyObject.LinksModuleData = &walletobjects.LinksModuleData { - Uris: []*walletobjects.Uri { - &walletobjects.Uri { - Id: "LINK_MODULE_URI_ID", - Uri: "http://maps.google.com/", + loyaltyObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", Description: "Link module URI description", }, - &walletobjects.Uri { - Id: "LINK_MODULE_TEL_ID", - Uri: "tel:6505555555", + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", Description: "Link module tel description", }, }, } - loyaltyObject.ImageModulesData = []*walletobjects.ImageModuleData { - &walletobjects.ImageModuleData { + loyaltyObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ Id: "IMAGE_MODULE_ID", - MainImage: &walletobjects.Image { + MainImage: &walletobjects.Image{ SourceUri: &walletobjects.ImageUri{ Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", }, }, }, } - loyaltyObject.TextModulesData = []*walletobjects.TextModuleData { - &walletobjects.TextModuleData { - Body: "Text module body", + loyaltyObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", Header: "Text module header", - Id: "TEXT_MODULE_ID", + Id: "TEXT_MODULE_ID", }, } - return loyaltyObject -} -// [END setupObject] -// [START createObject] -// Create an object. -func (d *demoLoyalty) createObject(issuerId, classSuffix, objectSuffix string) { - loyaltyObject := d.setupObject(issuerId, classSuffix, objectSuffix) res, err := d.service.Loyaltyobject.Insert(loyaltyObject).Do() if err != nil { log.Fatalf("Unable to insert object: %v", err) @@ -173,7 +160,7 @@ func (d *demoLoyalty) createObject(issuerId, classSuffix, objectSuffix string) { // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoLoyalty) expireObject(issuerId, objectSuffix string) { - loyaltyObject := &walletobjects.LoyaltyObject { + loyaltyObject := &walletobjects.LoyaltyObject{ State: "EXPIRED", } res, err := d.service.Loyaltyobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), loyaltyObject).Do() @@ -195,11 +182,12 @@ func (d *demoLoyalty) expireObject(issuerId, objectSuffix string) { // one API call when the user saves the pass to their wallet. func (d *demoLoyalty) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { loyaltyObject := new(walletobjects.LoyaltyObject) - loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix + "_") + loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix+"_") loyaltyObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) loyaltyObject.AccountName = "Account name" loyaltyObject.AccountId = "Account id" loyaltyObject.State = "ACTIVE" + loyaltyJson, _ := json.Marshal(loyaltyObject) var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` @@ -233,16 +221,46 @@ func (d *demoLoyalty) createJwtNewObjects(issuerId, classSuffix, objectSuffix st // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. func (d *demoLoyalty) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { - loyaltyObject := new(walletobjects.LoyaltyObject) - loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) - loyaltyObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) - loyaltyJson, _ := json.Marshal(loyaltyObject) - var payload map[string]any + var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { - "loyaltyObjects":[%s] + "eventTicketObjects": [{ + "id": "%s.EVENT_OBJECT_SUFFIX", + "classId": "%s.EVENT_CLASS_SUFFIX" + }], + + "flightObjects": [{ + "id": "%s.FLIGHT_OBJECT_SUFFIX", + "classId": "%s.FLIGHT_CLASS_SUFFIX" + }], + + "genericObjects": [{ + "id": "%s.GENERIC_OBJECT_SUFFIX", + "classId": "%s.GENERIC_CLASS_SUFFIX" + }], + + "giftCardObjects": [{ + "id": "%s.GIFT_CARD_OBJECT_SUFFIX", + "classId": "%s.GIFT_CARD_CLASS_SUFFIX" + }], + + "loyaltyObjects": [{ + "id": "%s.LOYALTY_OBJECT_SUFFIX", + "classId": "%s.LOYALTY_CLASS_SUFFIX" + }], + + "offerObjects": [{ + "id": "%s.OFFER_OBJECT_SUFFIX", + "classId": "%s.OFFER_CLASS_SUFFIX" + }], + + "transitObjects": [{ + "id": "%s.TRANSIT_OBJECT_SUFFIX", + "classId": "%s.TRANSIT_CLASS_SUFFIX" + }] } - `, loyaltyJson )), &payload) + `, issuerId)), &payload) + claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -255,7 +273,7 @@ func (d *demoLoyalty) createJwtExistingObjects(issuerId string, classSuffix stri key, _ := jwt.ParseRSAPrivateKeyFromPEM(d.credentials.PrivateKey) token, _ := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key) - fmt.Println("Add to Google Wallet link for existing objects") + fmt.Println("Add to Google Wallet link") fmt.Println("https://pay.google.com/gp/v/save/" + token) } @@ -267,9 +285,15 @@ func (d *demoLoyalty) batchCreateObjects(issuerId, classSuffix string) { data := "" for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - loyaltyObject := d.setupObject(issuerId, classSuffix, objectSuffix) + + loyaltyObject := new(walletobjects.LoyaltyObject) + loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + loyaltyObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + loyaltyObject.AccountName = "Account name" + loyaltyObject.AccountId = "Account id" + loyaltyObject.State = "ACTIVE" + loyaltyJson, _ := json.Marshal(loyaltyObject) - batchObject := fmt.Sprintf("%s", loyaltyJson) data += "--batch_createobjectbatch\n" @@ -279,7 +303,7 @@ func (d *demoLoyalty) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - res, err := d.credentials.Client(oauth2.NoContext).Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -292,11 +316,6 @@ func (d *demoLoyalty) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_loyalty.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) diff --git a/go/demo_offer.go b/go/demo_offer.go index dc4bf05..29355bc 100644 --- a/go/demo_offer.go +++ b/go/demo_offer.go @@ -20,6 +20,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "github.com/golang-jwt/jwt" @@ -27,35 +28,34 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" - "net/http" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" - classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerClass" - objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerObject" -) - // [END setup] type demoOffer struct { - credentials *oauthJwt.Config - httpClient *http.Client - batchUrl, classUrl, objectUrl string + credentials *oauthJwt.Config + service *walletobjects.Service } // [START auth] // Create authenticated HTTP client using a service account file. func (d *demoOffer) auth() { - b, _ := os.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) - credentials, _ := google.JWTConfigFromJSON(b, "https://www.googleapis.com/auth/wallet_object.issuer") + credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + b, _ := os.ReadFile(credentialsFile) + credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) + if err != nil { + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) + } d.credentials = credentials - d.httpClient = d.credentials.Client(oauth2.NoContext) + d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) } // [END auth] @@ -63,24 +63,18 @@ func (d *demoOffer) auth() { // [START createClass] // Create a class. func (d *demoOffer) createClass(issuerId, classSuffix string) { - newClass := fmt.Sprintf(` - { - "redemptionChannel": "ONLINE", - "reviewStatus": "UNDER_REVIEW", - "title": "Offer title", - "issuerName": "Issuer name", - "provider": "Provider name", - "id": "%s.%s" - } - `, issuerId, classSuffix) - - res, err := d.httpClient.Post(classUrl, "application/json", bytes.NewBuffer([]byte(newClass))) - + offerClass := new(walletobjects.OfferClass) + offerClass.Id = fmt.Sprintf("%s.%s", issuerId, classSuffix) + offerClass.RedemptionChannel = "ONLINE" + offerClass.ReviewStatus = "UNDER_REVIEW" + offerClass.Title = "Offer title" + offerClass.IssuerName = "Issuer name" + offerClass.Provider = "Provider name" + res, err := d.service.Offerclass.Insert(offerClass).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert class: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Class insert response:\n%s\n", b) + fmt.Printf("Class insert id:\n%v\n", res.Id) } } @@ -89,87 +83,70 @@ func (d *demoOffer) createClass(issuerId, classSuffix string) { // [START createObject] // Create an object. func (d *demoOffer) createObject(issuerId, classSuffix, objectSuffix string) { - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "heroImage": { - "contentDescription": { - "defaultValue": { - "value": "Hero image description", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" - } + offerObject := new(walletobjects.OfferObject) + offerObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + offerObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + offerObject.State = "ACTIVE" + offerObject.ValidTimeInterval = &walletobjects.TimeInterval{ + Start: &walletobjects.DateTime{ + Date: "2023-06-12T23:20:50.52Z", }, - "barcode": { - "type": "QR_CODE", - "value": "QR code" + End: &walletobjects.DateTime{ + Date: "2023-12-12T23:20:50.52Z", + }, + } + offerObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + }, + } + offerObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", + } + offerObject.Locations = []*walletobjects.LatLongPoint{ + &walletobjects.LatLongPoint{ + Latitude: 37.424015499999996, + Longitude: -122.09259560000001, + }, + } + offerObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", + Description: "Link module URI description", + }, + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", + Description: "Link module tel description", + }, + }, + } + offerObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ + Id: "IMAGE_MODULE_ID", + MainImage: &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + }, + }, + }, + } + offerObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", + Header: "Text module header", + Id: "TEXT_MODULE_ID", }, - "locations": [ - { - "latitude": 37.424015499999996, - "longitude": -122.09259560000001 - } - ], - "validTimeInterval": { - "start": { - "date": "2023-06-12T23:20:50.52Z" - }, - "end": { - "date": "2023-12-12T23:20:50.52Z" - } - }, - "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" - } - ] - }, - "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" - } - ], - "id": "%s.%s" } - `, issuerId, classSuffix, issuerId, objectSuffix) - - res, err := d.httpClient.Post(objectUrl, "application/json", bytes.NewBuffer([]byte(newObject))) + res, err := d.service.Offerobject.Insert(offerObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object insert response:\n%s\n", b) + fmt.Printf("Object insert id:\n%s\n", res.Id) } } @@ -181,16 +158,14 @@ func (d *demoOffer) createObject(issuerId, classSuffix, objectSuffix string) { // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoOffer) expireObject(issuerId, objectSuffix string) { - patchBody := `{"state": "EXPIRED"}` - url := fmt.Sprintf("%s/%s.%s", objectUrl, issuerId, objectSuffix) - req, _ := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer([]byte(patchBody))) - res, err := d.httpClient.Do(req) - + offerObject := &walletobjects.OfferObject{ + State: "EXPIRED", + } + res, err := d.service.Offerobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), offerObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to patch object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object expiration response:\n%s\n", b) + fmt.Printf("Object expiration id:\n%s\n", res.Id) } } @@ -204,99 +179,18 @@ func (d *demoOffer) expireObject(issuerId, objectSuffix string) { // 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 *demoOffer) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { - newClass := fmt.Sprintf(` - { - "redemptionChannel": "ONLINE", - "reviewStatus": "UNDER_REVIEW", - "title": "Offer title", - "issuerName": "Issuer name", - "provider": "Provider name", - "id": "%s.%s" - } - `, issuerId, classSuffix) + offerObject := new(walletobjects.OfferObject) + offerObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + offerObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + offerObject.State = "ACTIVE" - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "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 - } - ], - "validTimeInterval": { - "start": { - "date": "2023-06-12T23:20:50.52Z" - }, - "end": { - "date": "2023-12-12T23:20:50.52Z" - } - }, - "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" - } - ] - }, - "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" - } - ], - "id": "%s.%s" - } - `, issuerId, classSuffix, issuerId, objectSuffix) - - var payload map[string]interface{} + offerJson, _ := json.Marshal(offerObject) + var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` { - "genericClasses": [%s], - "genericObjects": [%s] + "offerObjects": [%s] } - `, newClass, newObject)), &payload) - + `, offerJson)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -322,7 +216,7 @@ func (d *demoOffer) createJwtNewObjects(issuerId, classSuffix, objectSuffix stri // their wallet, the pass objects defined in the JWT are added to the // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. -func (d *demoOffer) createJwtExistingObjects(issuerId string) { +func (d *demoOffer) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { @@ -388,79 +282,13 @@ func (d *demoOffer) batchCreateObjects(issuerId, classSuffix string) { for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - batchObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "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 - } - ], - "validTimeInterval": { - "start": { - "date": "2023-06-12T23:20:50.52Z" - }, - "end": { - "date": "2023-12-12T23:20:50.52Z" - } - }, - "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" - } - ] - }, - "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" - } - ], - "id": "%s.%s" - } - `, issuerId, classSuffix, issuerId, objectSuffix) + offerObject := new(walletobjects.OfferObject) + offerObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + offerObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + offerObject.State = "ACTIVE" + + offerJson, _ := json.Marshal(offerObject) + batchObject := fmt.Sprintf("%s", offerJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" @@ -469,8 +297,7 @@ func (d *demoOffer) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - // batchUrl = 'https://walletobjects.googleapis.com/batch'; - res, err := d.httpClient.Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -483,11 +310,6 @@ func (d *demoOffer) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_offer.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) @@ -499,6 +321,6 @@ func main() { d.createObject(issuerId, classSuffix, objectSuffix) d.expireObject(issuerId, objectSuffix) d.createJwtNewObjects(issuerId, classSuffix, objectSuffix) - d.createJwtExistingObjects(issuerId) + d.createJwtExistingObjects(issuerId, classSuffix, objectSuffix) d.batchCreateObjects(issuerId, classSuffix) } diff --git a/go/demo_transit.go b/go/demo_transit.go index 6c5a83a..0bf690a 100644 --- a/go/demo_transit.go +++ b/go/demo_transit.go @@ -20,6 +20,7 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "github.com/golang-jwt/jwt" @@ -27,35 +28,34 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" oauthJwt "golang.org/x/oauth2/jwt" + "google.golang.org/api/option" + "google.golang.org/api/walletobjects/v1" "io" - "net/http" + "log" "os" "strings" ) // [END imports] - -const ( - batchUrl = "https://walletobjects.googleapis.com/batch" - classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitClass" - objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitObject" -) - // [END setup] type demoTransit struct { - credentials *oauthJwt.Config - httpClient *http.Client - batchUrl, classUrl, objectUrl string + credentials *oauthJwt.Config + service *walletobjects.Service } // [START auth] // Create authenticated HTTP client using a service account file. func (d *demoTransit) auth() { - b, _ := os.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) - credentials, _ := google.JWTConfigFromJSON(b, "https://www.googleapis.com/auth/wallet_object.issuer") + credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") + b, _ := os.ReadFile(credentialsFile) + credentials, err := google.JWTConfigFromJSON(b, walletobjects.WalletObjectIssuerScope) + if err != nil { + fmt.Println(err) + log.Fatalf("Unable to load credentials: %v", err) + } d.credentials = credentials - d.httpClient = d.credentials.Client(oauth2.NoContext) + d.service, _ = walletobjects.NewService(context.Background(), option.WithCredentialsFile(credentialsFile)) } // [END auth] @@ -63,33 +63,22 @@ func (d *demoTransit) auth() { // [START createClass] // Create a class. func (d *demoTransit) createClass(issuerId, classSuffix string) { - newClass := fmt.Sprintf(` - { - "logo": { - "contentDescription": { - "defaultValue": { - "value": "Logo description", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://live.staticflickr.com/65535/48690277162_cd05f03f4d_o.png" - } + logo := walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg", }, - "issuerName": "Issuer name", - "reviewStatus": "UNDER_REVIEW", - "id": "%s.%s", - "transitType": "BUS" } - `, issuerId, classSuffix) - - res, err := d.httpClient.Post(classUrl, "application/json", bytes.NewBuffer([]byte(newClass))) - + transitClass := new(walletobjects.TransitClass) + transitClass.Id = fmt.Sprintf("%s.%s", issuerId, classSuffix) + transitClass.IssuerName = "Issuer name" + transitClass.ReviewStatus = "UNDER_REVIEW" + transitClass.Logo = &logo + transitClass.TransitType = "BUS" + res, err := d.service.Transitclass.Insert(transitClass).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert class: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Class insert response:\n%s\n", b) + fmt.Printf("Class insert id:\n%v\n", res.Id) } } @@ -98,106 +87,68 @@ func (d *demoTransit) createClass(issuerId, classSuffix string) { // [START createObject] // Create an object. func (d *demoTransit) createObject(issuerId, classSuffix, objectSuffix string) { - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "passengerNames": "Passenger names", - "heroImage": { - "contentDescription": { - "defaultValue": { - "value": "Hero image description", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" - } - }, - "ticketLeg": { - "destinationStationCode": "SFO", - "destinationName": { - "defaultValue": { - "value": "Destination name", - "language": "en-US" - } - }, - "arrivalDateTime": "2020-04-12T20:20:50.52Z", - "originStationCode": "LA", - "originName": { - "defaultValue": { - "value": "Origin name", - "language": "en-US" - } - }, - "departureDateTime": "2020-04-12T16:20:50.52Z", - "fareName": { - "defaultValue": { - "value": "Fare name", - "language": "en-US" - } - } - }, - "barcode": { - "type": "QR_CODE", - "value": "QR code" - }, - "locations": [ - { - "latitude": 37.424015499999996, - "longitude": -122.09259560000001 - } - ], - "passengerType": "SINGLE_PASSENGER", - "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" - } - ] - }, - "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" - } - ], - "tripType": "ONE_WAY", - "id": "%s.%s" + transitObject := new(walletobjects.TransitObject) + transitObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + transitObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + transitObject.State = "ACTIVE" + transitObject.PassengerNames = "Passenger names" + transitObject.TripType = "ONE_WAY" + transitObject.PassengerType = "SINGLE_PASSENGER" + transitObject.TicketLeg = &walletobjects.TicketLeg{ + DestinationStationCode: "SFO", + OriginStationCode: "LA", } - `, issuerId, classSuffix, issuerId, objectSuffix) - - res, err := d.httpClient.Post(objectUrl, "application/json", bytes.NewBuffer([]byte(newObject))) - + transitObject.HeroImage = &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + }, + } + transitObject.Barcode = &walletobjects.Barcode{ + Type: "QR_CODE", + Value: "QR code", + } + transitObject.Locations = []*walletobjects.LatLongPoint{ + &walletobjects.LatLongPoint{ + Latitude: 37.424015499999996, + Longitude: -122.09259560000001, + }, + } + transitObject.LinksModuleData = &walletobjects.LinksModuleData{ + Uris: []*walletobjects.Uri{ + &walletobjects.Uri{ + Id: "LINK_MODULE_URI_ID", + Uri: "http://maps.google.com/", + Description: "Link module URI description", + }, + &walletobjects.Uri{ + Id: "LINK_MODULE_TEL_ID", + Uri: "tel:6505555555", + Description: "Link module tel description", + }, + }, + } + transitObject.ImageModulesData = []*walletobjects.ImageModuleData{ + &walletobjects.ImageModuleData{ + Id: "IMAGE_MODULE_ID", + MainImage: &walletobjects.Image{ + SourceUri: &walletobjects.ImageUri{ + Uri: "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + }, + }, + }, + } + transitObject.TextModulesData = []*walletobjects.TextModuleData{ + &walletobjects.TextModuleData{ + Body: "Text module body", + Header: "Text module header", + Id: "TEXT_MODULE_ID", + }, + } + res, err := d.service.Transitobject.Insert(transitObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to insert object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object insert response:\n%s\n", b) + fmt.Printf("Object insert id:\n%s\n", res.Id) } } @@ -209,16 +160,14 @@ func (d *demoTransit) createObject(issuerId, classSuffix, objectSuffix string) { // Sets the object's state to Expired. If the valid time interval is // already set, the pass will expire automatically up to 24 hours after. func (d *demoTransit) expireObject(issuerId, objectSuffix string) { - patchBody := `{"state": "EXPIRED"}` - url := fmt.Sprintf("%s/%s.%s", objectUrl, issuerId, objectSuffix) - req, _ := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer([]byte(patchBody))) - res, err := d.httpClient.Do(req) - + transitObject := &walletobjects.TransitObject{ + State: "EXPIRED", + } + res, err := d.service.Transitobject.Patch(fmt.Sprintf("%s.%s", issuerId, objectSuffix), transitObject).Do() if err != nil { - fmt.Println(err) + log.Fatalf("Unable to patch object: %v", err) } else { - b, _ := io.ReadAll(res.Body) - fmt.Printf("Object expiration response:\n%s\n", b) + fmt.Printf("Object expiration id:\n%s\n", res.Id) } } @@ -232,127 +181,25 @@ func (d *demoTransit) expireObject(issuerId, objectSuffix string) { // 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 *demoTransit) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) { - newClass := fmt.Sprintf(` - { - "logo": { - "contentDescription": { - "defaultValue": { - "value": "Logo description", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://live.staticflickr.com/65535/48690277162_cd05f03f4d_o.png" - } - }, - "issuerName": "Issuer name", - "reviewStatus": "UNDER_REVIEW", - "id": "%s.%s", - "transitType": "BUS" + transitObject := new(walletobjects.TransitObject) + transitObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + transitObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + transitObject.State = "ACTIVE" + transitObject.PassengerNames = "Passenger names" + transitObject.TripType = "ONE_WAY" + transitObject.PassengerType = "SINGLE_PASSENGER" + transitObject.TicketLeg = &walletobjects.TicketLeg{ + DestinationStationCode: "SFO", + OriginStationCode: "LA", } - `, issuerId, classSuffix) - newObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "passengerNames": "Passenger names", - "heroImage": { - "contentDescription": { - "defaultValue": { - "value": "Hero image description", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" - } - }, - "ticketLeg": { - "destinationStationCode": "SFO", - "destinationName": { - "defaultValue": { - "value": "Destination name", - "language": "en-US" - } - }, - "arrivalDateTime": "2020-04-12T20:20:50.52Z", - "originStationCode": "LA", - "originName": { - "defaultValue": { - "value": "Origin name", - "language": "en-US" - } - }, - "departureDateTime": "2020-04-12T16:20:50.52Z", - "fareName": { - "defaultValue": { - "value": "Fare name", - "language": "en-US" - } - } - }, - "barcode": { - "type": "QR_CODE", - "value": "QR code" - }, - "locations": [ - { - "latitude": 37.424015499999996, - "longitude": -122.09259560000001 - } - ], - "passengerType": "SINGLE_PASSENGER", - "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" - } - ] - }, - "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" - } - ], - "tripType": "ONE_WAY", - "id": "%s.%s" - } - `, issuerId, classSuffix, issuerId, objectSuffix) - - var payload map[string]interface{} + transitJson, _ := json.Marshal(transitObject) + var payload map[string]any json.Unmarshal([]byte(fmt.Sprintf(` { - "genericClasses": [%s], - "genericObjects": [%s] + "transitObjects": [%s] } - `, newClass, newObject)), &payload) - + `, transitJson)), &payload) claims := jwt.MapClaims{ "iss": d.credentials.Email, "aud": "google", @@ -365,7 +212,7 @@ func (d *demoTransit) createJwtNewObjects(issuerId, classSuffix, objectSuffix st key, _ := jwt.ParseRSAPrivateKeyFromPEM(d.credentials.PrivateKey) token, _ := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key) - fmt.Println("Add to Google Wallet link") + fmt.Println("Add to Google Wallet link for new objects") fmt.Println("https://pay.google.com/gp/v/save/" + token) } @@ -378,7 +225,7 @@ func (d *demoTransit) createJwtNewObjects(issuerId, classSuffix, objectSuffix st // their wallet, the pass objects defined in the JWT are added to the // user's Google Wallet app. This allows the user to save multiple pass // objects in one API call. -func (d *demoTransit) createJwtExistingObjects(issuerId string) { +func (d *demoTransit) createJwtExistingObjects(issuerId string, classSuffix string, objectSuffix string) { var payload map[string]interface{} json.Unmarshal([]byte(fmt.Sprintf(` { @@ -444,98 +291,20 @@ func (d *demoTransit) batchCreateObjects(issuerId, classSuffix string) { for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") - batchObject := fmt.Sprintf(` - { - "classId": "%s.%s", - "passengerNames": "Passenger names", - "heroImage": { - "contentDescription": { - "defaultValue": { - "value": "Hero image description", - "language": "en-US" - } - }, - "sourceUri": { - "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" - } - }, - "ticketLeg": { - "destinationStationCode": "SFO", - "destinationName": { - "defaultValue": { - "value": "Destination name", - "language": "en-US" - } - }, - "arrivalDateTime": "2020-04-12T20:20:50.52Z", - "originStationCode": "LA", - "originName": { - "defaultValue": { - "value": "Origin name", - "language": "en-US" - } - }, - "departureDateTime": "2020-04-12T16:20:50.52Z", - "fareName": { - "defaultValue": { - "value": "Fare name", - "language": "en-US" - } - } - }, - "barcode": { - "type": "QR_CODE", - "value": "QR code" - }, - "locations": [ - { - "latitude": 37.424015499999996, - "longitude": -122.09259560000001 - } - ], - "passengerType": "SINGLE_PASSENGER", - "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" - } - ] - }, - "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" - } - ], - "tripType": "ONE_WAY", - "id": "%s.%s" + transitObject := new(walletobjects.TransitObject) + transitObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) + transitObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) + transitObject.State = "ACTIVE" + transitObject.PassengerNames = "Passenger names" + transitObject.TripType = "ONE_WAY" + transitObject.PassengerType = "SINGLE_PASSENGER" + transitObject.TicketLeg = &walletobjects.TicketLeg{ + DestinationStationCode: "SFO", + OriginStationCode: "LA", } - `, issuerId, classSuffix, issuerId, objectSuffix) + + transitJson, _ := json.Marshal(transitObject) + batchObject := fmt.Sprintf("%s", transitJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" @@ -544,8 +313,7 @@ func (d *demoTransit) batchCreateObjects(issuerId, classSuffix string) { } data += "--batch_createobjectbatch--" - // batchUrl = 'https://walletobjects.googleapis.com/batch'; - res, err := d.httpClient.Post(batchUrl, "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) + res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) @@ -558,11 +326,6 @@ func (d *demoTransit) batchCreateObjects(issuerId, classSuffix string) { // [END batch] func main() { - if len(os.Args) == 0 { - fmt.Println("Usage: go run demo_transit.go ") - os.Exit(1) - } - issuerId := os.Getenv("WALLET_ISSUER_ID") classSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") objectSuffix := fmt.Sprintf("%s-%s", strings.ReplaceAll(uuid.New().String(), "-", "_"), classSuffix) @@ -574,6 +337,6 @@ func main() { d.createObject(issuerId, classSuffix, objectSuffix) d.expireObject(issuerId, objectSuffix) d.createJwtNewObjects(issuerId, classSuffix, objectSuffix) - d.createJwtExistingObjects(issuerId) + d.createJwtExistingObjects(issuerId, classSuffix, objectSuffix) d.batchCreateObjects(issuerId, classSuffix) }