Aktualizacja zamówienia asynchronicznego

Gdy klient prześle zamówienie na jedzenie, możesz powiadomić nas o zmianie, wysyłając wiadomość o aktualizacji zamówienia do usługi kompleksowej obsługi zamówień.

Oto kilka najczęstszych przyczyn wysyłania aktualizacji zamówień:

  • Przewidywany czas realizacji zamówienia stanie się dostępny lub może ulec zmianie.
  • Stan zamówienia ulegnie zmianie.
  • Nie można już zrealizować zamówienia.
  • Zmieniła się cena pozycji w menu uwzględnionej w zamówieniu.
  • Klient ma nowy sposób zarządzania zamówieniami, np. obsługę klienta lub numer telefonu do restauracji.
  • Potwierdzenie zamówienia stanie się dostępne.

Kolejne sekcje zawierają szczegółowe informacje o tym, jak zastosować aktualizacje w tych różnych sytuacjach.

Przenoszenie stanów zamówienia

Zamówienie może mieć 6 stanów. Te stany i ich możliwe przejścia przedstawiono na tym diagramie:

Zmiany stanu zamówień

Gdy klient po raz pierwszy prześle zamówienie, ma ono stan CREATED, CONFIRMED lub REJECTED. Możesz wysłać wiadomość z aktualizacją stanu zamówienia, o ile zmiana stanu będzie ważna. Stan CREATED jest używany, gdy platforma partnera nie może od razu potwierdzić ani odrzucić zamówienia. Przykładem może być sytuacja, w której klient składa zamówienie przez pośrednika w dostawie. Agregator dostawy otrzymuje dostawę od Google, a pośrednik przesyła te informacje do restauracji. Gdy restauracja otrzyma i potwierdzi dostępność zamówienia, stan może teraz wynosić CONFIRMED. W przeciwnym razie REJECTED.

Następnie zamówienie w stanie CONFIRMED przechodzi do stanu IN_PREPARATION. W zależności od tego, czy zamówienie dotyczy odbioru czy dostawy, użyj stanu READY_FOR_PICKUP lub IN_TRANSIT. Gdy jedzenie zostało dostarczone lub odebrane, stan zamówienia jest ustawiany na FULFILLED.

Jeśli zezwalasz klientom na anulowanie zamówień, możesz użyć stanu CANCELLED. Zamówienie można anulować, jeśli jego stan to CREATED, CONFIRMED, IN_PREPARATION, READY_FOR_PICKUP lub IN_TRANSIT. Twoja kompleksowa usługa związana z zamawianiem powinna zwrócić środki w zależności od zasad anulowania i stanu płatności w momencie anulowania.

Kompleksowa usługa składania zamówień nie musi obsługiwać wszystkich dostępnych stanów i przejść. Ostatecznym stanem zamówienia musi być jednak FULFILLED, REJECTED lub CANCELLED.

Podawanie szacowanego czasu realizacji

Możesz podać użytkownikom szacowany czas, kiedy ich zamówienie będzie gotowe do odbioru (lub dostarczonego). Użyj pola estimatedFulfillmentTimeIso8601 w polu FoodOrderUpdateExtension, aby podać szacowany przedział czasu, w którym zamówienie klienta będzie gotowe do odbioru lub dostawy.

Wyślij estimatedFulfillmentTimeIso8601 w następujących godzinach:

  • Kiedy dostępny będzie szacowany czas, najlepiej w kolejności CREATED lub CONFIRMED.
  • Gdy zmieni się szacowany czas, na przykład zaktualizuje szacowany czas, aby był dokładniejszy, gdy zamówienie będzie IN_TRANSIT.

Aby skutecznie rozumieć oczekiwania użytkowników, stosuj ostrożne szacunki. Nie podawaj konkretnej daty ani godziny, podając tylko datę i godzinę. W miarę możliwości uwzględnij odmiany, takie jak warunki na drodze. Możesz na przykład wysłać szacunkową godzinę dostawy do 12:45 (dolna granica) do 13:15 (górna) w przypadku zamówienia, dla którego szacowany czas dostawy to 13:00.

Określanie działań związanych z zarządzaniem zamówieniami

Wysyłając aktualizację zamówienia, możesz udostępnić klientom zasoby, które pomogą im w zarządzaniu zamówieniem w postaci OrderManagementAction. Gdy klient złoży zamówienie, być może będzie musiał skontaktować się z Tobą lub restauracją realizującą zamówienie, aby śledzić postępy, wprowadzić zmiany lub anulować zamówienie.

OrderManagementAction pozwala klientom wysyłać e-maile, dzwonić i umieszczać linki do podstron bezpośrednio na urządzeniu. Użyj tych samych informacji w polu OrderManagementAction co w e-mailu z potwierdzeniem zamówienia, który wysyłasz do użytkownika.

