Asynchroniczne aktualizacje zamówień

Gdy klient przesyła zamówienie jedzenia, możesz wysłać do niego wiadomość o aktualizacji zamówienia, aby powiadomić nas o zmianie.

Oto kilka częstych przyczyn wysyłania aktualizacji zamówień:

  • Szacowany czas realizacji zamówienia będzie dostępny lub się zmieni.
  • Zmieni się stan zamówienia.
  • Nie można już zrealizować zamówienia.
  • Zmieniła się cena dania w menu dołączonego do zamówienia.
  • Klient ma nowy sposób zarządzania zamówieniami, np. obsługę klienta czy numer telefonu do restauracji.
  • Potwierdzenie zamówienia zostanie udostępnione.

W kolejnych sekcjach znajdziesz szczegółowe informacje o tym, jak rozwiązywać te problemy przy użyciu aktualizacji zamówień.

Przejściowe stany zamówień

Zamówienie może mieć 6 stanów. Te stany i ich możliwe przejście zostały opisane na tym diagramie:

Przeniesienia stanu zamówienia

Gdy klient przesyła zamówienie po raz pierwszy, zamówienie rozpoczyna się od CREATED, CONFIRMED lub REJECTED. Możesz wysłać wiadomość o aktualizacji zamówienia, aby zaktualizować jego stan, o ile migracja stanu jest prawidłowa. Stan CREATED jest używany, gdy platforma partnera nie może potwierdzić ani odrzucić zamówienia. Przykładem może być sytuacja, gdy klient zamawia za pomocą agregatora dostaw. Agregator odbierający dostarcza dane z Google i agregator wysyła je do restauracji. Gdy restauracja otrzyma i potwierdzi dostępność zamówienia, stan będzie się zmieniał na CONFIRMED, w przeciwnym razie – REJECTED.

Zamówienie w stanie CONFIRMED przechodzi później do stanu IN_PREPARATION. W zależności od tego, czy zamówienie obejmuje odbiór czy dostawę, zastosuj stan READY_FOR_PICKUP lub IN_TRANSIT. Po dostarczeniu lub odebraniu jedzenia zamówienie ma stan FULFILLED.

Jeśli zezwalasz klientom na anulowanie zamówień, możesz używać stanu CANCELLED. Zamówienie można anulować, jeśli ma stan CREATED, CONFIRMED, IN_PREPARATION, READY_FOR_PICKUP lub IN_TRANSIT. Zwrot środków za pomocą usługi Zamów przez Google powinien być zależny od zasad anulowania zamówień i stanu płatności w momencie anulowania.

Usługa Zamów przez Google nie musi obsługiwać wszystkich dostępnych stanów i procesów przenoszenia. Ostatnim stanem zamówienia musi być FULFILLED, REJECTED lub CANCELLED.

Podawanie szacowanego czasu realizacji

Możesz podać użytkownikom szacowany przedział czasu, w którym ich zamówienie będzie gotowe do odbioru (lub dostarczenia). W polu estimatedFulfillmentTimeIso8601 w polu FoodOrderUpdateExtension podaj szacowany przedział czasu, w którym zamówienie klienta będzie gotowe do odbioru lub dostawy.

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

  • Gdy szacowany czas będzie dostępny, najlepiej w kolejności CREATED lub CONFIRMED.
  • gdy szacowany czas się zmieni, np. zaktualizuje szacowany czas, aby zwiększyć dokładność, gdy zamówienie jest IN_TRANSIT.

Aby wydajnie zarządzać oczekiwaniami użytkowników, zachowawczo ustal szacunki i podawaj daty oraz godziny, a nie stałe daty i godziny. Jeśli to możliwe, uwzględniaj różne odmiany, np. warunki na drodze. Na przykład szacowaną godzinę 12:45 (dolną granicę) możesz wysłać do 13:15 (górna granica) w przypadku zamówienia, w przypadku którego szacowany czas dostawy to 13:00.

Wykonywanie działań związanych z zarządzaniem zamówieniami

Wysyłając aktualizację zamówienia, możesz udostępnić zasoby klientom, aby pomóc im w zarządzaniu zamówieniami w formie OrderManagementAction. Gdy klient złoży zamówienie, może potrzebować kontaktu z Tobą lub z restauracją, która realizuje zamówienie, aby śledzić postęp, wprowadzić zmiany lub anulować zamówienie.

