Przypadki użycia są takie same we wszystkich kategoriach kart. Na przykład wszystkie karty lojalnościowe, karty podarunkowe, oferty specjalne, bilety na wydarzenia, lotnicze karty pokładowe i bilety na przejazdy można dodać do aplikacji Google Pay na kilka sposobów. Aby dowiedzieć się więcej, wybierz jedną z tych metod:
Z aplikacji na Androida
Aby dodać przycisk Zapisz w Google Pay do aplikacji na Androida, zastosuj jedną z tych metod:
- Użycie pakietu SDK na Androida
- Użycie linku JWT i metody intencji
- Użycie metody żądania POST tokena JWT
Użycie pakietu SDK na Androida
Interfejs Android API umożliwia zapisywanie kart w Google Pay. Integracja przycisku Zapisz w Google Pay z Twoją aplikacją ułatwia klientom zapisywanie kart w Google Pay.
Aby dodać przycisk Zapisz w Google Pay dla karty lojalnościowej, wykonaj te czynności. Pamiętaj jednak, że proces dodawania wygląda tak samo w przypadku wszystkich kart.
1. Utwórz klasę
Najpierw określ LoyaltyClass
. Poniższy przykład przedstawia zasób JSON reprezentujący LoyaltyClass
:
{ "accountIdLabel": "Member Id", "accountNameLabel": "Member Name", "id": "2945482443380251551.ExampleClass1", "issuerName": "Baconrista", "kind": "walletobjects#loyaltyClass", "textModulesData": [ { "header": "Rewards details", "body": "Welcome to Baconrista rewards. Enjoy your rewards for being a loyal customer. " + "10 points for every dollar spent. Redeem your points for free coffee, bacon and more!" } ], "linksModuleData": { "uris": [ { "kind": "walletobjects#uri", "uri": "https://maps.google.com/map?q=google", "description": "Nearby Locations" }, { "kind": "walletobjects#uri", "uri": "tel:6505555555", "description": "Call Customer Service" } ] }, "imageModulesData": [ { "mainImage": { "kind": "walletobjects#image", "sourceUri": { "kind": "walletobjects#uri", "uri": "https://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg", "description": "Coffee beans" } } } ], "messages": [{ "header": "Welcome to Banconrista Rewards!", "body": "Featuring our new bacon donuts.", "kind": "walletobjects#walletObjectMessage" }], "locations": [{ "kind": "walletobjects#latLongPoint", "latitude": 37.424015499999996, "longitude": -122.09259560000001 },{ "kind": "walletobjects#latLongPoint", "latitude": 37.424354, "longitude": -122.09508869999999 },{ "kind": "walletobjects#latLongPoint", "latitude": 37.7901435, "longitude": -122.39026709999997 },{ "kind": "walletobjects#latLongPoint", "latitude": 40.7406578, "longitude": -74.00208940000002 }], "programLogo": { "kind": "walletobjects#image", "sourceUri": { "kind": "walletobjects#uri", "uri": "https://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg" } }, "programName": "Baconrista Rewards", "rewardsTier": "Gold", "rewardsTierLabel": "Tier", "reviewStatus": "underReview", "hexBackgroundColor": "#ffffff", "heroImage": { "kind": "walletobjects#image", "sourceUri": { "kind": "walletobjects#uri", "uri": "https://farm8.staticflickr.com/7302/11177240353_115daa5729_o.jpg" } } }
2. Utwórz obiekt
Po utworzeniu klasy zajęć zdefiniuj LoyaltyObject
zgodnie z tym fragmentem:
{ "classId": "2945482443380251551.ExampleClass1", "id": "2945482443380251551.ExampleObject1", "accountId": "1234567890", "accountName": "Jane Doe", "barcode": { "alternateText": "12345", "type": "qrCode", "value": "28343E3" }, "textModulesData": [{ "header": "Jane's Baconrista Rewards", "body": "Save more at your local Mountain View store Jane. " + "You get 1 bacon fat latte for every 5 coffees purchased. " + "Also just for you, 10% off all pastries in the Mountain View store." }], "linksModuleData": { "uris": [ { "kind": "walletobjects#uri", "uri": "https://www.baconrista.com/myaccount?id=1234567890", "description": "My Baconrista Account" }] }, "infoModuleData": { "labelValueRows": [{ "columns": [{ "label": "Next Reward in", "value": "2 coffees" }, { "label": "Member Since", "value": "01/15/2013" }] }, { "columns": [{ "label": "Local Store", "value": "Mountain View" }] }], "showLastUpdateTime": "true" }, "loyaltyPoints": { "balance": { "string": "5000" }, "label": "Points", "pointsType": "points" }, "messages": [{ "header": "Jane, welcome to Banconrista Rewards!", "body": "Thanks for joining our program. Show this message to " + "our barista for your first free coffee on us!" }], "state": "active" }
3. Zakoduj nieprzypisany token JWT
Po utworzeniu obiektu zakoduj LoyaltyClass
i LoyaltyObject
do nieprzypisanego tokena JWT zgodnie z tym fragmentem:
{ "iss": "example_service_account@developer.gserviceaccount.com", "aud": "google", "typ": "savetoandroidpay", "iat": 1368029586, "payload": { "eventTicketClasses": [{ ... //Event ticket Class JSON }], "eventTicketObjects": [{ ... //Event ticket Object JSON }], "flightClasses": [{ ... //Flight Class JSON }], "flightObjects": [{ ... //Flight Object JSON }], "giftCardClasses": [{ ... //Gift card Class JSON }], "giftCardObjects": [{ ... //Gift card Object JSON }], "loyaltyClasses": [{ ... //Loyalty Class JSON }], "loyaltyObjects": [{ ... //Loyalty Object JSON }], "offerClasses": [{ ... //Offer Class JSON }], "offerObjects": [{ ... //Offer Object JSON }], "transitClasses": [{ ... //Transit Class JSON }], "transitObjects": [{ ... //Transit Object JSON }] }, "origins": ["http://baconrista.com", "https://baconrista.com"] }
4. Wybierz format żądania, którego chcesz użyć
Pakiet Android SDK pozwala wysyłać żądania w jednym z tych formatów:
- Metoda
savePasses
wykorzystuje ładunek ciągu JSON. - Metoda
savePassesJwt
wykorzystuje ładunek tokena ciągu JSON.
Więcej informacji o tym, jak przesłać żądanie, znajdziesz w artykule Wywołanie pakietu Android SDK.
savePasses
Żądania wysyłane do metody savePasses
mają ładunek ciągu JSON. Oznacza to, że możesz bezpośrednio użyć JSON dla obiektu utworzonego w kroku 3.
Możesz wysyłać żądania Zapisz w Google Pay dla istniejących klas i obiektów lub takich, które są częścią procesu zapisywania. Możesz też zapisać wiele kart w tym samym żądaniu, jeśli kategoria karty obsługuje tę funkcję. Nie możesz aktualizować ani dodawać istniejących klas i obiektów.
Ze względów bezpieczeństwa niektóre pola są uznawane za wrażliwe. W takich przypadkach nie możesz zapisać istniejących kart jedynie przez określenie pola identyfikatora obiektu. Możesz zapisywać obiekty, które już istnieją, tylko wtedy, gdy wrażliwe pola w żądaniu są zgodne z polami istniejących obiektów. Te pola są uznawane za wrażliwe:
object.barcode.value
object.smartTapRedemptionValue
savePassesJwt
Żądania wysyłane do metody savePassesJwt
mają ładunek tokena ciągu JWT. Aby utworzyć token JWT, podpisz obiekt z kroku 3 przy użyciu prywatnego klucza konta usługi OAuth 2.0. Poniżej znajdziesz fragmenty pokazujące, jak zakodować token JWT w różnych językach:
Java
WobCredentials credentials = null; WobUtils utils = null; // Instantiate the WobUtils class which contains handy functions // Wob utils can be found in the quickstart sample try { credentials = new WobCredentials( ServiceAccountEmailAddress, ServiceAccountPrivateKeyPath, ApplicationName, IssuerId); utils = new WobUtils(credentials); } catch (GeneralSecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // Add valid domains for the Save to Wallet button List<String> origins = new ArrayList<String>(); origins.add("http://baconrista.com"); origins.add("https://baconrista.com"); origins.add(req.getScheme() + "://" + req.getServerName() + ":" + req.getLocalPort()); //Generate Objects and Classes here //........ WobPayload payload = new WobPayload(); payload.addObject({WalletObject/WalletClass}); // Convert the object into a Save to Android Pay Jwt String jwt = null; try { jwt = utils.generateSaveJwt(payload, origins); } catch (SignatureException e) { e.printStackTrace(); }
PHP
$requestBody = [ "iss"=> SERVICE_ACCOUNT_EMAIL_ADDRESS, "aud" => "google", "typ" => "savetoandroidpay", "iat"=> time(), "payload" => { "eventTicketClasses" => [ ], # Event ticket classes "eventTicketObjects" => [ ], # Event ticket objects "flightClasses" => [ ], # Flight classes "flightObjects" => [ ], # Flight objects "giftCardClasses" => [ ], # Gift card classes "giftCardObjects" => [ ], # Gift card objects "loyaltyClasses" => [ ], # Loyalty classes "loyaltyObjects" => [ ], # Loyalty objects "offerClasses" => [ ], # Offer classes "offerObjects" => [ ], # Offer objects "transitClasses" => [ ], # Transit classes "transitObjects" => [ ] # Transit objects }, "origins" => ["http://baconrista.com", "https://baconrista.com"] ] // Generate the Save to Android Pay Jwt echo $jwt = $assertObj->makeSignedJwt($requestBody, $client);
Python
jwt = { 'iss': config.SERVICE_ACCOUNT_EMAIL_ADDRESS, 'aud': 'google', 'typ': 'savetoandroidpay', 'iat': int(time.time()), 'payload': { 'webserviceResponse': { 'result': 'approved', 'message': 'Success.' }, 'eventTicketClasses': [], # Event ticket classes 'eventTicketObjects': [], # Event ticket objects 'flightClasses': [], # Flight classes 'flightObjects': [], # Flight objects 'giftCardClasses': [], # Gift card classes 'giftCardObjects': [], # Gift card objects 'loyaltyClasses': [], # Loyalty classes 'loyaltyObjects': [], # Loyalty objects 'offerClasses': [], # Offer classes 'offerObjects': [], # Offer objects 'transitClasses': [], # Transit classes 'transitObjects': [] # Transit objects }, 'origins' : ['http://baconrista.com', 'https://baconrista.com'] } // Generate the Save to Android Pay Jwt signer = crypt.Signer.from_string(app_key) signed_jwt = crypt.make_signed_jwt(signer, jwt) response = webapp2.Response(signed_jwt)
Możesz wysyłać żądania Zapisz w Google Pay dla istniejących klas i obiektów lub takich, które są częścią procesu zapisywania. Możesz też zapisać wiele kart w tym samym żądaniu, jeśli kategoria karty obsługuje tę funkcję. Nie możesz aktualizować ani dodawać istniejących klas i obiektów. Skróconych tokenów JWT można używać w przypadku istniejących klas i obiektów.
5. Wywołaj pakiet Android SDK
Najpierw użyj metody getPayApiAvailabilityStatus
, by sprawdzić, czy są dostępne metody savePasses
i savePassesJwt
, jak pokazano w poniższym przykładzie:
import com.google.android.gms.common.api.UnsupportedApiCallException; import com.google.android.gms.pay.Pay; import com.google.android.gms.pay.PayApiAvailabilityStatus; import com.google.android.gms.pay.PayClient; … PayClient payClient = Pay.getClient(this); payClient // Use PayClient.RequestType.SAVE_PASSES_JWT for the savePassesJwt API .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES) .addOnSuccessListener( status -> { switch (status) { case PayApiAvailabilityStatus.AVAILABLE: // You can call the savePasses API or savePassesJwt API ... break; case PayApiAvailabilityStatus.NOT_ELIGIBLE: default: // We recommend to either: // 1) Hide the save button // 2) Fall back to a different Save Passes integration (e.g. JWT link) // Note however that the user *will* only be able to access their // passes on web // A not eligible user might become eligible in the future. ... break; } }) .addOnFailureListener( exception -> { if (exception instanceof UnsupportedApiCallException) { // Google Play Services too old. We could not check API availability or // user eligibility. We recommend to either: // 1) Fall back to a different Save Passes integration (e.g. JWT link) // Note however that the user *may* only be able to access their // passes on web // 2) Hide the save button ... } else { // Very old version of Google Play Services or unexpected error! ... } });
Jeśli interfejs API jest dostępny, wywołaj metodę savePasses
lub savePassesJwt
, gdy użytkownik kliknie przycisk Zapisz w Google Pay.
savePasses
private static final int SAVE_TO_GOOGLE_PAY = 1000; … String jsonString = … // Build or fetch JSON request PayClient payClient = Pay.getClient(this); payClient.savePasses(jsonString, this, SAVE_TO_GOOGLE_PAY);
savePassesJwt
private static final int SAVE_TO_GOOGLE_PAY = 1000; … String jwtString = … // Fetch JWT from a secure server PayClient payClient = Pay.getClient(this); payClient.savePassesJwt(jwtString, this, SAVE_TO_GOOGLE_PAY);
To wywołanie uruchamia proces zapisywania. Po zakończeniu procesu Twoja aplikacja wyświetli wynik w onActivityResult
. W działaniu odbiorca musi być zdefiniowany w podobny sposób:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // `data` will only have information in the `SAVE_ERROR` case if (requestCode == SAVE_TO_GOOGLE_PAY) { switch (resultCode) { case Activity.RESULT_OK: // Save successful ... break; case Activity.RESULT_CANCELED: // Save canceled ... break; case PayClient.SavePassesResult.API_ERROR: // API error - this should not happen if getPayApiAvailabilityStatus is // used correctly ... break; case PayClient.SavePassesResult.SAVE_ERROR: // Save error - check EXTRA_API_ERROR_MESSAGE to debug the issue // Most save errors indicate an error in the app fingerprint or the Json // request payload. In most cases prompting the user to try again will not // help. if (data != null && !isEmpty(data.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE))) { ... } else { // Unexpected! A save error should always have a debug message associated // with it ... } break; case PayClient.SavePassesResult.INTERNAL_ERROR: default: // Internal error - prompt the user to try again, if the error persists // disable the button ... break; } } else { ... } }
6. Dodaj przycisk Zapisz w Google Pay do UI
W pakiecie Android SDK dostępny jest przycisk Google Pay, który można zintegrować z aplikacją. Zasoby przycisku znajdziesz we wskazówkach dotyczących marki.
Ten pakiet narzędzi zawiera obrazy wektorowe przycisków.
Aby dodać przycisk do swojej aplikacji, skopiuj jego obraz z pakietu narzędzi do folderu res
aplikacji i dodaj podany poniżej kod do pliku układu na Androida. Każdy przycisk musi mieć unikalny ciąg znaków contentDescription
, wartość minWidth
i poprawną wartość src
.
<ImageButton android:layout_width="match_parent" android:layout_height="48dp" android:minWidth="200dp" android:clickable="true" android:src="@drawable/s2ap" />
Parametr layout_height
przycisku to 48 dp. Parametr minWidth
musi mieć wartość 200 dp.
Użycie linku JWT i metody intencji
Aby zapisać kartę w Google Pay z aplikacji, wykonaj te czynności:
- Wykonaj czynności opisane w artykule na temat dodawania przycisku Zapisz w Google Pay do e-maila lub SMS-a.
Otwórz precyzyjny link z przycisku Zapisz w Google Pay za pomocą intencji
ACTION_VIEW
.Przycisk wyświetlający intencję musi być zgodny ze wskazówkami dotyczącymi marki.
Oto przykładowe podsumowanie przepływu:
- Zanim zostanie zapisana karta, w backendzie tworzona jest klasa za pomocą interfejsu API REST.
- Kiedy użytkownik chce zapisać kartę, backend serwera wysyła token
JWT
, który reprezentuje obiekt, do klienckiej aplikacji na Androida. - Kliencka aplikacja na Androida zawiera przycisk Zapisz w Google Pay, który jest zgodny ze wskazówkami dotyczącymi marki.
Kliknięcie go otwiera intencję
ACTION_VIEW
kierującą do identyfikatora URI, którego ścieżka zawiera token JWT. Oto przykład:https://pay.google.com/gp/v/save/{jwt_generated}
Użycie metody żądania POST tokena JWT
Metoda żądania POST
tokena JWT pozwala w inny sposób tworzyć klasy i obiekty do aplikacji na Androida dla lotów lub biletów na wydarzenia. Używa się jej, gdy trudno jest wdrożyć backend wymagany do utworzenia i wstawienia klasy przed zapisem obiektu. Ta metoda najlepiej sprawdza się przy biletach na wydarzenia i kartach pokładowych, ponieważ dla tych kart można tworzyć wiele klas. Przepływ ten wygląda tak:
- Gdy użytkownik dokonuje odprawy przed lotem lub wykorzystuje bilet na wydarzenie, backend serwera renderuje w klienckiej aplikacji na Androida token JWT, który zawiera klasę oraz obiekt.
- Kliencka aplikacja na Androida zawiera przycisk Zapisz w Google, który jest zgodny ze wskazówkami dotyczącymi marki. Gdy go klikniesz:
- Żądanie
POST
wyśle token JWT przez HTTPS do punktu końcowego Google. - Zwrócony zostanie identyfikator URI z odpowiedzi HTTP, za pomocą którego należy otworzyć intencję
ACTION_VIEW
.
Metoda żądania POST
tokena JWT wymaga również klucza interfejsu API. Jest on dołączany jako parametr zapytania do wywołania interfejsu API REST.
Tworzenie klasy
Nowa klasa tworzy się w naszym backendzie tylko po przedstawieniu identyfikatora class.id
, który nie został wcześniej zapisany. Można więc przekazać dane klasy do Google za pomocą tokena JWT, ale backend wykrywa, że klasa jest już zapisana, i nie tworzy nowych klas po każdym zapisaniu karty pokładowej.
Aktualizacje klasy
Po utworzeniu pierwszej karty pokładowej razem z klasą jest zapisywany obiekt. Możesz normalnie używać class.id
w interfejsie API REST, aby wykonywać operacje ADDMESSAGE
, GET
, LIST
, PATCH
i UPDATE
.
Aby zmienić dane klasy, musisz użyć interfejsu API aktualizacji klasy. Jeśli utworzysz klasę z class.id
=XYZ i innymi informacjami, a później spróbujesz utworzyć klasę z class.id
=XYZ i zmienionymi danymi klasy, zachowamy pierwszą klasę i nie wprowadzimy żadnych zmian.
Format tokena JWT
Format wysyłanego tokena JWT opisaliśmy dokładnie w dokumentacji tokenów JWT Google Pay API for Passes.
Ten payload
przekazuje 1 wpis obiektów (odpowiada obiektowi, który chcesz utworzyć) i 1 wpis klas (zawiera utworzoną klasę).
Żądanie HTTP
Za pomocą metody INSERT
można wstawiać klasy i obiekty określone w JWT. Klucz API musi być ustawiony jako parametr zapytania.
Metoda INSERT tokena JWT
Przy podanym tokenie JWT metoda INSERT
wstawia klasy i obiekty podane w tym tokenie. Jeśli operacja się uda, zostanie zwrócona odpowiedź HTTP 200.
Żądanie HTTP
POST https://walletobjects.googleapis.com/walletobjects/v1/jwt/
Autoryzacja
To żądanie nie wymaga autoryzacji. Token JWT musi być podpisany kluczem RSA-SHA256. Klucz podpisywania jest tworzony przez konto usługi OAuth.
Treść żądania
Dane w treści żądania muszą mieć poniższy format:
{ “jwt” : string }
Treść odpowiedzi
Jeśli operacja się uda, metoda zwróci odpowiedź w poniższym formacie:
{ "saveUri": string, "resources": { "eventTicketClasses": [ eventTicketClass resource, ... ], "eventTicketObjects": [ eventTicketObject resource, ... ], "flightClasses": [ flightClass resource, ... ], "flightObjects": [ flightObject resource, ... ], "giftCardClasses": [ giftCardClass resource, ... ], "giftCardObjects": [ giftCardObject resource, ... ], "loyaltyClasses": [ loyaltyClass resource, ... ], "loyaltyObjects": [ loyaltyObject resource, ... ], "offerClasses": [ offerClass resource, ... ], "offerObjects": [ offerObject resource, ... ], "transitClasses": [ transitClass resource, ... ], "transitObjects": [ transitObject resource, ... ] } }
Ciąg saveUri
to identyfikator URI, który po otwarciu pozwala użytkownikowi zapisać obiekty podane w tokenie JWT na jego koncie Google. Jest on ważny tylko przez tydzień po zwróceniu.
Więcej informacji znajdziesz w dokumentacji punktu końcowego JWT.
Diagramy przepływu
Diagramy przepływu znajdziesz w opisie typowych przepływów interfejsu API.