Działania zarządzania zamówieniami obejmują następujące typy:

  • CUSTOMER_SERVICE: zachęć klientów do kontaktu z obsługą klienta. Ten typ czynności zarządzania jest wymagany do aktualizacji zamówień.
  • EMAIL: zachęć klientów do wysłania e-maila na podany adres e-mail.
  • CALL: zachęć klientów, by zadzwonili pod podany numer telefonu.
  • VIEW_DETAIL: umożliwia klientom wyświetlenie szczegółów zamówienia.

Każda aktualizacja zamówienia musi zawierać co najmniej jedno działanie związane z zarządzaniem zamówieniami. Dostępne działania związane z zarządzaniem zamówieniami mogą się jednak różnić w zależności od stanu zamówienia. Jeśli na przykład zamówienie ma stan CONFIRMED, działanie CUSTOMER_SERVICE może wskazywać Twój numer telefonu do działu obsługi klienta. Gdy ten stan zamówienia zmieni się na IN_TRANSIT, działanie CUSTOMER_SERVICE może wskazywać numer telefonu restauracji realizującej zamówienie.

Wysyłam aktualizacje dotyczące zamówienia

Typ wiadomości AsyncOrderUpdateRequestMessage służy do wysyłania aktualizacji zamówienia do usługi obejmującej cały proces sortowania. W odpowiedzi Google przesyła AsyncOrderUpdateResponseMessage. Jeśli na przykład chcesz poinformować klienta, że jego zamówienie jest prawidłowe i zaakceptowane, możesz wysłać AsyncOrderUpdateRequestMessage, aby zmienić stan zamówienia na CONFIRMED z etykietą Accepted by restaurant.

Schemat aktualizacji zamówienia

Ustawianie komunikatu z aktualizacją zamówienia

Wysyłając AsyncOrderUpdateRequestMessage do Google, musisz podać informacje o stanie zamówienia w polu OrderUpdate.

W przykładach poniżej pokazujemy przykładowy element AsyncOrderUpdateRequestMessage dla każdego stanu zamówienia:

POTWIERDZONO

Ten przykład przedstawia przykładowe żądanie aktualizacji zamówienia, w którym informuje użytkownika, że zamówienie zostało potwierdzone za pomocą potwierdzenia i przewidywanego czasu dostawy.

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "CONFIRMED",
        "label": "Provider confirmed"
      },
      "receipt": {
        "userVisibleOrderId": "userVisibleId1234"
      },
      "updateTime": "2017-07-17T12:00:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
        "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601": "2017-07-17T13:00:00Z/2017-07-17T13:30:00Z"
      }
    }
  }
}
    

ODRZUCONO

Ten przykład przedstawia przykładowe żądanie aktualizacji zamówienia, które informuje użytkownika, że zamówienie zostało odrzucone z powodu odrzucenia.

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "REJECTED",
        "label": "Order rejected"
      },
      "updateTime": "2017-05-10T02:30:00.000Z",
      "rejectionInfo": {
        "type": "UNKNOWN",
        "reason": "Sorry, the restaurant cannot take your order right now."
      },
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
      "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
      "foodOrderErrors": [
        {
        "error": "NO_CAPACITY",
        "description": "Sorry, the restaurant cannot take your order right now."
        }
      ]
      }
    }
  }
}
    

ANULOWANY

Ten przykład przedstawia przykładowe żądanie aktualizacji zamówienia, które powiadamia użytkownika, że zamówienie zostało anulowane z powodu anulowania.

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "CANCELLED",
        "label": "Order cancelled"
      },
      "updateTime": "2017-05-10T02:30:00.000Z",
      "cancellationInfo": {
        "reason": "Customer requested"
      },
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ]
    }
  }
}
    

IN_PREPARATION

Ten przykład przedstawia przykładowe żądanie aktualizacji zamówienia, które informuje użytkownika, że jedzenie jest obecnie przygotowywane.

{
  "isInSandbox":true,
  "customPushMessage":{
    "orderUpdate":{
      "actionOrderId":"sample_action_order_id",
      "orderState":{
        "state":"IN_PREPARATION",
        "label":"Order is being prepared"
      },
      "receipt": {
        "userVisibleOrderId": "userVisibleId1234"
      },
      "updateTime":"2018-04-15T11:30:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension":{
        "@type":"type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601":"PT20M"
      }
    }
  }
}
    

READY_FOR_PICKUP