OrderManagementAction pozwala klientom wysyłać e-maile, dzwonić i dodawać linki do adresów URL bezpośrednio z urządzenia. Podaj te same informacje w OrderManagementAction, które znajdziesz w e-mailu z potwierdzeniem zamówienia wysłanym do użytkownika.

Do działań związanych z zarządzaniem zamówieniami należą:

  • CUSTOMER_SERVICE: zachęcenie klientów do skontaktowania się z obsługą klienta. Ten typ zarządzania jest wymagany do aktualizowania zamówień.
  • EMAIL: przekaż klientom działanie, aby wysłać e-maila na podany adres.
  • CALL: wyświetlaj klientom działanie, które pozwala zadzwonić pod podany numer telefonu.
  • VIEW_DETAIL: przekaż klientom działanie, aby wyświetlić szczegóły zamówienia.

Każda aktualizacja zamówienia musi zawierać co najmniej jedno działanie zarządzania zamówieniem. Podane czynności zarządzania zamówieniami mogą się jednak różnić w zależności od stanu zamówienia. Jeśli np. zamówienie ma stan CONFIRMED, działanie CUSTOMER_SERVICE może wskazywać numer telefonu do obsługi klienta. Gdy stan zamówienia zmieni się na IN_TRANSIT, działanie CUSTOMER_SERVICE może wskazywać numer telefonu restauracji realizacji.

Wysyłam aktualizacje zamówień

Typ wiadomości AsyncOrderUpdateRequestMessage służy do wysyłania aktualizacji zamówień do usługi Zamów przez Google. Odpowiedź Google zawiera odpowiedź AsyncOrderUpdateResponseMessage. Jeśli na przykład chcesz poinformować klienta, że zamówienie jest prawidłowe i zaakceptowane, możesz wysłać AsyncOrderUpdateRequestMessage, aby zmienić stan zamówienia na CONFIRMED z etykietą Accepted by restaurant.

Diagram aktualizacji zamówienia

Ustawianie komunikatu o aktualizacji zamówienia

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

W tych przykładach widać przykładowe AsyncOrderUpdateRequestMessage dla każdego stanu zamówienia:

POTWIERDZONO

Ten przykład pokazuje żądanie aktualizacji zamówienia, które informuje użytkownika o potwierdzeniu zamówienia wraz z szacowanym czasem 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 pokazuje żądanie aktualizacji zamówienia powiadamiające użytkownika o odrzuceniu zamówienia z przyczyną 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 pokazuje żądanie aktualizacji zamówienia, które informuje użytkownika o anulowaniu zamówienia z powodu jego 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"
            }
          }
        }
      ]
    }
  }
}
    

W_PRZYPADKU

Ten przykład pokazuje żądanie aktualizacji zamówienia, które powiadamia użytkownika o tym, ż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"
      }
    }
  }
}
    

GOTOWE_DO_ODBIORU

Ten przykład pokazuje żądanie aktualizacji zamówienia, które informuje użytkownika, że jedzenie można odebrać.

{
  "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"
      }
    }
  }
}
    

Transport publiczny

Ten przykład pokazuje żądanie aktualizacji zamówienia, które informuje użytkownika o tym, że zamówienie jest w drodze, oraz szacowanego czasu 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"
      }
    }
  }
}
  

SPEŁNIONE

W tym przykładowym żądaniu aktualizacji zamówienia powiadamiamy 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 Implementowanie zaawansowanych aktualizacji zamówień.

Wygeneruj token autoryzacji i wyślij wiadomość

Aktualizacje zamówień wymagają tokena autoryzacji, aby usługa Order with Google mogła zweryfikować, czy wiadomość pochodzi z usługi internetowej Zamów przez Google.

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

  1. Wygeneruj token autoryzacji, wykonując te czynności:
    1. Użyj biblioteki uwierzytelniania Google do odczytania danych 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 HTTP POST do tego punktu końcowego: https://actions.googleapis.com/v2/conversations:send
  3. W żądaniu ustaw nagłówek Content-Type na application/json.

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

Node.js

W tym kodzie używana jest biblioteka uwierzytelniania Google na potrzeby ś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

W tym kodzie używana jest biblioteka uwierzytelniania Google.

/**
 * 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 pomyślnych aktualizacji zamówień bez błędów Google zwraca odpowiedź HTTP 200 z pustym ładunkiem. Jeśli wystąpił problem, np. nieprawidłowa aktualizacja aktualizacji, Google zwróci błąd.