Mise à jour des commandes asynchrones

Une fois qu'un client a envoyé sa commande de repas, vous pouvez envoyer un message de mise à jour de commande au service Order with Google pour nous informer du changement.

Vous trouverez ci-dessous les raisons les plus courantes pouvant expliquer l'envoi de mises à jour des commandes:

  • Le délai de traitement estimé de la commande est disponible ou change.
  • L'état d'une commande change.
  • La commande ne peut plus être traitée.
  • Le prix d'un élément de menu inclus dans la commande a changé.
  • Le client dispose d'une nouvelle méthode pour gérer sa commande, telle qu'un numéro de téléphone du service client ou de restaurant.
  • Le reçu de la commande devient disponible.

Les sections suivantes expliquent comment gérer ces différents scénarios à l'aide des mises à jour de commandes.

Changer l'état des commandes

Une commande peut avoir six états. Ces états et leurs transitions possibles sont décrits dans le schéma suivant:

Transitions d'état de la commande

Lorsqu'un client envoie une commande pour la première fois, celle-ci commence par l'état CREATED, CONFIRMED ou REJECTED. Vous pouvez envoyer un message de mise à jour de la commande pour mettre à jour l'état d'une commande, à condition que la transition d'état soit valide. L'état CREATED est utilisé lorsque la plate-forme du partenaire ne peut pas confirmer ni refuser la commande immédiatement. C'est par exemple le cas lorsqu'un client passe une commande via un agrégateur de livraison. L'agrégateur reçoit les informations de livraison de la part de Google, puis envoie ces informations au restaurant. Une fois que le restaurant a reçu et confirmé la disponibilité de la commande, l'état peut désormais être CONFIRMED, sinon REJECTED.

Une commande dont l'état est CONFIRMED passe à l'état IN_PREPARATION. Selon l'état de la commande (retrait ou livraison), utilisez l'état READY_FOR_PICKUP ou IN_TRANSIT. Une fois le plat livré ou retiré, la commande est définie sur l'état FULFILLED.

Si vous autorisez les clients à annuler des commandes, vous pouvez utiliser l'état CANCELLED. Une commande peut être annulée lorsqu'elle présente l'état CREATED, CONFIRMED, IN_PREPARATION, READY_FOR_PICKUP ou IN_TRANSIT. Votre service Order with Google devrait émettre des remboursements en fonction de vos modalités d'annulation et de l'état des paiements au moment de l'annulation.

Votre service Order with Google ne doit pas être compatible avec tous les états et transitions disponibles. Toutefois, l'état final de la commande doit être FULFILLED, REJECTED ou CANCELLED.

Fournir une estimation du délai de traitement

Vous pouvez fournir aux utilisateurs un délai estimé pour la date où leur commande sera prête à être retirée (ou livrée). Utilisez le champ estimatedFulfillmentTimeIso8601 de FoodOrderUpdateExtension pour fournir une estimation de la période de livraison de la commande d'un client.

Envoyez estimatedFulfillmentTimeIso8601 aux heures suivantes:

  • Lorsque le délai estimé devient disponible, idéalement dans l'état CREATED ou CONFIRMED de la commande.
  • Lorsque l'heure estimée change, par exemple pour mettre à jour l'heure estimée afin que la commande soit IN_TRANSIT plus précise.

Pour gérer efficacement les attentes des utilisateurs, soyez prudent dans vos estimations et indiquez une date et une heure plutôt qu'une date et une heure fixes. Dans la mesure du possible, vous devez tenir compte des variantes telles que les conditions de circulation. Par exemple, vous pouvez envoyer une estimation de 12h45 (limite inférieure) à 13h15 (limite supérieure) pour une commande dont le délai de livraison estimé est 13h.

Fournir des actions de gestion des commandes

Lorsque vous envoyez une mise à jour de la commande, vous pouvez fournir aux clients des ressources qui les aident à gérer leur commande sous la forme d'un OrderManagementAction. Après avoir passé commande, il est susceptible de devoir vous contacter ou contacter le restaurant pour suivre votre progression, apporter des modifications ou annuler votre commande.

