From fcddb6659ec9e6c38c03225e778bd0fe2c42c732 Mon Sep 17 00:00:00 2001 From: Nick Alteen Date: Fri, 19 Aug 2022 13:40:05 -0400 Subject: [PATCH] Initial commit of demo issuer creation and permissions update code samples for /wallet documentation * Added issuer creation and permissions update examples to all templates * Generated new outputs for each template * Updated Google SDK version sfor C#, Java, PHP, and Python templates * General formatting and linting updates * Additional commenting * Added stronger typing of variables in C# and Java examples --- .gitignore | 4 + dotnet/DemoEventticket.cs | 333 +++++++++++++ dotnet/DemoEventticket.cs.example | 241 --------- dotnet/DemoFlight.cs | 310 ++++++++++++ dotnet/DemoFlight.cs.example | 218 --------- dotnet/DemoGeneric.cs | 301 ++++++++++++ dotnet/DemoGeneric.cs.example | 209 -------- dotnet/DemoGiftcard.cs | 292 +++++++++++ dotnet/DemoGiftcard.cs.example | 200 -------- dotnet/DemoLoyalty.cs | 299 ++++++++++++ dotnet/DemoLoyalty.cs.example | 207 -------- dotnet/DemoOffer.cs | 293 +++++++++++ dotnet/DemoOffer.cs.example | 201 -------- dotnet/DemoTransit.cs | 355 ++++++++++++++ dotnet/DemoTransit.cs.example | 263 ---------- dotnet/wallet-rest-samples.csproj | 4 +- http/demo_eventticket.http | 139 ++++++ http/demo_flight.http | 110 +++++ http/demo_generic.http | 119 +++++ http/demo_giftcard.http | 111 +++++ http/demo_loyalty.http | 110 +++++ http/demo_offer.http | 110 +++++ http/demo_transit.http | 154 ++++++ java/build.gradle | 4 + java/src/main/java/DemoEventticket.java | 219 ++++++--- java/src/main/java/DemoFlight.java | 219 ++++++--- java/src/main/java/DemoGeneric.java | 219 ++++++--- java/src/main/java/DemoGiftcard.java | 219 ++++++--- java/src/main/java/DemoLoyalty.java | 219 ++++++--- java/src/main/java/DemoOffer.java | 219 ++++++--- java/src/main/java/DemoTransit.java | 219 ++++++--- nodejs/demo-eventticket.js | 138 +++++- nodejs/demo-flight.js | 138 +++++- nodejs/demo-generic.js | 138 +++++- nodejs/demo-giftcard.js | 138 +++++- nodejs/demo-loyalty.js | 138 +++++- nodejs/demo-offer.js | 138 +++++- nodejs/demo-transit.js | 138 +++++- php/composer.json | 4 +- php/demo_eventticket.php | 150 +++++- php/demo_flight.php | 150 +++++- php/demo_generic.php | 150 +++++- php/demo_giftcard.php | 150 +++++- php/demo_loyalty.php | 150 +++++- php/demo_offer.php | 150 +++++- php/demo_transit.php | 150 +++++- python/Pipfile | 13 + python/demo_eventticket.py | 136 +++++- python/demo_flight.py | 136 +++++- python/demo_generic.py | 136 +++++- python/demo_giftcard.py | 136 +++++- python/demo_loyalty.py | 136 +++++- python/demo_offer.py | 136 +++++- python/demo_transit.py | 136 +++++- templates/generate.py | 621 +++++++++++++----------- templates/template.cs | 176 +++++-- templates/template.http | 48 ++ templates/template.java | 219 ++++++--- templates/template.js | 138 +++++- templates/template.php | 150 +++++- templates/template.py | 130 ++++- 61 files changed, 7649 insertions(+), 2938 deletions(-) create mode 100644 dotnet/DemoEventticket.cs delete mode 100644 dotnet/DemoEventticket.cs.example create mode 100644 dotnet/DemoFlight.cs delete mode 100644 dotnet/DemoFlight.cs.example create mode 100644 dotnet/DemoGeneric.cs delete mode 100644 dotnet/DemoGeneric.cs.example create mode 100644 dotnet/DemoGiftcard.cs delete mode 100644 dotnet/DemoGiftcard.cs.example create mode 100644 dotnet/DemoLoyalty.cs delete mode 100644 dotnet/DemoLoyalty.cs.example create mode 100644 dotnet/DemoOffer.cs delete mode 100644 dotnet/DemoOffer.cs.example create mode 100644 dotnet/DemoTransit.cs delete mode 100644 dotnet/DemoTransit.cs.example create mode 100644 http/demo_eventticket.http create mode 100644 http/demo_flight.http create mode 100644 http/demo_generic.http create mode 100644 http/demo_giftcard.http create mode 100644 http/demo_loyalty.http create mode 100644 http/demo_offer.http create mode 100644 http/demo_transit.http create mode 100644 python/Pipfile create mode 100644 templates/template.http diff --git a/.gitignore b/.gitignore index 935fee4..c6129c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # OS .DS_Store +.vscode +*.code-workspace # Node.js node_modules @@ -17,6 +19,8 @@ local.properties # Python *.pyc __pycache__ +.venv/ +Pipfile.lock # .NET bin diff --git a/dotnet/DemoEventticket.cs b/dotnet/DemoEventticket.cs new file mode 100644 index 0000000..8ca8464 --- /dev/null +++ b/dotnet/DemoEventticket.cs @@ -0,0 +1,333 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-eventTicket-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name", + eventName = new + { + defaultValue = new + { + language = "en-US", + value = "Test event name" + } + }, + reviewStatus = "underReview" +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + kind = "walletobjects#barcode", + type = "qrCode", + value = "Test QR Code" + }, + state = "active", + seatInfo = new + { + kind = "walletobjects#eventSeat", + seat = new + { + kind = "walletobjects#localizedString", + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "42" + } + }, + row = new + { + kind = "walletobjects#localizedString", + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "G3" + } + }, + section = new + { + kind = "walletobjects#localizedString", + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "5" + } + }, + gate = new + { + kind = "walletobjects#localizedString", + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "A" + } + } + }, + ticketHolderName = "Test ticket holder name", + ticketNumber = "Test ticket number", + locations = new object[] + { + new + { + kind = "walletobjects#latLongPoint", + latitude = 37.424015499999996, + longitude = -122.09259560000001 + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + eventTicketObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoEventticket.cs.example b/dotnet/DemoEventticket.cs.example deleted file mode 100644 index d4e160a..0000000 --- a/dotnet/DemoEventticket.cs.example +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-eventTicket-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name", - eventName = new - { - defaultValue = new - { - language = "en-US", - value = "Test event name" - } - }, - reviewStatus = "underReview" -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - kind = "walletobjects#barcode", - type = "qrCode", - value = "Test QR Code" - }, - state = "active", - seatInfo = new - { - kind = "walletobjects#eventSeat", - seat = new - { - kind = "walletobjects#localizedString", - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "42" - } - }, - row = new - { - kind = "walletobjects#localizedString", - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "G3" - } - }, - section = new - { - kind = "walletobjects#localizedString", - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "5" - } - }, - gate = new - { - kind = "walletobjects#localizedString", - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "A" - } - } - }, - ticketHolderName = "Test ticket holder name", - ticketNumber = "Test ticket number", - locations = new object[] - { - new - { - kind = "walletobjects#latLongPoint", - latitude = 37.424015499999996, - longitude = -122.09259560000001 - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - eventTicketObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/DemoFlight.cs b/dotnet/DemoFlight.cs new file mode 100644 index 0000000..822711f --- /dev/null +++ b/dotnet/DemoFlight.cs @@ -0,0 +1,310 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-flight-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name", + destination = new + { + airportIataCode = "SFO", + gate = "C3", + terminal = "2" + }, + flightHeader = new + { + carrier = new + { + carrierIataCode = "LX" + }, + flightNumber = "123" + }, + origin = new + { + airportIataCode = "LAX", + gate = "A2", + terminal = "1" + }, + localScheduledDepartureDateTime = "2023-07-02T15:30:00", + reviewStatus = "underReview" +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + kind = "walletobjects#barcode", + type = "qrCode", + value = "Test QR Code" + }, + state = "active", + passengerName = "Test passenger name", + reservationInfo = new + { + confirmationCode = "Test confirmation code" + }, + boardingAndSeatingInfo = new + { + seatNumber = "42", + boardingGroup = "B" + }, + locations = new object[] + { + new + { + kind = "walletobjects#latLongPoint", + latitude = 37.424015499999996, + longitude = -122.09259560000001 + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + flightObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoFlight.cs.example b/dotnet/DemoFlight.cs.example deleted file mode 100644 index 64a4348..0000000 --- a/dotnet/DemoFlight.cs.example +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-flight-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name", - destination = new - { - airportIataCode = "SFO", - gate = "C3", - terminal = "2" - }, - flightHeader = new - { - carrier = new - { - carrierIataCode = "LX" - }, - flightNumber = "123" - }, - origin = new - { - airportIataCode = "LAX", - gate = "A2", - terminal = "1" - }, - localScheduledDepartureDateTime = "2023-07-02T15:30:00", - reviewStatus = "underReview" -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - kind = "walletobjects#barcode", - type = "qrCode", - value = "Test QR Code" - }, - state = "active", - passengerName = "Test passenger name", - reservationInfo = new - { - confirmationCode = "Test confirmation code" - }, - boardingAndSeatingInfo = new - { - seatNumber = "42", - boardingGroup = "B" - }, - locations = new object[] - { - new - { - kind = "walletobjects#latLongPoint", - latitude = 37.424015499999996, - longitude = -122.09259560000001 - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - flightObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/DemoGeneric.cs b/dotnet/DemoGeneric.cs new file mode 100644 index 0000000..f7a318a --- /dev/null +++ b/dotnet/DemoGeneric.cs @@ -0,0 +1,301 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-generic-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name" +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + kind = "walletobjects#barcode", + type = "qrCode", + value = "Test QR Code" + }, + genericType = "GENERIC_TYPE_UNSPECIFIED", + hexBackgroundColor = "#4285f4", + logo = new + { + sourceUri = new + { + uri = "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" + } + }, + cardTitle = new + { + defaultValue = new + { + language = "en-US", + value = "Testing Generic Title" + } + }, + header = new + { + defaultValue = new + { + language = "en-US", + value = "Testing Generic Header" + } + }, + subheader = new + { + defaultValue = new + { + language = "en", + value = "Testing Generic Sub Header" + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + genericObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoGeneric.cs.example b/dotnet/DemoGeneric.cs.example deleted file mode 100644 index 81cb578..0000000 --- a/dotnet/DemoGeneric.cs.example +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-generic-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name" -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - kind = "walletobjects#barcode", - type = "qrCode", - value = "Test QR Code" - }, - genericType = "GENERIC_TYPE_UNSPECIFIED", - hexBackgroundColor = "#4285f4", - logo = new - { - sourceUri = new - { - uri = "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" - } - }, - cardTitle = new - { - defaultValue = new - { - language = "en-US", - value = "Testing Generic Title" - } - }, - header = new - { - defaultValue = new - { - language = "en-US", - value = "Testing Generic Header" - } - }, - subheader = new - { - defaultValue = new - { - language = "en", - value = "Testing Generic Sub Header" - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - genericObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/DemoGiftcard.cs b/dotnet/DemoGiftcard.cs new file mode 100644 index 0000000..0cb54fb --- /dev/null +++ b/dotnet/DemoGiftcard.cs @@ -0,0 +1,292 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-giftCard-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name", + merchantName = "Test merchant name", + allowMultipleUsersPerObject = "true", + reviewStatus = "underReview" +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + kind = "walletobjects#barcode", + type = "qrCode", + value = "Test QR Code" + }, + cardNumber = "Test card number", + cardPin = "Test card pin", + balance = new + { + kind = "walletobjects#money", + micros = 20000000, + currencyCode = "USD" + }, + balanceUpdateTime = new + { + date = "2020-04-12T16:20:50.52Z" + }, + locations = new object[] + { + new + { + kind = "walletobjects#latLongPoint", + latitude = 37.424015499999996, + longitude = -122.09259560000001 + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + giftCardObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoGiftcard.cs.example b/dotnet/DemoGiftcard.cs.example deleted file mode 100644 index e0f9056..0000000 --- a/dotnet/DemoGiftcard.cs.example +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-giftCard-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name", - merchantName = "Test merchant name", - allowMultipleUsersPerObject = "true", - reviewStatus = "underReview" -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - kind = "walletobjects#barcode", - type = "qrCode", - value = "Test QR Code" - }, - cardNumber = "Test card number", - cardPin = "Test card pin", - balance = new - { - kind = "walletobjects#money", - micros = 20000000, - currencyCode = "USD" - }, - balanceUpdateTime = new - { - date = "2020-04-12T16:20:50.52Z" - }, - locations = new object[] - { - new - { - kind = "walletobjects#latLongPoint", - latitude = 37.424015499999996, - longitude = -122.09259560000001 - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - giftCardObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/DemoLoyalty.cs b/dotnet/DemoLoyalty.cs new file mode 100644 index 0000000..5850a0a --- /dev/null +++ b/dotnet/DemoLoyalty.cs @@ -0,0 +1,299 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-loyalty-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name", + programName = "test program name", + programLogo = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg" + } + }, + reviewStatus = "underReview" +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + kind = "walletobjects#barcode", + type = "qrCode", + value = "Test QR Code" + }, + state = "active", + accountId = "Test account id", + accountName = "Test account name", + loyaltyPoints = new + { + balance = new + { + @string = "800" + }, + label = "Points" + }, + locations = new object[] + { + new + { + kind = "walletobjects#latLongPoint", + latitude = 37.424015499999996, + longitude = -122.09259560000001 + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + loyaltyObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoLoyalty.cs.example b/dotnet/DemoLoyalty.cs.example deleted file mode 100644 index 683d1a3..0000000 --- a/dotnet/DemoLoyalty.cs.example +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-loyalty-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name", - programName = "test program name", - programLogo = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg" - } - }, - reviewStatus = "underReview" -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - kind = "walletobjects#barcode", - type = "qrCode", - value = "Test QR Code" - }, - state = "active", - accountId = "Test account id", - accountName = "Test account name", - loyaltyPoints = new - { - balance = new - { - @string = "800" - }, - label = "Points" - }, - locations = new object[] - { - new - { - kind = "walletobjects#latLongPoint", - latitude = 37.424015499999996, - longitude = -122.09259560000001 - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - loyaltyObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/DemoOffer.cs b/dotnet/DemoOffer.cs new file mode 100644 index 0000000..b3476e9 --- /dev/null +++ b/dotnet/DemoOffer.cs @@ -0,0 +1,293 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-offer-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name", + provider = "test provider", + reviewStatus = "underReview", + title = "test title", + redemptionChannel = "online" +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + type = "qrCode", + value = "Testing Offers QR Code" + }, + state = "active", + validTimeInterval = new + { + kind = "walletobjects#timeInterval", + start = new + { + date = "2023-06-12T23:20:50.52Z" + }, + end = new + { + date = "2023-12-12T23:20:50.52Z" + } + }, + locations = new object[] + { + new + { + kind = "walletobjects#latLongPoint", + latitude = 37.424015499999996, + longitude = -122.09259560000001 + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + offerObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoOffer.cs.example b/dotnet/DemoOffer.cs.example deleted file mode 100644 index 34485e4..0000000 --- a/dotnet/DemoOffer.cs.example +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-offer-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name", - provider = "test provider", - reviewStatus = "underReview", - title = "test title", - redemptionChannel = "online" -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - type = "qrCode", - value = "Testing Offers QR Code" - }, - state = "active", - validTimeInterval = new - { - kind = "walletobjects#timeInterval", - start = new - { - date = "2023-06-12T23:20:50.52Z" - }, - end = new - { - date = "2023-12-12T23:20:50.52Z" - } - }, - locations = new object[] - { - new - { - kind = "walletobjects#latLongPoint", - latitude = 37.424015499999996, - longitude = -122.09259560000001 - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - offerObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/DemoTransit.cs b/dotnet/DemoTransit.cs new file mode 100644 index 0000000..1443200 --- /dev/null +++ b/dotnet/DemoTransit.cs @@ -0,0 +1,355 @@ +/* + * Copyright 2022 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START setup] +// [START imports] +using System.IdentityModel.Tokens.Jwt; +using System.Net; +using System.Net.Http.Headers; +using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] + +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; + +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; + +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-transit-class-id"; + +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; +// [END setup] + +/////////////////////////////////////////////////////////////////////////////// +// Create authenticated HTTP client, using service account file. +/////////////////////////////////////////////////////////////////////////////// + +// [START auth] +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); +// [END auth] + +/////////////////////////////////////////////////////////////////////////////// +// Create a class via the API (this can also be done in the business console). +/////////////////////////////////////////////////////////////////////////////// + +// [START class] +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitClass/"; +var classPayload = new +{ + id = $"{issuerId}.{classId}", + issuerName = "test issuer name", + reviewStatus = "underReview", + transitType = "bus", + logo = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "https://live.staticflickr.com/65535/48690277162_cd05f03f4d_o.png", + description = "Test logo description" + } + } +}; + +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); +// [END class] + +/////////////////////////////////////////////////////////////////////////////// +// Create an object via the API. +/////////////////////////////////////////////////////////////////////////////// + +// [START object] +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitObject/"; +var objectPayload = new +{ + id = objectId, + classId = $"{issuerId}.{classId}", + heroImage = new + { + sourceUri = new + { + uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + description = "Test heroImage description" + } + }, + textModulesData = new object[] + { + new + { + header = "Test text module header", + body = "Test text module body" + } + }, + linksModuleData = new + { + uris = new object[] + { + new + { + kind = "walletobjects#uri", + uri = "http://maps.google.com/", + description = "Test link module uri description" + }, + new + { + kind = "walletobjects#uri", + uri = "tel:6505555555", + description = "Test link module tel description" + } + } + }, + imageModulesData = new object[] + { + new + { + mainImage = new + { + kind = "walletobjects#image", + sourceUri = new + { + kind = "walletobjects#uri", + uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + description = "Test image module description" + } + } + } + }, + barcode = new + { + kind = "walletobjects#barcode", + type = "qrCode", + value = "Test QR Code" + }, + passengerType = "singlePassenger", + passengerNames = "Test passenger names", + ticketLeg = new + { + originStationCode = "LA", + originName = new + { + kind = "walletobjects#localizedString", + translatedValues = new object[] + { + new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "Test translated origin name" + } + }, + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "Test default origin name" + } + }, + destinationStationCode = "SFO", + destinationName = new + { + kind = "walletobjects#localizedString", + translatedValues = new object[] + { + new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "Test translated destination name" + } + }, + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "Test default destination name" + } + }, + departureDateTime = "2020-04-12T16:20:50.52Z", + arrivalDateTime = "2020-04-12T20:20:50.52Z", + fareName = new + { + kind = "walletobjects#localizedString", + translatedValues = new object[] + { + new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "Test translated fare name" + } + }, + defaultValue = new + { + kind = "walletobjects#translatedString", + language = "en-us", + value = "Test default fare name" + } + } + }, + locations = new object[] + { + new + { + kind = "walletobjects#latLongPoint", + latitude = 37.424015499999996, + longitude = -122.09259560000001 + } + } +}; + +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) +{ + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); +} + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); +// [END object] + +/////////////////////////////////////////////////////////////////////////////// +// Create a JWT for the object, and encode it to create a "Save" URL. +/////////////////////////////////////////////////////////////////////////////// + +// [START jwt] +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); +claims.Add("aud", "google"); +claims.Add("origins", new string[] { "www.example.com" }); +claims.Add("typ", "savetowallet"); +claims.Add("payload", new +{ + transitObjects = new object[] + { + new + { + id = objectId + } + } +}); + +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +Console.WriteLine(saveUrl); +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/dotnet/DemoTransit.cs.example b/dotnet/DemoTransit.cs.example deleted file mode 100644 index 58c7c0f..0000000 --- a/dotnet/DemoTransit.cs.example +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2022 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; - -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; - -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; - -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-transit-class-id"; - -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; - -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); -// [END setup] - -/////////////////////////////////////////////////////////////////////////////// -// Create authenticated HTTP client, using service account file. -/////////////////////////////////////////////////////////////////////////////// - -// [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; - -var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); -// [END auth] - -/////////////////////////////////////////////////////////////////////////////// -// Create a class via the API (this can also be done in the business console). -/////////////////////////////////////////////////////////////////////////////// - -// [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitClass/"; -var classPayload = new -{ - id = $"{issuerId}.{classId}", - issuerName = "test issuer name", - reviewStatus = "underReview", - transitType = "bus", - logo = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "https://live.staticflickr.com/65535/48690277162_cd05f03f4d_o.png", - description = "Test logo description" - } - } -}; - -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); -// [END class] - -/////////////////////////////////////////////////////////////////////////////// -// Create an object via the API. -/////////////////////////////////////////////////////////////////////////////// - -// [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitObject/"; -var objectPayload = new -{ - id = objectId, - classId = $"{issuerId}.{classId}", - heroImage = new - { - sourceUri = new - { - uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", - description = "Test heroImage description" - } - }, - textModulesData = new object[] - { - new - { - header = "Test text module header", - body = "Test text module body" - } - }, - linksModuleData = new - { - uris = new object[] - { - new - { - kind = "walletobjects#uri", - uri = "http://maps.google.com/", - description = "Test link module uri description" - }, - new - { - kind = "walletobjects#uri", - uri = "tel:6505555555", - description = "Test link module tel description" - } - } - }, - imageModulesData = new object[] - { - new - { - mainImage = new - { - kind = "walletobjects#image", - sourceUri = new - { - kind = "walletobjects#uri", - uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", - description = "Test image module description" - } - } - } - }, - barcode = new - { - kind = "walletobjects#barcode", - type = "qrCode", - value = "Test QR Code" - }, - passengerType = "singlePassenger", - passengerNames = "Test passenger names", - ticketLeg = new - { - originStationCode = "LA", - originName = new - { - kind = "walletobjects#localizedString", - translatedValues = new object[] - { - new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "Test translated origin name" - } - }, - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "Test default origin name" - } - }, - destinationStationCode = "SFO", - destinationName = new - { - kind = "walletobjects#localizedString", - translatedValues = new object[] - { - new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "Test translated destination name" - } - }, - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "Test default destination name" - } - }, - departureDateTime = "2020-04-12T16:20:50.52Z", - arrivalDateTime = "2020-04-12T20:20:50.52Z", - fareName = new - { - kind = "walletobjects#localizedString", - translatedValues = new object[] - { - new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "Test translated fare name" - } - }, - defaultValue = new - { - kind = "walletobjects#translatedString", - language = "en-us", - value = "Test default fare name" - } - } - }, - locations = new object[] - { - new - { - kind = "walletobjects#latLongPoint", - latitude = 37.424015499999996, - longitude = -122.09259560000001 - } - } -}; - -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) -{ - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); -} -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); -// [END object] - -/////////////////////////////////////////////////////////////////////////////// -// Create a JWT for the object, and encode it to create a "Save" URL. -/////////////////////////////////////////////////////////////////////////////// - -// [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. -claims.Add("aud", "google"); -claims.Add("origins", new string[] { "www.example.com" }); -claims.Add("typ", "savetowallet"); -claims.Add("payload", new -{ - transitObjects = new object[] - { - new - { - id = objectId, - }, - }, -}); - -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; -Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file diff --git a/dotnet/wallet-rest-samples.csproj b/dotnet/wallet-rest-samples.csproj index e565a9c..5847841 100644 --- a/dotnet/wallet-rest-samples.csproj +++ b/dotnet/wallet-rest-samples.csproj @@ -9,7 +9,9 @@ - + + + diff --git a/http/demo_eventticket.http b/http/demo_eventticket.http new file mode 100644 index 0000000..f97e780 --- /dev/null +++ b/http/demo_eventticket.http @@ -0,0 +1,139 @@ +# [START object] +POST /walletobjects/v1/eventTicketObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "kind": "walletobjects#barcode", + "type": "qrCode", + "value": "Test QR Code" + }, + "state": "active", + "seatInfo": { + "kind": "walletobjects#eventSeat", + "seat": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "42" + } + }, + "row": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "G3" + } + }, + "section": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "5" + } + }, + "gate": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "A" + } + } + }, + "ticketHolderName": "Test ticket holder name", + "ticketNumber": "Test ticket number", + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001 + } + ] +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/http/demo_flight.http b/http/demo_flight.http new file mode 100644 index 0000000..180d495 --- /dev/null +++ b/http/demo_flight.http @@ -0,0 +1,110 @@ +# [START object] +POST /walletobjects/v1/flightObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "kind": "walletobjects#barcode", + "type": "qrCode", + "value": "Test QR Code" + }, + "state": "active", + "passengerName": "Test passenger name", + "reservationInfo": { + "confirmationCode": "Test confirmation code" + }, + "boardingAndSeatingInfo": { + "seatNumber": "42", + "boardingGroup": "B" + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001 + } + ] +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/http/demo_generic.http b/http/demo_generic.http new file mode 100644 index 0000000..7a42308 --- /dev/null +++ b/http/demo_generic.http @@ -0,0 +1,119 @@ +# [START object] +POST /walletobjects/v1/genericObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "kind": "walletobjects#barcode", + "type": "qrCode", + "value": "Test QR Code" + }, + "genericType": "GENERIC_TYPE_UNSPECIFIED", + "hexBackgroundColor": "#4285f4", + "logo": { + "sourceUri": { + "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" + } + }, + "cardTitle": { + "defaultValue": { + "language": "en-US", + "value": "Testing Generic Title" + } + }, + "header": { + "defaultValue": { + "language": "en-US", + "value": "Testing Generic Header" + } + }, + "subheader": { + "defaultValue": { + "language": "en", + "value": "Testing Generic Sub Header" + } + } +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/http/demo_giftcard.http b/http/demo_giftcard.http new file mode 100644 index 0000000..0c0cd70 --- /dev/null +++ b/http/demo_giftcard.http @@ -0,0 +1,111 @@ +# [START object] +POST /walletobjects/v1/giftCardObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "kind": "walletobjects#barcode", + "type": "qrCode", + "value": "Test QR Code" + }, + "cardNumber": "Test card number", + "cardPin": "Test card pin", + "balance": { + "kind": "walletobjects#money", + "micros": 20000000, + "currencyCode": "USD" + }, + "balanceUpdateTime": { + "date": "2020-04-12T16:20:50.52Z" + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001 + } + ] +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/http/demo_loyalty.http b/http/demo_loyalty.http new file mode 100644 index 0000000..3a89f02 --- /dev/null +++ b/http/demo_loyalty.http @@ -0,0 +1,110 @@ +# [START object] +POST /walletobjects/v1/loyaltyObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "kind": "walletobjects#barcode", + "type": "qrCode", + "value": "Test QR Code" + }, + "state": "active", + "accountId": "Test account id", + "accountName": "Test account name", + "loyaltyPoints": { + "balance": { + "string": "800" + }, + "label": "Points" + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001 + } + ] +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/http/demo_offer.http b/http/demo_offer.http new file mode 100644 index 0000000..79c9047 --- /dev/null +++ b/http/demo_offer.http @@ -0,0 +1,110 @@ +# [START object] +POST /walletobjects/v1/offerObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "type": "qrCode", + "value": "Testing Offers QR Code" + }, + "state": "active", + "validTimeInterval": { + "kind": "walletobjects#timeInterval", + "start": { + "date": "2023-06-12T23:20:50.52Z" + }, + "end": { + "date": "2023-12-12T23:20:50.52Z" + } + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001 + } + ] +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/http/demo_transit.http b/http/demo_transit.http new file mode 100644 index 0000000..fd979fc --- /dev/null +++ b/http/demo_transit.http @@ -0,0 +1,154 @@ +# [START object] +POST /walletobjects/v1/transitObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "id": issuer-id.user-id, + "classId": issuer-id.class-id, + "heroImage": { + "sourceUri": { + "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", + "description": "Test heroImage description" + } + }, + "textModulesData": [ + { + "header": "Test text module header", + "body": "Test text module body" + } + ], + "linksModuleData": { + "uris": [ + { + "kind": "walletobjects#uri", + "uri": "http://maps.google.com/", + "description": "Test link module uri description" + }, + { + "kind": "walletobjects#uri", + "uri": "tel:6505555555", + "description": "Test link module tel description" + } + ] + }, + "imageModulesData": [ + { + "mainImage": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "description": "Test image module description" + } + } + } + ], + "barcode": { + "kind": "walletobjects#barcode", + "type": "qrCode", + "value": "Test QR Code" + }, + "passengerType": "singlePassenger", + "passengerNames": "Test passenger names", + "ticketLeg": { + "originStationCode": "LA", + "originName": { + "kind": "walletobjects#localizedString", + "translatedValues": [ + { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test translated origin name" + } + ], + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test default origin name" + } + }, + "destinationStationCode": "SFO", + "destinationName": { + "kind": "walletobjects#localizedString", + "translatedValues": [ + { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test translated destination name" + } + ], + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test default destination name" + } + }, + "departureDateTime": "2020-04-12T16:20:50.52Z", + "arrivalDateTime": "2020-04-12T20:20:50.52Z", + "fareName": { + "kind": "walletobjects#localizedString", + "translatedValues": [ + { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test translated fare name" + } + ], + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test default fare name" + } + } + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001 + } + ] +} +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/java/build.gradle b/java/build.gradle index 4a8dd38..d4e478a 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -13,5 +13,9 @@ dependencies { implementation 'com.auth0:java-jwt:3.19.1' implementation 'com.auth0:jwks-rsa:0.9.0' implementation 'com.google.apis:google-api-services-oauth2:v1-rev20190313-1.30.3' + implementation 'com.google.api-client:google-api-client:2.0.0' + implementation 'com.google.auth:google-auth-library-oauth2-http:1.10.0' implementation 'com.squareup.okhttp3:okhttp:4.3.1' + implementation 'javax.json:javax.json-api:1.1' + implementation 'org.glassfish:javax.json:1.1' } diff --git a/java/src/main/java/DemoEventticket.java b/java/src/main/java/DemoEventticket.java index 9e62153..1fa86d9 100644 --- a/java/src/main/java/DemoEventticket.java +++ b/java/src/main/java/DemoEventticket.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoEventticket { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-eventTicket-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoEventticket { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,7 +91,7 @@ public class DemoEventticket { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," @@ -74,14 +105,14 @@ public class DemoEventticket { + " \"reviewStatus\": \"underReview\"" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -89,7 +120,8 @@ public class DemoEventticket { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -183,29 +215,24 @@ public class DemoEventticket { + " }" + " ]" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -213,25 +240,101 @@ public class DemoEventticket { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("eventTicketObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("eventTicketObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/java/src/main/java/DemoFlight.java b/java/src/main/java/DemoFlight.java index 65c204e..b2e312e 100644 --- a/java/src/main/java/DemoFlight.java +++ b/java/src/main/java/DemoFlight.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoFlight { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-flight-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoFlight { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,7 +91,7 @@ public class DemoFlight { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/flightClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," @@ -85,14 +116,14 @@ public class DemoFlight { + " \"reviewStatus\": \"underReview\"" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -100,7 +131,8 @@ public class DemoFlight { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/flightObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/flightObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -165,29 +197,24 @@ public class DemoFlight { + " }" + " ]" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -195,25 +222,101 @@ public class DemoFlight { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("flightObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("flightObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/java/src/main/java/DemoGeneric.java b/java/src/main/java/DemoGeneric.java index bf1b8b7..0e644ec 100644 --- a/java/src/main/java/DemoGeneric.java +++ b/java/src/main/java/DemoGeneric.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoGeneric { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-generic-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoGeneric { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,21 +91,21 @@ public class DemoGeneric { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/genericClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," + " \"issuerName\": \"test issuer name\"" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -82,7 +113,8 @@ public class DemoGeneric { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/genericObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/genericObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -156,29 +188,24 @@ public class DemoGeneric { + " }" + " }" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -186,25 +213,101 @@ public class DemoGeneric { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("genericObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("genericObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/java/src/main/java/DemoGiftcard.java b/java/src/main/java/DemoGiftcard.java index dc31263..4aa7ebf 100644 --- a/java/src/main/java/DemoGiftcard.java +++ b/java/src/main/java/DemoGiftcard.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoGiftcard { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-giftCard-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoGiftcard { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,7 +91,7 @@ public class DemoGiftcard { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," @@ -70,14 +101,14 @@ public class DemoGiftcard { + " \"reviewStatus\": \"underReview\"" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -85,7 +116,8 @@ public class DemoGiftcard { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -151,29 +183,24 @@ public class DemoGiftcard { + " }" + " ]" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -181,25 +208,101 @@ public class DemoGiftcard { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("giftCardObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("giftCardObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/java/src/main/java/DemoLoyalty.java b/java/src/main/java/DemoLoyalty.java index bc71f38..d2f9631 100644 --- a/java/src/main/java/DemoLoyalty.java +++ b/java/src/main/java/DemoLoyalty.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoLoyalty { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-loyalty-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoLoyalty { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,7 +91,7 @@ public class DemoLoyalty { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," @@ -76,14 +107,14 @@ public class DemoLoyalty { + " \"reviewStatus\": \"underReview\"" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -91,7 +122,8 @@ public class DemoLoyalty { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -156,29 +188,24 @@ public class DemoLoyalty { + " }" + " ]" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -186,25 +213,101 @@ public class DemoLoyalty { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("loyaltyObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("loyaltyObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/java/src/main/java/DemoOffer.java b/java/src/main/java/DemoOffer.java index fcdd6bf..b502add 100644 --- a/java/src/main/java/DemoOffer.java +++ b/java/src/main/java/DemoOffer.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoOffer { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-offer-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoOffer { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,7 +91,7 @@ public class DemoOffer { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/offerClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," @@ -71,14 +102,14 @@ public class DemoOffer { + " \"redemptionChannel\": \"online\"" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -86,7 +117,8 @@ public class DemoOffer { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/offerObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/offerObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -151,29 +183,24 @@ public class DemoOffer { + " }" + " ]" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -181,25 +208,101 @@ public class DemoOffer { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("offerObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("offerObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/java/src/main/java/DemoTransit.java b/java/src/main/java/DemoTransit.java index 435ee33..25c1ace 100644 --- a/java/src/main/java/DemoTransit.java +++ b/java/src/main/java/DemoTransit.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class DemoTransit { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-transit-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class DemoTransit { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,7 +91,7 @@ public class DemoTransit { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/transitClass/"); String classPayload = String.format( "{" + " \"id\": \"%s.%s\"," @@ -77,14 +108,14 @@ public class DemoTransit { + " }" + "}", issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -92,7 +123,8 @@ public class DemoTransit { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/transitObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/transitObject/" + objectId); String objectPayload = String.format( "{" + " \"id\": \"%s\"," @@ -201,29 +233,24 @@ public class DemoTransit { + " }" + " ]" + "}", objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -231,25 +258,101 @@ public class DemoTransit { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("transitObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("transitObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/nodejs/demo-eventticket.js b/nodejs/demo-eventticket.js index 000c80c..4036406 100644 --- a/nodejs/demo-eventticket.js +++ b/nodejs/demo-eventticket.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-eventTicket-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -66,13 +85,13 @@ async function main() { "reviewStatus": "underReview" }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -174,17 +193,26 @@ async function main() { ] }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -194,20 +222,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - eventTicketObjects: [{id: objectId}], - }, + eventTicketObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/nodejs/demo-flight.js b/nodejs/demo-flight.js index 4ba4070..3c0a810 100644 --- a/nodejs/demo-flight.js +++ b/nodejs/demo-flight.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-flight-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -77,13 +96,13 @@ async function main() { "reviewStatus": "underReview" }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -156,17 +175,26 @@ async function main() { ] }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -176,20 +204,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - flightObjects: [{id: objectId}], - }, + flightObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/nodejs/demo-generic.js b/nodejs/demo-generic.js index 652b9fd..7707f5f 100644 --- a/nodejs/demo-generic.js +++ b/nodejs/demo-generic.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-generic-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -59,13 +78,13 @@ async function main() { "issuerName": "test issuer name" }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -147,17 +166,26 @@ async function main() { } }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -167,20 +195,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - genericObjects: [{id: objectId}], - }, + genericObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/nodejs/demo-giftcard.js b/nodejs/demo-giftcard.js index 3d90d24..23d1130 100644 --- a/nodejs/demo-giftcard.js +++ b/nodejs/demo-giftcard.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-giftCard-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -62,13 +81,13 @@ async function main() { "reviewStatus": "underReview" }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -142,17 +161,26 @@ async function main() { ] }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -162,20 +190,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - giftCardObjects: [{id: objectId}], - }, + giftCardObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/nodejs/demo-loyalty.js b/nodejs/demo-loyalty.js index 1482797..207d8c0 100644 --- a/nodejs/demo-loyalty.js +++ b/nodejs/demo-loyalty.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-loyalty-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -68,13 +87,13 @@ async function main() { "reviewStatus": "underReview" }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -147,17 +166,26 @@ async function main() { ] }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -167,20 +195,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - loyaltyObjects: [{id: objectId}], - }, + loyaltyObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/nodejs/demo-offer.js b/nodejs/demo-offer.js index 7c8e245..8cfb119 100644 --- a/nodejs/demo-offer.js +++ b/nodejs/demo-offer.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-offer-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -63,13 +82,13 @@ async function main() { "redemptionChannel": "online" }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -142,17 +161,26 @@ async function main() { ] }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -162,20 +190,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - offerObjects: [{id: objectId}], - }, + offerObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/nodejs/demo-transit.js b/nodejs/demo-transit.js index ccc8e94..147d483 100644 --- a/nodejs/demo-transit.js +++ b/nodejs/demo-transit.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-transit-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -69,13 +88,13 @@ async function main() { } }; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -192,17 +211,26 @@ async function main() { ] }; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -212,20 +240,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - transitObjects: [{id: objectId}], - }, + transitObjects: [{ + id: objectId + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/php/composer.json b/php/composer.json index 3bccdda..dc101b7 100644 --- a/php/composer.json +++ b/php/composer.json @@ -1,5 +1,7 @@ { "require": { - "google/auth": "^1.18" + "google/auth": "^1.18", + "guzzlehttp/guzzle": "*", + "google/apiclient": "^2.12" } } diff --git a/php/demo_eventticket.php b/php/demo_eventticket.php index 9811622..38c0642 100644 --- a/php/demo_eventticket.php +++ b/php/demo_eventticket.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-eventTicket-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-eventTicket-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -73,12 +99,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -182,16 +208,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -199,16 +229,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['eventTicketObjects' => [['id' => $objectId]]] + 'payload' => [ + 'eventTicketObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/php/demo_flight.php b/php/demo_flight.php index 1add97f..356eaa6 100644 --- a/php/demo_flight.php +++ b/php/demo_flight.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-flight-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-flight-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -84,12 +110,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -164,16 +190,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -181,16 +211,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['flightObjects' => [['id' => $objectId]]] + 'payload' => [ + 'flightObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/php/demo_generic.php b/php/demo_generic.php index b804657..06a298e 100644 --- a/php/demo_generic.php +++ b/php/demo_generic.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-generic-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-generic-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -66,12 +92,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -155,16 +181,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -172,16 +202,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['genericObjects' => [['id' => $objectId]]] + 'payload' => [ + 'genericObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/php/demo_giftcard.php b/php/demo_giftcard.php index 77e5122..39ed8d9 100644 --- a/php/demo_giftcard.php +++ b/php/demo_giftcard.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-giftCard-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-giftCard-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -69,12 +95,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -150,16 +176,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -167,16 +197,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['giftCardObjects' => [['id' => $objectId]]] + 'payload' => [ + 'giftCardObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/php/demo_loyalty.php b/php/demo_loyalty.php index d38baf1..5b967da 100644 --- a/php/demo_loyalty.php +++ b/php/demo_loyalty.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-loyalty-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-loyalty-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -75,12 +101,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -155,16 +181,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -172,16 +202,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['loyaltyObjects' => [['id' => $objectId]]] + 'payload' => [ + 'loyaltyObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/php/demo_offer.php b/php/demo_offer.php index b1d0091..9306531 100644 --- a/php/demo_offer.php +++ b/php/demo_offer.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-offer-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-offer-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -70,12 +96,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -150,16 +176,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -167,16 +197,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['offerObjects' => [['id' => $objectId]]] + 'payload' => [ + 'offerObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/php/demo_transit.php b/php/demo_transit.php index 10ad1e9..47265cb 100644 --- a/php/demo_transit.php +++ b/php/demo_transit.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-transit-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-transit-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -76,12 +102,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -200,16 +226,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -217,16 +247,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['transitObjects' => [['id' => $objectId]]] + 'payload' => [ + 'transitObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/python/Pipfile b/python/Pipfile new file mode 100644 index 0000000..4dff796 --- /dev/null +++ b/python/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +google-auth = "*" +requests = "*" + +[dev-packages] + +[requires] +python_version = "3.9" diff --git a/python/demo_eventticket.py b/python/demo_eventticket.py index a328729..0e62a11 100644 --- a/python/demo_eventticket.py +++ b/python/demo_eventticket.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-eventTicket-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-eventTicket-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,9 +65,9 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name", "eventName": { "defaultValue": { @@ -66,8 +78,11 @@ class_payload = { "reviewStatus": "underReview" } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -75,10 +90,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/eventTicketObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -169,10 +184,15 @@ object_payload = { ] } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -182,17 +202,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "eventTicketObjects": [{"id": object_id}] + "eventTicketObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/python/demo_flight.py b/python/demo_flight.py index e1723fc..02b2957 100644 --- a/python/demo_flight.py +++ b/python/demo_flight.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-flight-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-flight-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,9 +65,9 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/flightClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/flightClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name", "destination": { "airportIataCode": "SFO", @@ -77,8 +89,11 @@ class_payload = { "reviewStatus": "underReview" } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -86,10 +101,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/flightObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/flightObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -151,10 +166,15 @@ object_payload = { ] } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -164,17 +184,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "flightObjects": [{"id": object_id}] + "flightObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/python/demo_generic.py b/python/demo_generic.py index 74b686e..6f9cf24 100644 --- a/python/demo_generic.py +++ b/python/demo_generic.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-generic-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-generic-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,14 +65,17 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/genericClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/genericClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name" } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -68,10 +83,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/genericObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/genericObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -142,10 +157,15 @@ object_payload = { } } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -155,17 +175,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "genericObjects": [{"id": object_id}] + "genericObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/python/demo_giftcard.py b/python/demo_giftcard.py index f496354..5ba2304 100644 --- a/python/demo_giftcard.py +++ b/python/demo_giftcard.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-giftCard-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-giftCard-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,17 +65,20 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name", "merchantName": "Test merchant name", "allowMultipleUsersPerObject": "true", "reviewStatus": "underReview" } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -71,10 +86,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/giftCardObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -137,10 +152,15 @@ object_payload = { ] } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -150,17 +170,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "giftCardObjects": [{"id": object_id}] + "giftCardObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/python/demo_loyalty.py b/python/demo_loyalty.py index f8cad6e..a032e97 100644 --- a/python/demo_loyalty.py +++ b/python/demo_loyalty.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-loyalty-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-loyalty-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,9 +65,9 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name", "programName": "test program name", "programLogo": { @@ -68,8 +80,11 @@ class_payload = { "reviewStatus": "underReview" } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -77,10 +92,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -142,10 +157,15 @@ object_payload = { ] } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -155,17 +175,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "loyaltyObjects": [{"id": object_id}] + "loyaltyObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/python/demo_offer.py b/python/demo_offer.py index 4da8e07..274c6dd 100644 --- a/python/demo_offer.py +++ b/python/demo_offer.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-offer-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-offer-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,9 +65,9 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/offerClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/offerClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name", "provider": "test provider", "reviewStatus": "underReview", @@ -63,8 +75,11 @@ class_payload = { "redemptionChannel": "online" } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -72,10 +87,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/offerObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/offerObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -137,10 +152,15 @@ object_payload = { ] } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -150,17 +170,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "offerObjects": [{"id": object_id}] + "offerObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/python/demo_transit.py b/python/demo_transit.py index d45c8af..4f61c42 100644 --- a/python/demo_transit.py +++ b/python/demo_transit.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-transit-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-transit-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,9 +65,9 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/transitClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/transitClass/" class_payload = { - "id": "%s.%s" % (issuer_id, class_id), + "id": f"{ISSUER_ID}.{CLASS_ID}", "issuerName": "test issuer name", "reviewStatus": "underReview", "transitType": "bus", @@ -69,8 +81,11 @@ class_payload = { } } -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -78,10 +93,10 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/transitObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/transitObject/" object_payload = { - "id": object_id, - "classId": "%s.%s" % (issuer_id, class_id), + "id": OBJECT_ID, + "classId": f"{ISSUER_ID}.{CLASS_ID}", "heroImage": { "sourceUri": { "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg", @@ -187,10 +202,15 @@ object_payload = { ] } -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -200,17 +220,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "transitObjects": [{"id": object_id}] + "transitObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions] diff --git a/templates/generate.py b/templates/generate.py index 9ad22e0..126066b 100644 --- a/templates/generate.py +++ b/templates/generate.py @@ -15,7 +15,8 @@ # the License. # -import os, json +import os +import json default_class_payload = { "id": "$class_id", @@ -57,7 +58,7 @@ default_object_payload = { "kind": "walletobjects#image", "sourceUri": { "kind": "walletobjects#uri", - "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", + "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", "description": "Test image module description", }, }, @@ -66,13 +67,21 @@ default_object_payload = { "barcode": { "kind": "walletobjects#barcode", "type": "qrCode", - "value": "Test QR Code" + "value": "Test QR Code", }, } payloads = {} -for object_type in ["generic", "offer", "loyalty", "giftCard", "eventTicket", "flight", "transit"]: +for object_type in [ + "generic", + "offer", + "loyalty", + "giftCard", + "eventTicket", + "flight", + "transit", +]: payloads[object_type] = { "$class_payload": dict(default_class_payload), "$object_payload": dict(default_object_payload), @@ -82,358 +91,412 @@ for object_type in ["generic", "offer", "loyalty", "giftCard", "eventTicket", "f # Generic ################# -payloads["generic"]["$object_payload"].update({ - "genericType": "GENERIC_TYPE_UNSPECIFIED", - "hexBackgroundColor": "#4285f4", - "logo": { - "sourceUri": { - "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" - } - }, - "cardTitle": { - "defaultValue": { - "language": "en-US", - "value": "Testing Generic Title" - } - }, - "header": { - "defaultValue": { - "language": "en-US", - "value": "Testing Generic Header" - } - }, - "subheader": { - "defaultValue": { - "language": "en", - "value": "Testing Generic Sub Header" - } - }, -}) +payloads["generic"]["$object_payload"].update( + { + "genericType": "GENERIC_TYPE_UNSPECIFIED", + "hexBackgroundColor": "#4285f4", + "logo": { + "sourceUri": { + "uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg" + } + }, + "cardTitle": { + "defaultValue": {"language": "en-US", "value": "Testing Generic Title"} + }, + "header": { + "defaultValue": {"language": "en-US", "value": "Testing Generic Header"} + }, + "subheader": { + "defaultValue": {"language": "en", "value": "Testing Generic Sub Header"} + }, + } +) ################# # Offer ################# -payloads["offer"]["$class_payload"].update({ - "provider": "test provider", - "reviewStatus" : "underReview", - "title": "test title", - "redemptionChannel" : "online" -}) +payloads["offer"]["$class_payload"].update( + { + "provider": "test provider", + "reviewStatus": "underReview", + "title": "test title", + "redemptionChannel": "online", + } +) -payloads["offer"]["$object_payload"].update({ - "state" : "active", - "barcode": { - "type": "qrCode", - "value": "Testing Offers QR Code" - }, - "validTimeInterval": { - "kind": "walletobjects#timeInterval", - "start": {"date": "2023-06-12T23:20:50.52Z"}, - "end": {"date": "2023-12-12T23:20:50.52Z"}, - }, - "locations": [{ - "kind": "walletobjects#latLongPoint", - "latitude": 37.424015499999996, - "longitude": -122.09259560000001, - }], -}) +payloads["offer"]["$object_payload"].update( + { + "state": "active", + "barcode": { + "type": "qrCode", + "value": "Testing Offers QR Code" + }, + "validTimeInterval": { + "kind": "walletobjects#timeInterval", + "start": { + "date": "2023-06-12T23:20:50.52Z" + }, + "end": { + "date": "2023-12-12T23:20:50.52Z" + }, + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001, + } + ], + } +) ################# # Loyalty ################# -payloads["loyalty"]["$class_payload"].update({ - "programName": "test program name", - "programLogo": { - "kind": "walletobjects#image", - "sourceUri": { - "kind": "walletobjects#uri", - "uri": "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg", +payloads["loyalty"]["$class_payload"].update( + { + "programName": "test program name", + "programLogo": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg", + }, }, - }, - "reviewStatus": "underReview", -}) + "reviewStatus": "underReview", + } +) -payloads["loyalty"]["$object_payload"].update({ - "state" : "active", - "accountId": "Test account id", - "accountName": "Test account name", - "loyaltyPoints": { - "balance": { - "string": "800" +payloads["loyalty"]["$object_payload"].update( + { + "state": "active", + "accountId": "Test account id", + "accountName": "Test account name", + "loyaltyPoints": { + "balance": {"string": "800"}, + "label": "Points", }, - "label": "Points", - }, - "locations": [{ - "kind": "walletobjects#latLongPoint", - "latitude": 37.424015499999996, - "longitude": -122.09259560000001, - }], -}) + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001, + } + ], + } +) ################# # GiftCard ################# -payloads["giftCard"]["$class_payload"].update({ - "merchantName": "Test merchant name", - "allowMultipleUsersPerObject": "true", - "reviewStatus": "underReview", -}) +payloads["giftCard"]["$class_payload"].update( + { + "merchantName": "Test merchant name", + "allowMultipleUsersPerObject": "true", + "reviewStatus": "underReview", + } +) -payloads["giftCard"]["$object_payload"].update({ - "cardNumber": "Test card number", - "cardPin": "Test card pin", - "balance": { - "kind": "walletobjects#money", - "micros": 20000000, - "currencyCode": "USD", - }, - "balanceUpdateTime": { - "date": "2020-04-12T16:20:50.52Z", - }, - "locations": [{ - "kind": "walletobjects#latLongPoint", - "latitude": 37.424015499999996, - "longitude": -122.09259560000001, - }], -}) +payloads["giftCard"]["$object_payload"].update( + { + "cardNumber": "Test card number", + "cardPin": "Test card pin", + "balance": { + "kind": "walletobjects#money", + "micros": 20000000, + "currencyCode": "USD", + }, + "balanceUpdateTime": { + "date": "2020-04-12T16:20:50.52Z", + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001, + } + ], + } +) ################# # Eventticket ################# -payloads["eventTicket"]["$class_payload"].update({ - "eventName": { - "defaultValue": { - "language": "en-US", - "value": "Test event name", - }, - }, - "reviewStatus": "underReview", -}) +payloads["eventTicket"]["$class_payload"].update( + { + "eventName": { + "defaultValue": { + "language": "en-US", + "value": "Test event name", + }, + }, + "reviewStatus": "underReview", + } +) -payloads["eventTicket"]["$object_payload"].update({ - "state" : "active", - "seatInfo": { - "kind": "walletobjects#eventSeat", - "seat": { - "kind": "walletobjects#localizedString", - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "42", +payloads["eventTicket"]["$object_payload"].update( + { + "state": "active", + "seatInfo": { + "kind": "walletobjects#eventSeat", + "seat": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "42", + }, + }, + "row": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "G3", + }, + }, + "section": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "5", + }, + }, + "gate": { + "kind": "walletobjects#localizedString", + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "A", + }, }, }, - "row": { - "kind": "walletobjects#localizedString", - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "G3", - }, - }, - "section": { - "kind": "walletobjects#localizedString", - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "5", - }, - }, - "gate": { - "kind": "walletobjects#localizedString", - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "A", - }, - }, - }, - "ticketHolderName": "Test ticket holder name", - "ticketNumber": "Test ticket number", - "locations": [{ - "kind": "walletobjects#latLongPoint", - "latitude": 37.424015499999996, - "longitude": -122.09259560000001, - }], -}) + "ticketHolderName": "Test ticket holder name", + "ticketNumber": "Test ticket number", + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001, + } + ], + } +) ################# # Flight ################# -payloads["flight"]["$class_payload"].update({ - "destination": { - "airportIataCode": "SFO", - "gate": "C3", - "terminal": "2", - }, - "flightHeader": { - "carrier": { - "carrierIataCode": "LX", +payloads["flight"]["$class_payload"].update( + { + "destination": { + "airportIataCode": "SFO", + "gate": "C3", + "terminal": "2", }, - "flightNumber": "123", - }, - "origin": { - "airportIataCode": "LAX", - "gate": "A2", - "terminal": "1", - }, - "localScheduledDepartureDateTime" : "2023-07-02T15:30:00", - "reviewStatus": "underReview", -}) + "flightHeader": { + "carrier": { + "carrierIataCode": "LX", + }, + "flightNumber": "123", + }, + "origin": { + "airportIataCode": "LAX", + "gate": "A2", + "terminal": "1", + }, + "localScheduledDepartureDateTime": "2023-07-02T15:30:00", + "reviewStatus": "underReview", + } +) -payloads["flight"]["$object_payload"].update({ - "state": "active", - "passengerName": "Test passenger name", - "reservationInfo": { - "confirmationCode": "Test confirmation code", - }, - "boardingAndSeatingInfo": { - "seatNumber": "42", - "boardingGroup": "B", - }, - "locations": [{ - "kind": "walletobjects#latLongPoint", - "latitude": 37.424015499999996, - "longitude": -122.09259560000001, - }], -}) +payloads["flight"]["$object_payload"].update( + { + "state": "active", + "passengerName": "Test passenger name", + "reservationInfo": { + "confirmationCode": "Test confirmation code", + }, + "boardingAndSeatingInfo": { + "seatNumber": "42", + "boardingGroup": "B", + }, + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001, + } + ], + } +) ################# # Transit ################# -payloads["transit"]["$class_payload"].update({ - "reviewStatus": "underReview", - "transitType": "bus", - "logo": { - "kind": "walletobjects#image", - "sourceUri": { - "kind": "walletobjects#uri", - "uri": "https://live.staticflickr.com/65535/48690277162_cd05f03f4d_o.png", - "description": "Test logo description", - }, - }, -}) - -payloads["transit"]["$object_payload"].update({ - "passengerType": "singlePassenger", - "passengerNames": "Test passenger names", - "ticketLeg": { - "originStationCode": "LA", - "originName": { - "kind": "walletobjects#localizedString", - "translatedValues": [{ - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "Test translated origin name", - }], - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "Test default origin name", +payloads["transit"]["$class_payload"].update( + { + "reviewStatus": "underReview", + "transitType": "bus", + "logo": { + "kind": "walletobjects#image", + "sourceUri": { + "kind": "walletobjects#uri", + "uri": "https://live.staticflickr.com/65535/48690277162_cd05f03f4d_o.png", + "description": "Test logo description", }, }, - "destinationStationCode": "SFO", - "destinationName": { - "kind": "walletobjects#localizedString", - "translatedValues": [{ - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "Test translated destination name", - }], - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "Test default destination name", + } +) + +payloads["transit"]["$object_payload"].update( + { + "passengerType": "singlePassenger", + "passengerNames": "Test passenger names", + "ticketLeg": { + "originStationCode": "LA", + "originName": { + "kind": "walletobjects#localizedString", + "translatedValues": [ + { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test translated origin name", + } + ], + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test default origin name", + }, + }, + "destinationStationCode": "SFO", + "destinationName": { + "kind": "walletobjects#localizedString", + "translatedValues": [ + { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test translated destination name", + } + ], + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test default destination name", + }, + }, + "departureDateTime": "2020-04-12T16:20:50.52Z", + "arrivalDateTime": "2020-04-12T20:20:50.52Z", + "fareName": { + "kind": "walletobjects#localizedString", + "translatedValues": [ + { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test translated fare name", + } + ], + "defaultValue": { + "kind": "walletobjects#translatedString", + "language": "en-us", + "value": "Test default fare name", + }, }, }, - "departureDateTime": "2020-04-12T16:20:50.52Z", - "arrivalDateTime": "2020-04-12T20:20:50.52Z", - "fareName": { - "kind": "walletobjects#localizedString", - "translatedValues": [{ - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "Test translated fare name", - }], - "defaultValue": { - "kind": "walletobjects#translatedString", - "language": "en-us", - "value": "Test default fare name", - }, - }, - }, - "locations": [{ - "kind": "walletobjects#latLongPoint", - "latitude": 37.424015499999996, - "longitude": -122.09259560000001, - }], -}) + "locations": [ + { + "kind": "walletobjects#latLongPoint", + "latitude": 37.424015499999996, + "longitude": -122.09259560000001, + } + ], + } +) -def indent(s, spaces): - return s.replace("\n", "\n" + (" " * spaces)) -def format_payload_dotnet(payload): - output = [] - payload = (payload - .replace(' "', " ") - .replace('": ', " = ") - .replace(" string = ", ' @string = ') - .replace("]", "}")) - for line in payload.split("\n"): +def indent(text, spaces): + """Enforce spacing/indentation on each new line""" + return text.replace("\n", "\n" + (" " * spaces)) + + +def format_payload_dotnet(unformatted_payload): + """Format JSON payloads for .NET syntax""" + formatted_output = [] + + unformatted_payload = ( + unformatted_payload.replace(' "', " ") + .replace('": ', " = ") + .replace(" string = ", " @string = ") + .replace("]", "}") + ) + + for line in unformatted_payload.split("\n"): _indent = len(line) - len(line.lstrip(" ")) if line.endswith("{"): - line = line[:-1] + "new\n%s{" % (" " * _indent) + line = line[:-1] + f"new\n{' ' * _indent}{{" if line.endswith("["): - line = line[:-1] + "new object[]\n%s{" % (" " * _indent) - output.append(line) - return "\n".join(output) + line = line[:-1] + f"new object[]\n{' ' * _indent}{{" + + formatted_output.append(line) + return "\n".join(formatted_output) + lang_config = { "java": { "ext": "java", "class_id": "%s.%s", "object_id": "%s", - "formatter": lambda s: '\n "' + s.replace('"', '\\"').replace("\n", '"\n + "') + '"', - "filename": lambda s: "src/main/java/Demo%s.java" % s.title(), + "formatter": lambda s: '\n "' + + s.replace('"', '\\"').replace("\n", '"\n + "') + + '"', + "filename": lambda s: f"src/main/java/Demo{s.title()}.java", }, "python": { "ext": "py", - "class_id": '"%s.%s" % (issuer_id, class_id)', - "object_id": "object_id", - "filename": lambda s: "demo_%s.py" % s.lower(), + "class_id": 'f"{ISSUER_ID}.{CLASS_ID}"', + "object_id": "OBJECT_ID", + "filename": lambda s: f"demo_{s.lower()}.py", }, "nodejs": { "ext": "js", "class_id": "`${issuerId}.${classId}`", "object_id": "objectId", "formatter": lambda s: indent(s, 2), - "filename": lambda s: "demo-%s.js" % s.lower(), + "filename": lambda s: f"demo-{s.lower()}.js", }, "php": { "ext": "php", "class_id": '"{$issuerId}.{$classId}"', "object_id": '"{$objectId}"', - "filename": lambda s: "demo_%s.php" % s.lower(), + "filename": lambda s: f"demo_{s.lower()}.php", }, "dotnet": { "ext": "cs", "class_id": '$"{issuerId}.{classId}"', "object_id": "objectId", "formatter": format_payload_dotnet, - "filename": lambda s: "Demo%s.cs.example" % s.title(), - "indent": 4, + "filename": lambda s: f"Demo{s.title()}.cs", + "indent": 2, + }, + "http": { + "ext": "http", + "class_id": "issuer-id.class-id", + "object_id": "issuer-id.user-id", + "filename": lambda s: f"demo_{s.lower()}.http", }, } path = lambda *s: os.path.join(os.path.dirname(os.path.abspath(__file__)), *s) for lang, config in lang_config.items(): - with open(path("template.%s" % config["ext"]), "r") as f: + with open(path(f"template.{config['ext']}"), "r", encoding="utf-8") as f: template = f.read() for object_type, content in payloads.items(): output = template @@ -449,8 +512,10 @@ for lang, config in lang_config.items(): config["object_type"] = object_type config["object_type_titlecase"] = object_type.title() for name in ("object_type_titlecase", "object_type", "class_id", "object_id"): - output = output.replace('"$%s"' % name, config[name]) - output = output.replace('$%s' % name, config[name]) + output = output.replace(f'"${name}"', config[name]) + output = output.replace(f"${name}", config[name]) - with open(path("..", lang, config["filename"](object_type)), "w") as f: + with open( + path("..", lang, config["filename"](object_type)), "w", encoding="utf-8" + ) as f: f.write(output) diff --git a/templates/template.cs b/templates/template.cs index 4b06468..0c32bfd 100644 --- a/templates/template.cs +++ b/templates/template.cs @@ -15,27 +15,46 @@ */ // [START setup] -using Google.Apis.Auth.OAuth2; -using Microsoft.IdentityModel.Tokens; +// [START imports] using System.IdentityModel.Tokens.Jwt; -using System.Net.Http.Json; +using System.Net; using System.Net.Http.Headers; using System.Text.RegularExpressions; +using Google.Apis.Auth.OAuth2; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +string keyFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json"; -// Issuer ID obtained from Google Pay Business Console. -var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? ""; +/* + * issuerId - The issuer ID being used in this request + * - Environment variable: WALLET_ISSUER_ID + */ +string issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "issuer-id"; -// Developer defined ID for the wallet class. -var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-$object_type-class-id"; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +string classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-$object_type-class-id"; -// Developer defined ID for the user, eg an email address. -var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com"; +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +string userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "user-id"; -// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. -var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId); +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ +string objectId = $"{issuerId}.{new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_")}-{classId}"; // [END setup] /////////////////////////////////////////////////////////////////////////////// @@ -43,13 +62,15 @@ var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", Rege /////////////////////////////////////////////////////////////////////////////// // [START auth] -var credentials = (ServiceAccountCredential) GoogleCredential - .FromFile(serviceAccountJson) - .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) - .UnderlyingCredential; +var credentials = (ServiceAccountCredential)GoogleCredential.FromFile(keyFilePath) + .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" }) + .UnderlyingCredential; var httpClient = new HttpClient(); -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync()); +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Bearer", + await credentials.GetAccessTokenForRequestAsync() +); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -57,12 +78,16 @@ httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(" /////////////////////////////////////////////////////////////////////////////// // [START class] -var classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/"; +string classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/"; var classPayload = $class_payload; -var classResponse = await httpClient.PostAsJsonAsync(classUrl, classPayload); -var classContent = await classResponse.Content.ReadAsStringAsync(); -Console.WriteLine("class POST response: " + classContent); +HttpRequestMessage classRequest = new HttpRequestMessage(HttpMethod.Post, classUrl); +classRequest.Content = new StringContent(JsonConvert.SerializeObject(classPayload)); +HttpResponseMessage classResponse = httpClient.Send(classRequest); ; + +string classContent = await classResponse.Content.ReadAsStringAsync(); + +Console.WriteLine($"class POST response: {classContent}"); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -70,16 +95,22 @@ Console.WriteLine("class POST response: " + classContent); /////////////////////////////////////////////////////////////////////////////// // [START object] -var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/"; +string objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/"; var objectPayload = $object_payload; -var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}"); -if ((int) objectResponse.StatusCode == 404) +HttpRequestMessage objectRequest = new HttpRequestMessage(HttpMethod.Get, $"{objectUrl}{objectId}"); +HttpResponseMessage objectResponse = httpClient.Send(objectRequest); +if (objectResponse.StatusCode == HttpStatusCode.NotFound) { - objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload); + // Object does not yet exist + // Send POST request to create it + objectRequest = new HttpRequestMessage(HttpMethod.Post, objectUrl); + objectRequest.Content = new StringContent(JsonConvert.SerializeObject(objectPayload)); + objectResponse = httpClient.Send(objectRequest); } -var objectContent = await objectResponse.Content.ReadAsStringAsync(); -Console.WriteLine("object GET or POST response: " + objectContent); + +string objectContent = await objectResponse.Content.ReadAsStringAsync(); +Console.WriteLine($"object GET or POST response: {objectContent}"); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -87,26 +118,87 @@ Console.WriteLine("object GET or POST response: " + objectContent); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -var claims = new JwtPayload(); -claims.Add("iss", credentials.Id); // `client_email` in service account file. +JwtPayload claims = new JwtPayload(); +claims.Add("iss", credentials.Id); claims.Add("aud", "google"); claims.Add("origins", new string[] { "www.example.com" }); claims.Add("typ", "savetowallet"); claims.Add("payload", new { - $object_typeObjects = new object[] + $object_typeObjects = new object[] + { + new { - new - { - id = $object_id, - }, - }, + id = objectId + } + } }); -var key = new RsaSecurityKey(credentials.Key); -var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); -var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); -var token = new JwtSecurityTokenHandler().WriteToken(jwt); -var saveUrl = $"https://pay.google.com/gp/v/save/{token}"; +RsaSecurityKey key = new RsaSecurityKey(credentials.Key); +SigningCredentials signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256); +JwtSecurityToken jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims); +string token = new JwtSecurityTokenHandler().WriteToken(jwt); +string saveUrl = $"https://pay.google.com/gp/v/save/{token}"; Console.WriteLine(saveUrl); -// [END jwt] \ No newline at end of file +// [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +string issuerName = "name"; + +// New issuer email address +string issuerEmail = "email-address"; + +// Issuer API endpoint +string issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + +// New issuer information +var issuerPayload = new +{ + name = issuerName, + contactInfo = new + { + email = issuerEmail + } +}; + +HttpRequestMessage issuerRequest = new HttpRequestMessage(HttpMethod.Post, issuerUrl); +issuerRequest.Content = new StringContent(JsonConvert.SerializeObject(issuerPayload)); +HttpResponseMessage issuerResponse = httpClient.Send(issuerRequest); + +Console.WriteLine($"issuer POST response: {await issuerResponse.Content.ReadAsStringAsync()}"); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +string permissionsUrl = $"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{issuerId}"; + +// New issuer permissions information +var permissionsPayload = new +{ + issuerId = issuerId, + permissions = new object[] + { + // Copy as needed for each email address that will need access + new + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + } +}; + +HttpRequestMessage permissionsRequest = new HttpRequestMessage(HttpMethod.Put, permissionsUrl); +permissionsRequest.Content = new StringContent(JsonConvert.SerializeObject(permissionsPayload)); +HttpResponseMessage permissionsResponse = httpClient.Send(permissionsRequest); + +Console.WriteLine($"permissions PUT response: {await permissionsResponse.Content.ReadAsStringAsync()}"); +// [END updatePermissions] diff --git a/templates/template.http b/templates/template.http new file mode 100644 index 0000000..ac34a71 --- /dev/null +++ b/templates/template.http @@ -0,0 +1,48 @@ +# [START object] +POST /walletobjects/v1/$object_typeObject HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +$object_payload +# [END object] + +# [START createIssuer] +POST /walletobjects/v1/issuer HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "name": "name", + "contactInfo": { + "email": "email-address" + } +} +# [END createIssuer] + +# [START updatePermissions] +PUT /walletobjects/v1/permissions/issuer-id HTTP/1.1 +Host: walletobjects.googleapis.com +Content-Type: application/json +Authorization: Bearer ; +Accept-Language: en-us +Accept-Encoding: gzip, deflate +Connection: Keep-Alive + +{ + "issuerId": "issuer-id", + "permissions": [ + { + emailAddress = "email-address", + role = "READER | WRITER | OWNER" + } + ] +} +# [END updatePermissions] diff --git a/templates/template.java b/templates/template.java index 69af830..593f981 100644 --- a/templates/template.java +++ b/templates/template.java @@ -15,31 +15,61 @@ */ // [START setup] +// [START imports] import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import okhttp3.*; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.*; +import com.google.api.client.http.json.JsonHttpContent; +import com.google.api.client.json.gson.GsonFactory; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.common.collect.Lists; import java.io.FileInputStream; import java.security.interfaces.RSAPrivateKey; import java.util.*; +// [END imports] public class Demo$object_type_titlecase { public static void main(String[] args) throws Exception { + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + final String keyFilePath = System.getenv().getOrDefault( + "GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json"); - // Path to service account key file obtained from Google CLoud Console. - String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + String issuerId = System.getenv().getOrDefault( + "WALLET_ISSUER_ID", + "issuer-id"); - // Issuer ID obtained from Google Pay Business Console. - String issuerId = System.getenv("WALLET_ISSUER_ID"); + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ + String classId = System.getenv().getOrDefault( + "WALLET_CLASS_ID", + "test-$object_type-class-id"); - // Developer defined ID for the wallet class. - String classId = System.getenv("WALLET_CLASS_ID"); + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + String userId = System.getenv().getOrDefault( + "WALLET_USER_ID", + "user-id"); - // Developer defined ID for the user, eg an email address. - String userId = System.getenv("WALLET_USER_ID"); - - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId); // [END setup] @@ -48,11 +78,12 @@ public class Demo$object_type_titlecase { /////////////////////////////////////////////////////////////////////////////// // [START auth] - GoogleCredential credential = - GoogleCredential.fromStream(new FileInputStream(serviceAccountFile)) - .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer")); - credential.refreshToken(); - OkHttpClient httpClient = new OkHttpClient(); + GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyFilePath)) + .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/wallet_object.issuer")); + credentials.refresh(); + + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory(); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -60,17 +91,17 @@ public class Demo$object_type_titlecase { /////////////////////////////////////////////////////////////////////////////// // [START class] - String classUrl = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/"; + GenericUrl classUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/"); String classPayload = String.format($class_payload, issuerId, classId); - Request.Builder builder = - new Request.Builder() - .url(classUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(classPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - System.out.println("class POST response:" + Objects.requireNonNull(response.body()).string()); - } + HttpRequest classRequest = httpRequestFactory.buildPostRequest( + classUrl, + new JsonHttpContent(new GsonFactory(), classPayload)); + classRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse classResponse = classRequest.execute(); + + System.out.println("class POST response:" + classResponse.parseAsString()); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -78,31 +109,27 @@ public class Demo$object_type_titlecase { /////////////////////////////////////////////////////////////////////////////// // [START object] - String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/"; + GenericUrl objectUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/" + objectId); String objectPayload = String.format($object_payload, objectId, issuerId, classId); - String output = null; - builder = - new Request.Builder() - .url(objectUrl + objectId) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()) - .get(); - try (Response response = httpClient.newCall(builder.build()).execute()) { - if (response.code() != 404) { - output = Objects.requireNonNull(response.body()).string(); - } + HttpRequest objectRequest = httpRequestFactory.buildGetRequest(objectUrl); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse objectResponse = objectRequest.execute(); + + if (objectResponse.getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + objectRequest = httpRequestFactory.buildPostRequest( + objectUrl, + new JsonHttpContent(new GsonFactory(), objectPayload)); + objectRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + objectResponse = objectRequest.execute(); } - if (output == null) { - builder = - new Request.Builder() - .url(objectUrl) - .addHeader("Authorization", "Bearer " + credential.getAccessToken()); - builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8"))); - try (Response response = httpClient.newCall(builder.build()).execute()) { - output = Objects.requireNonNull(response.body()).string(); - } - } - System.out.println("object GET or POST response: " + output); + + System.out.println("object GET or POST response: " + objectResponse.parseAsString()); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -110,25 +137,101 @@ public class Demo$object_type_titlecase { /////////////////////////////////////////////////////////////////////////////// // [START jwt] - Map claims = new HashMap(); - claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file. + HashMap objectIdMap = new HashMap(); + objectIdMap.put("id", objectId); + + HashMap payload = new HashMap(); + payload.put("$object_typeObjects", new ArrayList<>(Arrays.asList(objectIdMap))); + + HashMap claims = new HashMap(); + claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail()); claims.put("aud", "google"); claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com"))); claims.put("typ", "savetowallet"); - - Map payload = new HashMap(); - Map objectIdMap = new HashMap(); - objectIdMap.put("id", objectId); - payload.put("$object_typeObjects", new ArrayList<>(Arrays.asList(objectIdMap))); claims.put("payload", payload); - Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey()); + Algorithm algorithm = Algorithm.RSA256( + null, + (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey()); String token = JWT.create() - .withPayload(claims) - .sign(algorithm); + .withPayload(claims) + .sign(algorithm); String saveUrl = "https://pay.google.com/gp/v/save/" + token; + System.out.println(saveUrl); // [END jwt] + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START createIssuer] + // New issuer name + final String issuerName = "name"; + + // New issuer email address + final String issuerEmail = "email-address"; + + // Issuer API endpoint + GenericUrl issuerUrl = new GenericUrl("https://walletobjects.googleapis.com/walletobjects/v1/issuer"); + + // New issuer information + HashMap issuerPayload = new HashMap() { + { + put("name", issuerName); + put("contactInfo", new HashMap() { + { + put("email", issuerEmail); + } + }); + } + }; + + HttpRequest issuerRequest = httpRequestFactory.buildPostRequest( + issuerUrl, + new JsonHttpContent(new GsonFactory(), issuerPayload)); + issuerRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse issuerResponse = issuerRequest.execute(); + + System.out.println("issuer POST response: " + issuerResponse.parseAsString()); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + GenericUrl permissionsUrl = new GenericUrl( + "https://walletobjects.googleapis.com/walletobjects/v1/permissions/" + issuerId); + + ArrayList> permissions = new ArrayList<>(); + + // Copy as needed for each email address that will need access + permissions.add(new HashMap() { + { + put("emailAddress", "email-address"); + put("role", "READER | WRITER | OWNER"); + } + }); + + // New issuer permissions information + HashMap permissionsPayload = new HashMap() { + { + put("issuerId", issuerId); + put("permissions", permissions); + } + }; + + HttpRequest permissionsRequest = httpRequestFactory.buildPutRequest( + permissionsUrl, + new JsonHttpContent(new GsonFactory(), permissionsPayload)); + permissionsRequest.setHeaders(new HttpHeaders() + .setAuthorization("Bearer " + credentials.getAccessToken().getTokenValue())); + HttpResponse permissionsResponse = permissionsRequest.execute(); + + System.out.println("permissions PUT response: " + permissionsResponse.parseAsString()); + // [END updatePermissions] } } diff --git a/templates/template.js b/templates/template.js index 191c418..0d0b6dc 100644 --- a/templates/template.js +++ b/templates/template.js @@ -17,22 +17,40 @@ async function main() { // [START setup] + // [START imports] const { GoogleAuth } = require('google-auth-library'); const jwt = require('jsonwebtoken'); + // [END imports] - // Path to service account key file obtained from Google CLoud Console. - const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; + /* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ + const keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json'; - // Issuer ID obtained from Google Pay Business Console. - const issuerId = process.env.WALLET_ISSUER_ID || ''; + /* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ + const issuerId = process.env.WALLET_ISSUER_ID || 'issuer-id'; - // Developer defined ID for the wallet class. + /* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ const classId = process.env.WALLET_CLASS_ID || 'test-$object_type-class-id'; - // Developer defined ID for the user, eg an email address. - const userId = process.env.WALLET_USER_ID || 'test@example.com'; + /* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ + const userId = process.env.WALLET_USER_ID || 'user-id'; - // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric. + /* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`; // [END setup] @@ -41,7 +59,8 @@ async function main() { /////////////////////////////////////////////////////////////////////////////// // [START auth] - const credentials = require(serviceAccountFile); + const credentials = require(keyFilePath); + const httpClient = new GoogleAuth({ credentials: credentials, scopes: 'https://www.googleapis.com/auth/wallet_object.issuer' @@ -56,13 +75,13 @@ async function main() { const classUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/'; const classPayload = $class_payload; - let classResponse; - try { - classResponse = await httpClient.request({url: classUrl, method: 'POST', data: classPayload}); - } catch (err) { - classResponse = err; - } - console.log('class POST response:', classResponse); + let classResponse = await httpClient.request({ + url: classUrl, + method: 'POST', + data: classPayload + }); + + console.log('class POST response: ', classResponse); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -73,17 +92,26 @@ async function main() { const objectUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/'; const objectPayload = $object_payload; - // Retrieve the object, or create it if it doesn't exist. let objectResponse; try { - objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'}); + objectResponse = await httpClient.request({ + url: objectUrl + objectId, + method: 'GET' + }); } catch (err) { if (err.response && err.response.status === 404) { - objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload}); + // Object does not yet exist + // Send POST request to create it + objectResponse = await httpClient.request({ + url: objectUrl, + method: 'POST', + data: objectPayload + }); } else { objectResponse = err; } } + console.log('object GET or POST response:', objectResponse); // [END object] @@ -93,20 +121,80 @@ async function main() { // [START jwt] const claims = { - iss: credentials.client_email, // `client_email` in service account file. + iss: credentials.client_email, aud: 'google', origins: ['www.example.com'], typ: 'savetowallet', payload: { - $object_typeObjects: [{id: $object_id}], - }, + $object_typeObjects: [{ + id: $object_id + }], + } }; - const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'}); + const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' }); const saveUrl = `https://pay.google.com/gp/v/save/${token}`; + console.log(saveUrl); // [END jwt] -}; + /////////////////////////////////////////////////////////////////////////////// + // Create a new Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// -main().catch(console.error); \ No newline at end of file + // [START createIssuer] + // New issuer name + const issuerName = "name"; + + // New issuer email address + const issuerEmail = "email-address"; + + // Issuer API endpoint + const issuerUrl = "https://walletobjects.googleapis.com/walletobjects/v1/issuer"; + + // New issuer information + let issuerPayload = { + name: issuerName, + contactInfo: { + email: issuerEmail + } + }; + + let issuerResponse = await httpClient.request({ + url: issuerUrl, + method: 'POST', + data: issuerPayload + }); + + console.log('issuer POST response:', issuerResponse); + // [END createIssuer] + + /////////////////////////////////////////////////////////////////////////////// + // Update permissions for an existing Google Wallet issuer account + /////////////////////////////////////////////////////////////////////////////// + + // [START updatePermissions] + // Permissions API endpoint + permissionsUrl = `https://walletobjects.googleapis.com/walletobjects/v1/permissions/${issuerId}`; + + // New issuer permissions information + permissionsPayload = { + issuerId: issuerId, + permissions: [ + // Copy as needed for each email address that will need access + { + emailAddress: "email-address", + role: "READER | WRITER | OWNER" + } + ] + }; + + let permissionsResponse = await httpClient.request({ + url: permissionsUrl, + method: 'PUT', + data: permissionsPayload + }); + + console.log('permissions PUT response:', permissionsResponse); + // [END updatePermissions] +}; diff --git a/templates/template.php b/templates/template.php index 32eed72..bab4ade 100644 --- a/templates/template.php +++ b/templates/template.php @@ -18,26 +18,45 @@ require __DIR__ . '/vendor/autoload.php'; // [START setup] +// [START imports] use Firebase\JWT\JWT; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Middleware\AuthTokenMiddleware; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Exception\ClientException; +// [END imports] -// Path to service account key file obtained from Google CLoud Console. -$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Issuer ID obtained from Google Pay Business Console. -$issuerId = getenv('WALLET_ISSUER_ID') ?: ''; +/* + * keyFilePath - Path to service account key file from Google Cloud Console + * - Environment variable: GOOGLE_APPLICATION_CREDENTIALS + */ +$keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json'; -// Developer defined ID for the wallet class. -$classId = getenv('WALLET_CLASS_ID') ?: "test-$object_type-class-id"; +/* + * issuerId - The issuer ID being updated in this request + * - Environment variable: WALLET_ISSUER_ID + */ +$issuerId = getenv('WALLET_ISSUER_ID') ?: 'issuer-id'; -// Developer defined ID for the user, eg an email address. -$userId = getenv('WALLET_USER_ID') ?: 'test@example.com'; +/* + * classId - Developer-defined ID for the wallet class + * - Environment variable: WALLET_CLASS_ID + */ +$classId = getenv('WALLET_CLASS_ID') ?: 'test-$object_type-class-id'; -// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. +/* + * userId - Developer-defined ID for the user, such as an email address + * - Environment variable: WALLET_USER_ID + */ +$userId = getenv('WALLET_USER_ID') ?: 'user-id'; + +/* + * objectId - ID for the wallet object + * - Format: `issuerId.userId` + * - Should only include alphanumeric characters, '.', '_', or '-' + */ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}"; // [END setup] @@ -46,11 +65,18 @@ $objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$clas /////////////////////////////////////////////////////////////////////////////// // [START auth] -$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile); -$middleware = new AuthTokenMiddleware($credentials); +$credentials = new ServiceAccountCredentials( + 'https://www.googleapis.com/auth/wallet_object.issuer', + $keyFilePath +); + +$middleware = new AuthTokenMiddleware($credentials); $stack = HandlerStack::create(); $stack->push($middleware); -$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']); +$httpClient = new Client([ + 'handler' => $stack, + 'auth' => 'google_auth' +]); // [END auth] /////////////////////////////////////////////////////////////////////////////// @@ -63,12 +89,12 @@ $classPayload = <<post($classUrl, ['json' => json_decode($classPayload)]); -} catch (ClientException $e) { - $classResponse = $e->getResponse(); -} -echo "class POST response: " . $classResponse->getBody(); +$classResponse = $httpClient->post( + $classUrl, + ['json' => json_decode($classPayload)] +); + +echo 'class POST response: ' . $classResponse->getBody(); // [END class] /////////////////////////////////////////////////////////////////////////////// @@ -81,16 +107,20 @@ $objectPayload = <<get($objectUrl . $objectId); -} catch (ClientException $e) { - $objectResponse = $e->getResponse(); - if ($objectResponse->getStatusCode() == 404) { - $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]); +} catch (ClientException $err) { + if ($err->getResponse()->getStatusCode() == 404) { + // Object does not yet exist + // Send POST request to create it + $objectResponse = $httpClient->post( + $objectUrl, + ['json' => json_decode($objectPayload)] + ); } } -echo "object GET or POST response: " . $objectResponse->getBody(); + +echo 'object GET or POST response: ' . $objectResponse->getBody(); // [END object] /////////////////////////////////////////////////////////////////////////////// @@ -98,16 +128,84 @@ echo "object GET or POST response: " . $objectResponse->getBody(); /////////////////////////////////////////////////////////////////////////////// // [START jwt] -$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true); +$serviceAccount = json_decode(file_get_contents($keyFilePath), true); $claims = [ 'iss' => $serviceAccount['client_email'], 'aud' => 'google', 'origins' => ['www.example.com'], 'typ' => 'savetowallet', - 'payload' => ['$object_typeObjects' => [['id' => $objectId]]] + 'payload' => [ + '$object_typeObjects' => [ + ['id' => $objectId] + ] + ] ]; $token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256'); $saveUrl = "https://pay.google.com/gp/v/save/${token}"; + echo $saveUrl; // [END jwt] + +/////////////////////////////////////////////////////////////////////////////// +// Create a new Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START createIssuer] +// New issuer name +$issuerName = 'name'; + +// New issuer email address +$issuerEmail = 'email-address'; + +// Issuer API endpoint +$issuerUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/issuer'; + +// New issuer information +$issuerPayload = <<post( + $issuerUrl, + ['json' => json_decode($issuerPayload)] +); + +echo 'issuer POST response: ' . $issuerResponse->getBody(); +// [END createIssuer] + +/////////////////////////////////////////////////////////////////////////////// +// Update permissions for an existing Google Wallet issuer account +/////////////////////////////////////////////////////////////////////////////// + +// [START updatePermissions] +// Permissions API endpoint +$permissionsUrl = "https://walletobjects.googleapis.com/walletobjects/v1/permissions/{$issuerId}"; + +// New issuer permissions information +// Copy objects in permissions as needed for each email that will need access +$permissionsPayload = <<put( + $permissionsUrl, + ['json' => json_decode($permissionsPayload)] +); + +echo 'permissions PUT response: ' . $permissionsResponse->getBody(); +// [END updatePermissions] diff --git a/templates/template.py b/templates/template.py index c021f70..8fb7611 100644 --- a/templates/template.py +++ b/templates/template.py @@ -16,26 +16,36 @@ # # [START setup] -import os, re, datetime +# [START imports] +import os +import re from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account from google.auth import jwt, crypt +# [END imports] -# Path to service account key file obtained from Google CLoud Console. -service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json") +# KEY_FILE_PATH - Path to service account key file from Google Cloud Console +# - Environment variable: GOOGLE_APPLICATION_CREDENTIALS +KEY_FILE_PATH = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", + "/path/to/key.json") -# Issuer ID obtained from Google Pay Business Console. -issuer_id = os.environ.get("WALLET_ISSUER_ID", "") +# ISSUER_ID - The issuer ID being updated in this request +# - Environment variable: WALLET_ISSUER_ID +ISSUER_ID = os.environ.get("WALLET_ISSUER_ID", "issuer-id") -# Developer defined ID for the wallet class. -class_id = os.environ.get("WALLET_CLASS_ID", "test-$object_type-class-id") +# CLASS_ID - Developer-defined ID for the wallet class +# - Environment variable: WALLET_CLASS_ID +CLASS_ID = os.environ.get("WALLET_CLASS_ID", "test-$object_type-class-id") -# Developer defined ID for the user, eg an email address. -user_id = os.environ.get("WALLET_USER_ID", "test@example.com") +# USER_ID - Developer-defined ID for the user, such as an email address +# - Environment variable: WALLET_USER_ID +USER_ID = os.environ.get("WALLET_USER_ID", "test@example.com") -# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric. -object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) +# objectId - ID for the wallet object +# - Format: `issuerId.userId` +# - Should only include alphanumeric characters, '.', '_', or '-' +OBJECT_ID = "%s.%s-%s" % (ISSUER_ID, re.sub(r"[^\w.-]", "_", USER_ID), CLASS_ID) # [END setup] ############################################################################### @@ -43,8 +53,10 @@ object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id) ############################################################################### # [START auth] -credentials = service_account.Credentials.from_service_account_file(service_account_file, +credentials = service_account.Credentials.from_service_account_file( + KEY_FILE_PATH, scopes=["https://www.googleapis.com/auth/wallet_object.issuer"]) + http_client = AuthorizedSession(credentials) # [END auth] @@ -53,11 +65,14 @@ http_client = AuthorizedSession(credentials) ############################################################################### # [START class] -class_url = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/" +CLASS_URL = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeClass/" class_payload = $class_payload -class_response = http_client.post(class_url, json=class_payload) -print("class POST response:", class_response.text) +class_response = http_client.post( + CLASS_URL, + json=class_payload +) +print("class POST response: ", class_response.text) # [END class] ############################################################################### @@ -65,13 +80,18 @@ print("class POST response:", class_response.text) ############################################################################### # [START object] -object_url = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/" +OBJECT_URL = "https://walletobjects.googleapis.com/walletobjects/v1/$object_typeObject/" object_payload = $object_payload -# Retrieve the object, or create it if it doesn't exist. -object_response = http_client.get(object_url + object_id) +object_response = http_client.get(OBJECT_URL + OBJECT_ID) if object_response.status_code == 404: - object_response = http_client.post(object_url, json=object_payload) + # Object does not yet exist + # Send POST request to create it + object_response = http_client.post( + OBJECT_URL, + json=object_payload + ) + print("object GET or POST response:", object_response.text) # [END object] @@ -81,17 +101,81 @@ print("object GET or POST response:", object_response.text) # [START jwt] claims = { - "iss": http_client.credentials.service_account_email, # `client_email` in service account file. + "iss": http_client.credentials.service_account_email, "aud": "google", "origins": ["www.example.com"], "typ": "savetowallet", "payload": { - "$object_typeObjects": [{"id": object_id}] + "$object_typeObjects": [ + { + "id": OBJECT_ID + } + ] } } -signer = crypt.RSASigner.from_service_account_file(service_account_file) +signer = crypt.RSASigner.from_service_account_file(KEY_FILE_PATH) token = jwt.encode(signer, claims).decode("utf-8") -save_url = "https://pay.google.com/gp/v/save/%s" % token +save_url = f"https://pay.google.com/gp/v/save/{token}" + print(save_url) # [END jwt] + +############################################################################### +# Create a new Google Wallet issuer account +############################################################################### + +# [START createIssuer] +# New issuer name +ISSUER_NAME = "name" + +# New issuer email address +ISSUER_EMAIL = "email-address" + +# Issuer API endpoint +ISSUER_URL = "https://walletobjects.googleapis.com/walletobjects/v1/issuer" + +# New issuer information +issuer_payload = { + "name": ISSUER_NAME, + "contactInfo": { + "email": ISSUER_EMAIL + } +} + +# Make the POST request +issuer_response = http_client.post( + url=ISSUER_URL, + json=issuer_payload +) + +print("issuer POST response:", issuer_response.text) +# [END createIssuer] + +############################################################################### +# Update permissions for an existing Google Wallet issuer account +############################################################################### + +# [START updatePermissions] +# Permissions API endpoint +permissions_url = f"https://walletobjects.googleapis.com/walletobjects/v1/permissions/{ISSUER_ID}" + +# New issuer permissions information +permissions_payload = { + "issuerId": ISSUER_ID, + "permissions": [ + # Copy as needed for each email address that will need access + { + "emailAddress": "email-address", + "role": "READER | WRITER | OWNER" + }, + ] +} + +permissions_response = http_client.put( + permissions_url, + json=permissions_payload +) + +print("permissions PUT response:", permissions_response.text) +# [END updatePermissions]