Ten przykład pokazuje przykładowe żądanie aktualizacji zamówienia, które informuje użytkownika, że jedzenie jest gotowe do odbioru.

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "READY_FOR_PICKUP",
        "label": "Order is ready for pickup"
      },
      "receipt": {
        "userVisibleOrderId": "userVisibleId1234"
      },
      "updateTime": "2018-04-15T12:00:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
        "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601": "PT20M"
      }
    }
  }
}
    

IN_TRANSIT

Ten przykład przedstawia przykładowe żądanie aktualizacji zamówienia, które informuje użytkownika, że zamówienie jest w drodze, z przewidywanym czasem dostawy.

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "IN_TRANSIT",
        "label": "Order is on the way"
      },
      "inTransitInfo": {
        "updatedTime": "2017-07-17T12:00:00Z"
      },
      "updateTime": "2017-07-17T12:00:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
        "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601": "PT20M"
      }
    }
  }
}
  

Zrealizowano

Ten przykład przedstawia przykładowe żądanie aktualizacji zamówienia, które informuje użytkownika, że zamówienie zostało odebrane lub dostarczone:

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
      "state": "FULFILLED",
      "label": "Order delivered"
      },
      "updateTime": "2017-05-10T02:30:00.000Z",
      "fulfillmentInfo": {
        "deliveryTime": "2017-05-10T02:30:00.000Z"
      },
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ]
    }
  }
}
    

Więcej przykładów żądań aktualizacji zamówień w różnych przypadkach użycia znajdziesz w artykule o wdrażaniu zaawansowanych aktualizacji zamówień.

Wygeneruj token autoryzacji i wyślij wiadomość

Aktualizacje zamówień wymagają tokena autoryzacji, aby usługa kompleksowej obsługi zamówień mogła sprawdzić, czy wiadomość pochodzi z Twojej kompleksowej usługi internetowej do obsługi zamówień.

Aby wdrożyć aktualizacje zamówień w projekcie, wykonaj te czynności:

  1. Wygeneruj token autoryzacji, wykonując te czynności:
    1. Użyj biblioteki Google Auth Library, aby odczytać dane logowania z pliku konta usługi.
    2. Poproś o token, używając tego zakresu interfejsu API: https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. Użyj tego tokena, aby wysłać uwierzytelnione żądanie POST HTTP do tego punktu końcowego: https://actions.googleapis.com/v2/conversations:send
  3. W ramach żądania ustaw nagłówek Content-Type na application/json.

Poniższe przykłady pokazują, jak wdrożyć aktualizacje zamówienia:

Node.js

Ten kod korzysta z biblioteki uwierzytelniania Google dla środowiska Node.js.

const {auth} = require('google-auth-library')
const request = require('request');
// The service account client secret file downloaded from the Google Cloud Console
const serviceAccountJson = require('./service-account.json')
// order-update.json is a file that contains the payload
const jsonBody = require('./order-update.json')

/**
 * Get the authorization token using a service account.
 */
async function getAuthToken() {
  let client = auth.fromJSON(serviceAccountJson)
  client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation']
  const tokens = await client.authorize()
  return tokens.access_token;
}

/**
 * Send an order update request
 */
async function sendOrderUpdate() {
  const token = await getAuthToken()
  request.post({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    url: 'https://actions.googleapis.com/v2/conversations:send',
    body: jsonBody,
    json: true
  },
  (err, res, body) => {
    if (err) { return console.log(err); }
    console.log(`Response: ${JSON.stringify(res)}`)
  })
}
    

Python

Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Pythona.

from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
import json

# service-account.json is the service account client secret file downloaded from the
# Google Cloud Console
credentials = service_account.Credentials.from_service_account_file(
    'service-account.json')

scoped_credentials = credentials.with_scopes(
    ['https://www.googleapis.com/auth/actions.fulfillment.conversation'])

authed_session = AuthorizedSession(scoped_credentials)

# order-update.json is a file that contains the payload
json_payload=json.load(open('order-update.json'))

response = authed_session.post(
    'https://actions.googleapis.com/v2/conversations:send',
    json=json_payload)
    

Java

Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Javy.

/**
 * Get the authorization token using a service account.
 */
private static String getAuthToken() {
  InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json");
  ServiceAccountCredentials.Builder credentialsSimpleBuilder =
      ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder();
  credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/actions.fulfillment.conversation"));
  AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken();
  return accessToken.getTokenValue();
}

/**
 * Send an order update request
 */
public void sendOrderUpdate() {
  String authToken = getAuthToken();
  // Execute POST request
  executePostRequest("https://actions.googleapis.com/v2/conversations:send",
      authToken, "update_order_example.json",);
}
    

W przypadku udanej aktualizacji zamówień bez błędów Google zwraca odpowiedź HTTP 200 z pustym ładunkiem. Jeśli wystąpił problem, na przykład nieprawidłowa aktualizacja, Google zwróci błąd.