Un OrderManagementAction permet aux clients d'envoyer un e-mail, d'appeler ou de créer un lien vers une URL directement depuis leur appareil. Utilisez les mêmes informations dans OrderManagementAction que dans la confirmation de commande par e-mail que vous envoyez à l'utilisateur.

Les types d'actions de gestion des commandes sont les suivants:

  • CUSTOMER_SERVICE: fournissez aux clients une action pour contacter le service client. Ce type d'action de gestion est obligatoire pour les mises à jour de commandes.
  • EMAIL: indiquez aux clients une action à envoyer à l'adresse e-mail fournie.
  • CALL: expliquez aux clients comment appeler le numéro de téléphone indiqué.
  • VIEW_DETAIL: action permettant aux clients d'afficher les détails de leur commande.

Chaque mise à jour de commande doit contenir au moins une action de gestion des commandes. Toutefois, les actions de gestion des commandes fournies peuvent varier en fonction de l'état de la commande. Par exemple, lorsqu'une commande est à l'état CONFIRMED, l'action CUSTOMER_SERVICE peut pointer vers le numéro de téléphone de votre service client. Lorsque cette commande passe à l'état IN_TRANSIT, l'action CUSTOMER_SERVICE peut pointer vers le numéro de téléphone du restaurant de traitement.

Envoyer des mises à jour de commandes

Vous utilisez le type de message AsyncOrderUpdateRequestMessage pour envoyer une mise à jour de commande au service Order with Google. Google répond par un AsyncOrderUpdateResponseMessage. Par exemple, si vous souhaitez informer un client que sa commande est valide et acceptée, vous pouvez envoyer un AsyncOrderUpdateRequestMessage pour définir l'état de la commande sur CONFIRMED avec le libellé Accepted by restaurant.

Schéma de mise à jour de la commande

Définir le message de mise à jour de la commande

Lorsque vous envoyez une requête AsyncOrderUpdateRequestMessage à Google, vous devez inclure des informations sur l'état de la commande à l'aide du champ OrderUpdate.

Les exemples suivants illustrent un exemple de AsyncOrderUpdateRequestMessage pour chaque état de la commande:

CONFIRMÉ

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur que la commande est confirmée avec un reçu et une date de livraison estimée.

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

REFUSÉE

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur du refus de la commande.

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

CANCELLED

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur que la commande est annulée pour un motif d'annulation.

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

EN_PRÉPARATION

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur que le plat est en cours de préparation.

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

PRÊT POUR LE RETRAIT

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur que le plat est prêt à être retiré.

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

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur que la commande est en cours d'acheminement avec un délai de livraison estimé.

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

TERMINÉE

Cet exemple présente un exemple de requête de mise à jour de commande qui informe l'utilisateur que la commande est retirée ou livrée:

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

Pour obtenir d'autres exemples de demandes de mise à jour de commandes dans différents cas d'utilisation, consultez Implémenter des mises à jour avancées des commandes.

Générer un jeton d'autorisation et envoyer le message

Les mises à jour de commandes nécessitent un jeton d'autorisation afin que le service Order with Google puisse vérifier que le message provient de votre service Web Order with Google.

Pour implémenter des mises à jour de commandes pour votre projet, procédez comme suit:

  1. Générez un jeton d'autorisation en procédant comme suit :
    1. Utilisez la bibliothèque Google Auth pour lire les identifiants à partir du fichier de votre compte de service.
    2. Jeton de requête à l'aide du champ d'application d'API suivant : https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. Utilisez ce jeton pour envoyer une requête HTTP POST authentifiée au point de terminaison suivant: https://actions.googleapis.com/v2/conversations:send
  3. Définissez l'en-tête Content-Type sur application/json dans votre requête.

Les exemples suivants montrent comment implémenter les mises à jour de commandes:

Node.js

Ce code utilise la bibliothèque d'authentification Google pour 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

Ce code utilise la bibliothèque d'authentification Google pour Python.

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

Ce code utilise la bibliothèque d'authentification Google pour Java.

/**
 * 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",);
}
    

Pour les mises à jour de commande réussies sans erreur, Google renvoie une réponse HTTP 200 avec une charge utile vide. En cas de problème, par exemple une mise à jour incorrecte, Google renvoie une erreur.