Z tego przewodnika dowiesz się, jak tworzyć projekt w Actions. który do składania rezerwacji używa interfejsu Orders API.
Przepływ transakcji
Gdy projekt w Actions obsługuje rezerwacje, korzysta z takiego procesu:
- Wymagania dotyczące weryfikacji transakcji (opcjonalnie) – użyj asystenta wymagań dotyczących transakcji na początku rozmowy, aby upewnić się, że użytkownik może realizowania transakcji.
- Ustal kolejność – pokaż użytkownikowi „skład koszyka” gdzie podają szczegóły rezerwacji.
- Zaproponuj zamówienie – gdy „koszyk” zakończono, zaproponuj „zamówienie” rezerwacji do użytkownika, aby mógł potwierdzić, że jest poprawny. Jeśli rezerwacja zostanie potwierdzona, otrzyma odpowiedź ze szczegółami rezerwacji.
- Sfinalizuj zamówienie i wyślij potwierdzenie – po potwierdzeniu zamówienia zaktualizuj do systemu rezerwacji i wysłać rachunek po stronie użytkownika.
- Wysyłaj aktualne informacje o zamówieniu – w trakcie okresu ważności rezerwacji aktualizować stan rezerwacji użytkownika, wysyłając żądania PATCH do Orders API.
Ograniczenia i wytyczne dotyczące sprawdzania
Pamiętaj, że w przypadku akcji, które korzystają z transakcji i interfejsu Orders API, obowiązują dodatkowe zasady. Sprawdzanie działań z transakcjami może zająć do 6 tygodni, więc uwzględnij ten czas w planowaniu harmonogramu publikacji. Aby uprościć proces weryfikacji, przed przesłaniem akcji do sprawdzenia upewnij się, że przestrzegasz zasad i wytycznych dotyczących transakcji.
Działania używające interfejsu Orders API możesz wdrażać tylko w tych krajach:
Australia Brazylia Kanada Indonezja, |
Japonia Meksyk Katar Rosja |
Singapur Szwajcaria Tajlandia Turcja Wielka Brytania Stany Zjednoczone |
Kompilowanie projektu
Obszerne przykłady rozmów transakcyjnych znajdziesz w przykładach transakcji w środowiskach Node.js i Java.
Konfigurowanie projektu
Tworząc akcję, musisz określić, że chcesz dokonywać transakcji. w Konsoli działań. Poza tym, jeśli za pomocą biblioteki klienta Node.JS, skonfiguruj realizację tak, aby wykorzystywała korzystając z interfejsu Orders API.
Aby skonfigurować projekt i realizację:
- Utwórz nowy projekt lub zaimportuj istniejący.
- Przejdź do Wdróż > Informacje o katalogu.
W sekcji Dodatkowe informacje > Transakcje > zaznacz pole z napisem „Wykonuj działania”. używać interfejsu Transaction API do przeprowadzania transakcji na towary fizyczne?”.
Jeśli do tworzenia realizacji akcji używasz biblioteki klienta Node.JS, otwórz kod realizacji i zaktualizuj przekazywanie danych aplikacji, aby ustawić flaga
ordersv3
do:true
. Ten fragment kodu pokazuje przykładową aplikację deklaracja dotycząca wersji 3 usługi Orders.
Node.js
const {dialogflow} = require('actions-on-google'); let app = dialogflow({ clientId, // If using account linking debug: true, ordersv3: true, });
Node.js
const {actionssdk} = require('actions-on-google'); let app = actionssdk({ clientId, // If using account linking debug: true, ordersv3: true, });
1. Wymagania dotyczące weryfikacji transakcji (opcjonalne)
Interfejs użytkownika
Gdy tylko użytkownik wskaże, że chce utworzyć rezerwację, zalecamy aktywowanie reguły
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
chce zapewnić tę możliwość
poprosić o rezerwację. Akcja może na przykład zapytać:
„Czy chcesz zarezerwować miejsce?” Jeśli użytkownik mówi
„tak”, zgłoś tę intencję jak najszybciej. Dzięki temu
że można kontynuować i dać mu szansę na poprawienie ustawień,
co uniemożliwia kontynuowanie transakcji.
Wysyłanie próśb o transakcje wymaga sprawdzenia, aby intencje były zgodne z jednym z tych wyników:
- Jeśli wymagania są spełnione, realizacja otrzymuje intencję z atrybutem możesz kontynuować tworzenie zamówienia użytkownika.
Jeśli co najmniej jedno z wymagań nie spełnia tego wymogu, intencję z warunkiem błędu. W takim przypadku zakończ rozmowę lub odejść od procesu rezerwacji.
Jeśli użytkownik może naprawić błąd, zostanie automatycznie poproszony o rozwiązanie problemu. na swoim urządzeniu. czy rozmowa odbywa się na platformie z włączonym głosem; jak inteligentny głośnik – przekaz jest przekazywany na telefon użytkownika.
Realizacja
Aby użytkownicy spełniali
wymagania dotyczące transakcji, żądanie spełnienia
Intencja actions.intent.TRANSACTION_REQUIREMENTS_CHECK
ze
obiektu TransactionRequirementsCheckSpec.
Sprawdź wymagania
Sprawdź, czy użytkownik spełnia wymagania dotyczące rezerwacji w bibliotece klienta:
conv.ask(new TransactionRequirements());
return getResponseBuilder(request) .add("Placeholder for transaction requirements text") .add(new TransactionRequirements()) .build();
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec" } } } } }
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "inputValueData": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec" } } ] } ] }
Otrzymaj wynik kontroli wymagań
Gdy Asystent spełni intencję, wysyła żądanie dotyczące jej realizacji.
z intencją actions.intent.TRANSACTION_REQUIREMENTS_CHECK
i wynikiem
weryfikacji.
Aby prawidłowo obsługiwać to żądanie, zadeklaruj intencję Dialogflow aktywowaną przez
zdarzenie actions_intent_TRANSACTION_REQUIREMENTS_CHECK
. Po uruchomieniu
obsługuj tę intencję w swojej realizacji:
const arg = conv.arguments.get('TRANSACTION_REQUIREMENTS_CHECK_RESULT'); if (arg && arg.resultType === 'CAN_TRANSACT') { // Normally take the user through cart building flow conv.ask(`Looks like you're good to go!`); } else { conv.close('Transaction failed.'); }
Argument transactionCheckResult = request .getArgument("TRANSACTION_REQUIREMENTS_CHECK_RESULT"); boolean result = false; if (transactionCheckResult != null) { Map<String, Object> map = transactionCheckResult.getExtension(); if (map != null) { String resultType = (String) map.get("resultType"); result = resultType != null && resultType.equals("CAN_TRANSACT"); } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (result) { responseBuilder.add("Looks like you're good to go! Now say 'confirm transaction'"); } else { responseBuilder.add("Transaction failed"); } return responseBuilder.build();
Zwróć uwagę, że poniższy kod JSON opisuje żądanie webhooka.
{ "responseId": "", "queryResult": { "queryText": "", "action": "", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "", "fulfillmentMessages": [], "outputContexts": [], "intent": { "name": "reservation_transaction_check_complete_df", "displayName": "reservation_transaction_check_complete_df" }, "intentDetectionConfidence": 1, "diagnosticInfo": {}, "languageCode": "" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "isInSandbox": true, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "inputs": [ { "rawInputs": [], "intent": "", "arguments": [ { "extension": { "@type": "type.googleapis.com/google.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" }, "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT" } ] } ], "user": {}, "conversation": {}, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "" }
Zwróć uwagę, że poniższy kod JSON opisuje żądanie webhooka.
{ "user": {}, "device": {}, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "conversation": {}, "inputs": [ { "rawInputs": [], "intent": "reservation_transaction_check_complete_asdk", "arguments": [ { "extension": { "@type": "type.googleapis.com/google.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" }, "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT" } ] } ], "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
2. Tworzenie zamówienia
Interfejs użytkownika
Po zgromadzeniu potrzebnych informacji o użytkowniku utwórz „koszyk”, montaż” która pomaga użytkownikowi zrobić rezerwację. Co Procedura składania koszyka będzie wyglądał trochę inaczej, zależnie od potrzeb posprzedażna.
W podstawowym procesie składania koszyka użytkownik wybiera z listy opcje, które chce dodać do rezerwacji, chociaż możesz tak zaplanować rozmowę, aby uprościć użytkowników. Stwórz na przykład środowisko składania koszyków, które umożliwia zarezerwowanie miesięcznej rezerwacji, odpowiadając na pytanie typu „tak” lub „nie”. Możesz też pokazać użytkownikowi kartę karuzeli lub z listą „Polecane” rezerwacji.
Zalecamy użycie formatu multimedialnego odpowiedzi, aby przedstawić opcje użytkownika, również wizualnie, ale też zaprojektować rozmowę w taki sposób, aby użytkownik tylko za pomocą głosu. Kilka sprawdzonych metod i przykładów procesu składania koszyków, zapoznaj się ze wskazówkami dotyczącymi projektowania transakcji.
Realizacja
Podczas rozmowy zbieraj szczegóły rezerwacji potrzebne użytkownikowi.
kupić ją, a potem utworzyć obiekt Order
.
Order
musi zawierać przynajmniej:
buyerInfo
– informacje o użytkowniku planującym rezerwację.transactionMerchant
– informacje o sprzedawcy, który ułatwia korzystanie z usługi. rezerwacji.contents
– rzeczywiste szczegóły rezerwacji wymienione jakolineItems
.
Zapoznaj się z dokumentacją odpowiedzi Order
.
aby utworzyć koszyk. Pamiętaj, że może być konieczne uwzględnienie innych pól
w zależności od rezerwacji.
Przykładowy kod poniżej przedstawia kompletne zamówienie rezerwacji, w tym pola opcjonalne:
app.intent('build_reservation_df', (conv) => { const now = new Date().toISOString(); const order = { createTime: now, lastUpdateTime: now, merchantOrderId: 'UNIQUE_ORDER_ID', userVisibleOrderId: 'USER_VISIBLE_ORDER_ID', transactionMerchant: { id: 'https://www.example.com', name: 'Example Merchant', }, contents: { lineItems: [ { id: 'LINE_ITEM_ID', name: 'Dinner reservation', description: 'A world of flavors all in one destination.', reservation: { status: 'PENDING', userVisibleStatusLabel: 'Reservation is pending.', type: 'RESTAURANT', reservationTime: { timeIso8601: '2020-01-16T01:30:15.01Z', }, userAcceptableTimeRange: { timeIso8601: '2020-01-15/2020-01-17', }, partySize: 6, staffFacilitators: [ { name: 'John Smith', }, ], location: { zipCode: '94086', city: 'Sunnyvale', postalAddress: { regionCode: 'US', postalCode: '94086', administrativeArea: 'CA', locality: 'Sunnyvale', addressLines: [ '222, Some other Street', ], }, }, }, }, ], }, buyerInfo: { email: 'janedoe@gmail.com', firstName: 'Jane', lastName: 'Doe', displayName: 'Jane Doe', }, followUpActions: [ { type: 'VIEW_DETAILS', title: 'View details', openUrlAction: { url: 'https://example.com', }, }, { type: 'CALL', title: 'Call us', openUrlAction: { url: 'tel:+16501112222', }, }, { type: 'EMAIL', title: 'Email us', openUrlAction: { url: 'mailto:person@example.com', }, }, ], termsOfServiceUrl: 'https://www.example.com', };
private static OrderV3 createOrder() { // Transaction Merchant MerchantV3 transactionMerchant = new MerchantV3() .setId("http://www.example.com") .setName("Example Merchant"); // Line Item // Reservation Item Extension ReservationItemExtension reservationItemExtension = new ReservationItemExtension() .setStatus("PENDING") .setUserVisibleStatusLabel("Reservation pending.") .setType("RESTAURANT") .setReservationTime(new TimeV3() .setTimeIso8601("2020-01-16T01:30:15.01Z")) .setUserAcceptableTimeRange(new TimeV3() .setTimeIso8601("2020-01-15/2020-01-17")) .setPartySize(6) .setStaffFacilitators(Collections.singletonList(new StaffFacilitator() .setName("John Smith"))) .setLocation(new Location() .setZipCode("94086") .setCity("Sunnyvale") .setPostalAddress(new PostalAddress() .setRegionCode("US") .setPostalCode("94086") .setAdministrativeArea("CA") .setLocality("Sunnyvale") .setAddressLines( Collections.singletonList("222, Some other Street")))); LineItemV3 lineItem = new LineItemV3() .setId("LINE_ITEM_ID") .setName("Dinner reservation") .setDescription("A world of flavors all in one destination.") .setReservation(reservationItemExtension); // Order Contents OrderContents contents = new OrderContents() .setLineItems(Collections.singletonList(lineItem)); // User Info UserInfo buyerInfo = new UserInfo() .setEmail("janedoe@gmail.com") .setFirstName("Jane") .setLastName("Doe") .setDisplayName("Jane Doe"); // Follow up actions Action viewDetails = new Action() .setType("VIEW_DETAILS") .setTitle("View details") .setOpenUrlAction(new OpenUrlAction() .setUrl("https://example.com")); Action call = new Action() .setType("CALL") .setTitle("Call us") .setOpenUrlAction(new OpenUrlAction() .setUrl("tel:+16501112222")); Action email = new Action() .setType("EMAIL") .setTitle("Email us") .setOpenUrlAction(new OpenUrlAction() .setUrl("mailto:person@example.com")); // Terms of service and order note String termsOfServiceUrl = "https://example.com"; String now = Instant.now().toString(); OrderV3 order = new OrderV3() .setCreateTime(now) .setLastUpdateTime(now) .setMerchantOrderId("UNIQUE_ORDER_ID") .setUserVisibleOrderId("UNIQUE_USER_VISIBLE_ORDER_ID") .setTransactionMerchant(transactionMerchant) .setContents(contents) .setBuyerInfo(buyerInfo) .setFollowUpActions(Arrays.asList( viewDetails, call, email )) .setTermsOfServiceUrl(termsOfServiceUrl); return order; }
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_DECISION", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "order": { "createTime": "2019-07-17T18:25:30.182Z", "lastUpdateTime": "2019-07-17T18:25:30.182Z", "merchantOrderId": "UNIQUE_ORDER_ID", "userVisibleOrderId": "USER_VISIBLE_ORDER_ID", "transactionMerchant": { "id": "https://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Dinner reservation", "description": "A world of flavors all in one destination.", "reservation": { "status": "PENDING", "userVisibleStatusLabel": "Reservation is pending.", "type": "RESTAURANT", "reservationTime": { "timeIso8601": "2020-01-16T01:30:15.01Z" }, "userAcceptableTimeRange": { "timeIso8601": "2020-01-15/2020-01-17" }, "partySize": 6, "staffFacilitators": [ { "name": "John Smith" } ], "location": { "zipCode": "94086", "city": "Sunnyvale", "postalAddress": { "regionCode": "US", "postalCode": "94086", "administrativeArea": "CA", "locality": "Sunnyvale", "addressLines": [ "222, Some other Street" ] } } } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "followUpActions": [ { "type": "VIEW_DETAILS", "title": "View details", "openUrlAction": { "url": "https://example.com" } }, { "type": "CALL", "title": "Call us", "openUrlAction": { "url": "tel:+16501112222" } }, { "type": "EMAIL", "title": "Email us", "openUrlAction": { "url": "mailto:person@example.com" } } ], "termsOfServiceUrl": "https://www.example.com" }, "orderOptions": { "requestDeliveryAddress": false, "userInfoOptions": { "userInfoProperties": [ "EMAIL" ] } }, "presentationOptions": { "actionDisplayName": "RESERVE" } } } } } }
3. Zaproponuj zamówienie
Przedstaw użytkownikowi zamówienie rezerwacji, aby mógł je potwierdzić lub
odrzuć. Poproś o actions.intent.TRANSACTION_DECISION
i udostępnij stworzony przez siebie zasób Order
.
Wygoda użytkowników
Gdy poprosisz o intencję actions.intent.TRANSACTION_DECISION
, Asystent
uruchamia wbudowane środowisko, w którym Order
jest
renderowanych bezpośrednio na „karcie podglądu koszyka”. Użytkownik może powiedzieć „zaplanuj rezerwację”,
odrzucić transakcję lub poprosić o zmianę szczegółów rezerwacji.
Na tym etapie użytkownik może również poprosić o zmianę zamówienia. W tym przypadku musisz się upewnić, że Twoja realizacja będzie mogła obsługiwać prośby o zmianę zamówienia po i kończę składanie koszyka.
Realizacja
Gdy poprosisz o
Intencja actions.intent.TRANSACTION_DECISION
, utwórz
TransactionDecision
, która zawiera Order
i orderOptions
Poniżej znajduje się przykładowy TransactionsDecision
dla zamówienia:
conv.ask(new TransactionDecision({ orderOptions: { requestDeliveryAddress: 'false', }, presentationOptions: { actionDisplayName: 'RESERVE', }, order: order, }));
// Create order options OrderOptionsV3 orderOptions = new OrderOptionsV3() .setRequestDeliveryAddress(false) .setUserInfoOptions(new UserInfoOptions() .setUserInfoProperties(Collections.singletonList("EMAIL"))); // Create presentation options PresentationOptionsV3 presentationOptions = new PresentationOptionsV3() .setActionDisplayName("RESERVE"); // Ask for transaction decision return getResponseBuilder(request) .add("Placeholder for transaction decision text") .add(new TransactionDecision() .setOrder(order) .setOrderOptions(orderOptions) .setPresentationOptions(presentationOptions) ) .build();
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_DECISION", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "requestDeliveryAddress": "false" }, "presentationOptions": { "actionDisplayName": "RESERVE" }, "order": { "createTime": "2019-07-17T18:25:30.184Z", "lastUpdateTime": "2019-07-17T18:25:30.184Z", "merchantOrderId": "UNIQUE_ORDER_ID", "userVisibleOrderId": "USER_VISIBLE_ORDER_ID", "transactionMerchant": { "id": "https://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Dinner reservation", "description": "A world of flavors all in one destination.", "reservation": { "status": "PENDING", "userVisibleStatusLabel": "Reservation is pending.", "type": "RESTAURANT", "reservationTime": { "timeIso8601": "2020-01-16T01:30:15.01Z" }, "userAcceptableTimeRange": { "timeIso8601": "2020-01-15/2020-01-17" }, "partySize": 6, "staffFacilitators": [ { "name": "John Smith" } ], "location": { "zipCode": "94086", "city": "Sunnyvale", "postalAddress": { "regionCode": "US", "postalCode": "94086", "administrativeArea": "CA", "locality": "Sunnyvale", "addressLines": [ "222, Some other Street" ] } } } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "followUpActions": [ { "type": "VIEW_DETAILS", "title": "View details", "openUrlAction": { "url": "https://example.com" } }, { "type": "CALL", "title": "Call us", "openUrlAction": { "url": "tel:+16501112222" } }, { "type": "EMAIL", "title": "Email us", "openUrlAction": { "url": "mailto:person@example.com" } } ], "termsOfServiceUrl": "https://www.example.com" } } } } } }
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TRANSACTION_DECISION", "inputValueData": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "requestDeliveryAddress": "false" }, "presentationOptions": { "actionDisplayName": "RESERVE" }, "order": { "createTime": "2019-07-17T18:25:30.057Z", "lastUpdateTime": "2019-07-17T18:25:30.057Z", "merchantOrderId": "UNIQUE_ORDER_ID", "userVisibleOrderId": "USER_VISIBLE_ORDER_ID", "transactionMerchant": { "id": "https://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Dinner reservation", "description": "A world of flavors all in one destination.", "reservation": { "status": "PENDING", "userVisibleStatusLabel": "Reservation is pending.", "type": "RESTAURANT", "reservationTime": { "timeIso8601": "2020-01-16T01:30:15.01Z" }, "userAcceptableTimeRange": { "timeIso8601": "2020-01-15/2020-01-17" }, "partySize": 6, "staffFacilitators": [ { "name": "John Smith" } ], "location": { "zipCode": "94086", "city": "Sunnyvale", "postalAddress": { "regionCode": "US", "postalCode": "94086", "administrativeArea": "CA", "locality": "Sunnyvale", "addressLines": [ "222, Some other Street" ] } } } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "followUpActions": [ { "type": "VIEW_DETAILS", "title": "View details", "openUrlAction": { "url": "https://example.com" } }, { "type": "CALL", "title": "Call us", "openUrlAction": { "url": "tel:+16501112222" } }, { "type": "EMAIL", "title": "Email us", "openUrlAction": { "url": "mailto:person@example.com" } } ], "termsOfServiceUrl": "https://www.example.com" } } } ] } ] }
Podejmowanie decyzji użytkownika
Gdy użytkownik odpowie na proponowane zamówienie, Twoja realizacja otrzyma
Intencja actions_intent_TRANSACTION_DECISION
z argumentem zawierającym
TransactionDecisionValue
Ta wartość będzie zawierać:
transactionDecision
– decyzja użytkownika w sprawie proponowanej zamówienie. Możliwe wartości toORDER_ACCEPTED
,ORDER_REJECTED
,CART_CHANGE_REQUESTED
iUSER_CANNOT_TRANSACT
.
Aby obsłużyć to żądanie, zadeklaruj intencję Dialogflow, która jest aktywowana przez
zdarzenie actions_intent_TRANSACTION_DECISION
. Obsługuj tę intencję w
realizację:
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE'); if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') { console.log('order accepted'); const order = arg.order; }
Argument transactionDecisionValue = request .getArgument("TRANSACTION_DECISION_VALUE"); Map<String, Object> extension = null; if (transactionDecisionValue != null) { extension = transactionDecisionValue.getExtension(); } String transactionDecision = null; if (extension != null) { transactionDecision = (String) extension.get("transactionDecision"); } if ((transactionDecision != null && transactionDecision.equals("ORDER_ACCEPTED"))) { OrderV3 order = ((OrderV3) extension.get("order")); }
Zwróć uwagę, że poniższy kod JSON opisuje żądanie webhooka.
{ "responseId": "", "queryResult": { "queryText": "", "action": "", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "", "fulfillmentMessages": [], "outputContexts": [], "intent": { "name": "reservation_get_transaction_decision_df", "displayName": "reservation_get_transaction_decision_df" }, "intentDetectionConfidence": 1, "diagnosticInfo": {}, "languageCode": "" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "isInSandbox": true, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "inputs": [ { "rawInputs": [], "intent": "", "arguments": [] } ], "user": {}, "conversation": {}, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "" }
Zwróć uwagę, że poniższy kod JSON opisuje żądanie webhooka.
{ "user": {}, "device": {}, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "conversation": {}, "inputs": [ { "rawInputs": [], "intent": "reservation_get_transaction_decision_asdk", "arguments": [] } ], "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
4. Dokończ rezerwację i wyślij rachunek
Gdy intencja actions.intent.TRANSACTION_DECISION
zwraca się z parametrem
transactionDecision
z ORDER_ACCEPTED
, wykonaj dowolną
do zaplanowania rezerwacji jest wymagane przetwarzanie (np. przechowywanie
dzięki własnej bazie danych).
Wyślij prostą odpowiedź aby podtrzymywać kontakt z widzami. Użytkownik otrzymuje „zwinięta kartę z potwierdzeniem zakupu” wraz z Twoją odpowiedzią.
Realizacja
// Set lastUpdateTime and update status of reservation order.lastUpdateTime = new Date().toISOString(); order.reservation.status = 'CONFIRMED'; order.reservation.userVisibleStatusLabel = 'Reservation confirmed'; order.reservation.confirmationCode = '123ABCDEFGXYZ'; // Send synchronous order update conv.ask(`Transaction completed! You're all set!`); conv.ask(new OrderUpdate({ type: 'SNAPSHOT', reason: 'Reason string', order: order, }));
ResponseBuilder responseBuilder = getResponseBuilder(request); order.setLastUpdateTime(Instant.now().toString()); // Set reservation status to confirmed and provide confirmation code LineItemV3 lineItem = order.getContents().getLineItems().get(0); ReservationItemExtension reservationItemExtension = lineItem.getReservation(); reservationItemExtension.setStatus("CONFIRMED"); reservationItemExtension.setUserVisibleStatusLabel("Reservation confirmed."); reservationItemExtension.setConfirmationCode("123ABCDEFGXYZ"); lineItem.setReservation(reservationItemExtension); order.getContents().getLineItems().set(0, lineItem); // Order update OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setType("SNAPSHOT") .setReason("Reason string") .setOrder(order); responseBuilder .add("Transaction completed! You're all set! Would you like to do anything else?") .add(new StructuredResponse().setOrderUpdateV3(orderUpdate)); return responseBuilder.build();
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! You're all set!" } }, { "structuredResponse": { "orderUpdateV3": { "type": "SNAPSHOT", "reason": "Reason string", "order": { "merchantOrderId": "UNIQUE_ORDER_ID", "reservation": { "status": "CONFIRMED", "userVisibleStatusLabel": "Reservation confirmed", "confirmationCode": "123ABCDEFGXYZ" }, "lastUpdateTime": "2019-07-17T18:25:30.187Z" } } } } ] } } } }
Pamiętaj, że poniższy kod JSON opisuje odpowiedź webhooka.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! You're all set!" } }, { "structuredResponse": { "orderUpdateV3": { "type": "SNAPSHOT", "reason": "Reason string", "order": { "merchantOrderId": "UNIQUE_ORDER_ID", "reservation": { "status": "CONFIRMED", "userVisibleStatusLabel": "Reservation confirmed", "confirmationCode": "123ABCDEFGXYZ" }, "lastUpdateTime": "2019-07-17T18:25:30.059Z" } } } } ] } } } ] }
5. Wysyłaj aktualne informacje o zamówieniu
Stan rezerwacji zmienia się w ciągu od początku jego istnienia. Wysyłaj aktualizacje dotyczące zamówień z rezerwacją użytkownika przez HTTP Żądania PATCH wysyłane do interfejsu Orders API zawierające stan i szczegóły zamówienia.
Konfigurowanie żądań asynchronicznych do interfejsu Orders API
Żądania aktualizacji zamówień do interfejsu Orders API są autoryzowane przez dostęp
token. Aby uzupełnić aktualizację zamówienia do interfejsu Orders API, pobierz plik JSON
klucz konta usługi powiązany z projektem w Konsoli Actions, a następnie
klucz konta usługi dla tokena okaziciela, który można przekazać do
Nagłówek Authorization
żądania HTTP.
Aby pobrać klucz konta usługi, wykonaj te czynności:
- W konsoli Google Cloud: przejdź do Menu ☰ > Interfejsy API Usługi > Dane logowania > Utwórz dane logowania > Klucz konta usługi.
- W sekcji Konto usługi wybierz Nowe konto usługi.
- Ustaw konto usługi na
service-account
. - Ustaw Rola na Projekt > Właściciel.
- Ustaw typ klucza na JSON.
- Kliknij Utwórz.
- Prywatny klucz konta usługi JSON zostanie pobrany na Twój komputer lokalny.
W kodzie aktualizacji zamówienia wymień klucz usługi na token okaziciela za pomocą biblioteki klienta interfejsów API Google i zakresu "https://www.googleapis.com/auth/actions.order.developer". Instrukcje instalacji i opis znajdziesz znajdziesz na stronie GitHub biblioteki klienta interfejsów API.
Odwołaj się do order-update.js
w naszych przykładach Node.js i Java dla
przykładową wymianę kluczy.
Wysyłaj aktualne informacje o zamówieniu
Po wymianie klucza konta usługi na token okaziciela OAuth wyślij aktualizacje zamówień jako autoryzowane żądania PATCH wysyłane do interfejsu Orders API.
Adres URL interfejsu Orders API:
PATCH https://actions.googleapis.com/v3/orders/${orderId}
Umieść w żądaniu te nagłówki:
"Authorization: Bearer token"
z tokenem okaziciela OAuth dla którego wymieniono klucz konta usługi."Content-Type: application/json"
.
Żądanie PATCH powinno przyjąć treść JSON w tym formacie:
{ "orderUpdate": OrderUpdate }
OrderUpdate
obiekt składa się z następujących pól najwyższego poziomu:
updateMask
– pola aktualizowanego zamówienia. Aby zaktualizować stan rezerwacji, ustaw wartość nareservation.status, reservation.userVisibleStatusLabel
.order
– zawartość aktualizacji. Jeśli aktualizujesz treści rezerwacji, ustaw wartość na zaktualizowany obiektOrder
. Jeśli tylko aktualizujesz stan rezerwacji (na przykład z od"PENDING"
do"FULFILLED"
), obiekt zawiera tych pól:merchantOrderId
– identyfikator, który został ustawiony w obiekcieOrder
.lastUpdateTime
– sygnatura czasowa aktualizacji.purchase
– obiekt zawierający:status
– stan zamówienia (ReservationStatus
), na przykład „CONFIRMED
” lub „CANCELLED
”.userVisibleStatusLabel
– etykieta dla użytkownika zawierająca szczegółowe informacje stan zamówienia, np. „Rezerwacja została potwierdzona”.
userNotification
(opcjonalnie) – AuserNotification
do wyświetlenia na urządzeniu użytkownika po wysłaniu tej aktualizacji. Notatka że uwzględnienie tego obiektu nie gwarantuje, że powiadomienie na urządzeniu użytkownika.
Poniżej znajduje się przykładowy kod OrderUpdate
, który aktualizuje
stan zamówienia rezerwacji na FULFILLED
:
// Import the 'googleapis' module for authorizing the request. const {google} = require('googleapis'); // Import the 'request' module for sending an HTTP POST request. const request = require('request'); // Import the OrderUpdate class from the Actions on Google client library. const {OrderUpdate} = require('actions-on-google'); // Import the service account key used to authorize the request. Replace the string path with a path to your service account key. const key = require('./service-account.json'); // Create a new JWT client for the Actions API using credentials from the service account key. let jwtClient = new google.auth.JWT( key.client_email, null, key.private_key, ['https://www.googleapis.com/auth/actions.order.developer'], null ); // Authorize the client asynchronously, passing in a callback to run upon authorization. jwtClient.authorize((err, tokens) => { if (err) { console.log(err); return; } // Declare the ID of the order to update. const orderId = '<UNIQUE_MERCHANT_ORDER_ID>'; const orderUpdateJson = new OrderUpdate({ updateMask: [ 'lastUpdateTime', 'contents.lineItems.reservation.status', 'contents.lineItems.reservation.userVisibleStatusLabel', ].join(','), order: { merchantOrderId: orderId, lastUpdateTime: new Date().toISOString(), contents: { lineItems: [ { reservation: { status: 'FULFILLED', userVisibleStatusLabel: 'Reservation fulfilled', }, } ] } }, reason: 'Reservation status was updated to fulfilled.', }); // Set up the PATCH request header and body, including the authorized token // and order update. const bearer = 'Bearer ' + tokens.access_token; const options = { method: 'PATCH', url: `https://actions.googleapis.com/v3/orders/${orderId}`, headers: { 'Authorization': bearer, }, body: { header: { 'isInSandbox': true, }, orderUpdate: orderUpdateJson, }, json: true, }; // Send the PATCH request to the Orders API. request.patch(options, (err, httpResponse, body) => { if (err) { console.log('There was an error...'); console.log(err); return; } }); });
// Create order update FieldMask fieldMask = FieldMask.newBuilder().addAllPaths(Arrays.asList( "lastUpdateTime", "contents.lineItems.reservation.status", "contents.lineItems.reservation.userVisibleStatusLabel")) .build(); OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setOrder(new OrderV3() .setMerchantOrderId(orderId) .setLastUpdateTime(Instant.now().toString()) .setContents(new OrderContents() .setLineItems(Collections.singletonList(new LineItemV3() .setReservation(new ReservationItemExtension() .setStatus("FULFILLED") .setUserVisibleStatusLabel("Reservation fulfilled.")))))) .setUpdateMask(FieldMaskUtil.toString(fieldMask)) .setReason("Reservation status was updated to fulfilled."); // Setup JSON body containing order update JsonParser parser = new JsonParser(); JsonObject orderUpdateJson = parser.parse(new Gson().toJson(orderUpdate)).getAsJsonObject(); JsonObject body = new JsonObject(); body.add("orderUpdate", orderUpdateJson); JsonObject header = new JsonObject(); header.addProperty("isInSandbox", true); body.add("header", header); StringEntity entity = new StringEntity(body.toString()); entity.setContentType(ContentType.APPLICATION_JSON.getMimeType()); request.setEntity(entity); // Make request HttpClient httpClient = HttpClientBuilder.create().build(); HttpResponse response = httpClient.execute(request);
Ustawianie stanu rezerwacji
Identyfikator ReservationStatus
aktualizacji zamówienia
musi opisywać bieżący stan zamówienia. W grupie order.ReservationStatus
aktualizacji
użyj jednej z tych wartości:
PENDING
– rezerwacja została „utworzona” przez akcję, ale wymaga dodatkowe przetwarzanie w Twoim zapleczu.CONFIRMED
– rezerwacja została potwierdzona w backendzie do planowania.CANCELLED
– użytkownik anulował rezerwację.FULFILLED
– rezerwacja użytkownika została zrealizowana przez usługę.CHANGE_REQUESTED
– użytkownik poprosił o zmianę rezerwacji, która została wprowadzona. w trakcie przetwarzania danych.REJECTED
– jeśli nie udało się przetworzyć lub masz inne problemy potwierdzić rezerwację.
Wysyłaj aktualne informacje o zamówieniach o każdym stanie powiązanym z
rezerwacji. Jeśli na przykład Twoja rezerwacja wymaga ręcznego przetwarzania, aby
potwierdź rezerwację po przesłaniu prośby, wyślij aktualizację dotyczącą zamówienia u sprzedawcy PENDING
do
że jest wykonywane dodatkowe przetwarzanie. Nie każda rezerwacja wymaga każdej wartości stanu.
Rozwiązywanie problemów
Jeśli podczas testowania wystąpią jakiekolwiek problemy, przeczytaj artykuł o rozwiązywaniu problemów. transakcji.