Créer des réservations

Ce guide vous explique comment développer un projet Actions qui utilise l'API Orders pour effectuer des réservations.

Flux de transactions

Lorsque votre projet Actions gère des réservations, il suit le flux suivant:

  1. Valider les exigences de transaction (facultatif) : Utilisez l'assistant des exigences de transaction au début de la conversation pour vous assurer que l'utilisateur est en mesure d'effectuer une transaction.
  2. Créer la commande : guidez l'utilisateur à travers un "assemblage de panier" dans lequel il crée les détails de sa réservation.
  3. Proposez la commande : une fois le "panier" terminé, proposez la "commande" de la réservation à l'utilisateur afin qu'il puisse confirmer qu'elle est correcte. Si la réservation est confirmée, vous recevez une réponse contenant les détails de la réservation.
  4. Finaliser la commande et envoyer un reçu : une fois la commande confirmée, mettez à jour votre système de réservation et envoyez un reçu à l'utilisateur.
  5. Envoyer des mises à jour de commande : au cours de la durée de vie de la réservation, informez l'utilisateur des mises à jour de l'état de la réservation en envoyant des requêtes PATCH à l'API Orders.

Restrictions et consignes relatives aux avis

N'oubliez pas que des règles supplémentaires s'appliquent aux actions qui utilisent les transactions et Orders API. L'examen des actions avec transactions peut prendre jusqu'à six semaines. Tenez-en compte lorsque vous planifiez votre calendrier de lancement. Pour faciliter le processus d'examen, assurez-vous de respecter les Règles et consignes concernant les transactions avant d'envoyer votre action pour examen.

Vous ne pouvez déployer des actions qui utilisent l'API Orders que dans les pays suivants:

Australie
Brésil
Canada
Indonésie
Japon
Mexique
Qatar
Russie
Singapour
Suisse
Thaïlande
Turquie
Royaume-Uni
États-Unis

Compiler votre projet

Pour obtenir un exemple complet de conversations transactionnelles, consultez notre exemple de transactions dans Node.js.

Prérequis

Lors de la création de votre action, vous devez indiquer que vous souhaitez effectuer des transactions dans la console Actions.

Pour configurer votre projet et votre traitement, procédez comme suit:

  1. Créez un projet ou importez un projet existant.
  2. Accédez à Déployer > Informations sur le répertoire.
  3. Sous Informations supplémentaires > Transactions, cochez la case "Vos actions utilisent-ils l'API Transactions pour effectuer des transactions de biens physiques ?".

Valider les exigences de transaction (facultatif)

Dès que l'utilisateur a indiqué vouloir configurer une réservation, vous devez vérifier qu'il peut demander une réservation. Par exemple, lorsqu'elle est appelée, votre action peut demander : "Voulez-vous réserver une place ?". Si l'utilisateur répond "Oui", vous devez vous assurer qu'il peut continuer et lui donner la possibilité de corriger les paramètres qui l'empêchent de poursuivre la transaction. Pour ce faire, vous devez passer à une scène qui effectue une vérification des exigences de la transaction.

Créer une scène de vérification des exigences de transaction

  1. Dans l'onglet Scenes (Scènes), ajoutez une scène nommée TransactionRequirementsCheck.
  2. Sous Remplissage de cases, cliquez sur + pour ajouter un emplacement.
  3. Sous Sélectionner un type, sélectionnez actions.type.TransactionRequirementsCheckResult comme type d'emplacement.
  4. Dans le champ du nom de l'emplacement, nommez l'emplacement TransactionRequirementsCheck.
  5. Cochez la case Personnaliser l'écriture des valeurs d'emplacement (option activée par défaut).
  6. Cliquez sur Enregistrer.

Une vérification des exigences de transaction entraîne l'un des résultats suivants:

  • Si les conditions sont remplies, le paramètre de session est défini avec une condition de réussite, et vous pouvez continuer à créer la commande de l'utilisateur.
  • Si une ou plusieurs des conditions ne peuvent pas être remplies, le paramètre de session est défini avec une condition d'échec. Dans ce cas, vous devez détourner la conversation de l'expérience transactionnelle ou mettre fin à la conversation.
    • Si l'utilisateur peut corriger les erreurs entraînant l'état d'échec, il sera invité à le faire sur son appareil. Si la conversation se déroule sur une surface vocale uniquement, un transfert est lancé vers le téléphone de l'utilisateur.

Gérer le résultat de la vérification des exigences de transaction

  1. Dans l'onglet Scenes (Scènes), sélectionnez la scène TransactionRequirementsCheck que vous venez de créer.
  2. Sous Condition, cliquez sur + pour ajouter une condition.
  3. Dans le champ de texte, saisissez la syntaxe de condition suivante pour vérifier la condition de réussite:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  5. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il est prêt à effectuer une transaction:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Looks like you're good to go!.
    
  6. Sous Transition, sélectionnez une autre scène pour permettre à l'utilisateur de poursuivre la conversation et d'effectuer une transaction.

  7. Sélectionnez la condition else if scene.slots.status == "FINAL".

  8. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il ne peut pas effectuer de transaction:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. Sous Transition, sélectionnez End conversation (Terminer la conversation) pour mettre fin à la conversation si un utilisateur ne parvient pas à effectuer de transactions.

Créer la commande

Une fois que vous disposez des informations utilisateur dont vous avez besoin, créez une expérience d'assemblage du panier qui guide l'utilisateur pour créer sa réservation. Chaque action est associée à un flux d'assemblage de panier légèrement différent en fonction du service.

Dans une expérience d'assemblage de panier de base, un utilisateur sélectionne des options dans une liste à ajouter à sa réservation, mais vous pouvez concevoir la conversation pour simplifier l'expérience utilisateur. Par exemple, vous pouvez créer une expérience d'assemblage de chariots qui permet à l'utilisateur de planifier une réservation mensuelle à l'aide d'une simple question "oui" ou "non". Vous pouvez également présenter à l'utilisateur une fiche de type carrousel ou liste de réservations "recommandées".

Nous vous recommandons d'utiliser des réponses enrichies pour présenter visuellement les options à l'utilisateur, mais également de concevoir la conversation de sorte que l'utilisateur puisse créer son panier en utilisant uniquement sa voix. Pour découvrir des bonnes pratiques et des exemples d'expérience d'assemblage de paniers, consultez les consignes de conception.

Créer une commande

Tout au long de votre conversation, rassemblez les détails de la réservation de l'utilisateur, puis créez un objet Order.

Votre fichier Order doit au minimum contenir les éléments suivants:

  • buyerInfo : informations sur l'utilisateur effectuant l'achat.
  • transactionMerchant : informations sur le marchand qui a géré la commande.
  • contents : contenu réel de la commande indiquée sous la forme lineItems.

Consultez la documentation concernant la réponse Order pour créer votre panier. Notez que vous devrez peut-être inclure différents champs en fonction de la réservation.

L'exemple de code ci-dessous montre un ordre de réservation complet, avec des champs facultatifs:

const order = {
   createTime: '2019-09-24T18:00:00.877Z',
   lastUpdateTime: '2019-09-24T18:00:00.877Z',
   merchantOrderId: orderId, // A unique ID String for the order
   userVisibleOrderId: orderId,
   transactionMerchant: {
     id: 'http://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: 'http://example.com',
       },
     },
     {
       type: 'CALL',
       title: 'Call us',
       openUrlAction: {
         url: 'tel:+16501112222',
       },
     },
     {
       type: 'EMAIL',
       title: 'Email us',
       openUrlAction: {
         url: 'mailto:person@example.com',
       },
     },
   ],
   termsOfServiceUrl: 'http://www.example.com'
 };

Créer des options de commande et de présentation

const orderOptions = {
      'requestDeliveryAddress': false,
    };

const presentationOptions = {
      'actionDisplayName': 'RESERVE'
    };

Enregistrer les données de commande dans le paramètre de session

À partir du traitement, enregistrez les données de la commande dans un paramètre de session. L'objet order sera utilisé dans toutes les scènes de la même session.

conv.session.params.order = {
    '@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
    order: order,
    orderOptions: orderOptions,
    presentationOptions: presentationOptions
};

Proposer la commande

Une fois que vous avez créé un ordre de réservation, vous devez le présenter à l'utilisateur pour qu'il le confirme ou le refuse. Pour ce faire, vous devez passer à une scène qui effectue une décision de transaction.

Créer une scène de décision de transaction

  1. Dans l'onglet Scenes (Scènes), ajoutez une scène nommée TransactionDecision.
  2. Sous Remplissage de cases, cliquez sur + pour ajouter un emplacement.
  3. Sous Select type (Sélectionner un type), sélectionnez actions.type.TransactionDecisionValue comme type d'emplacement.
  4. Dans le champ du nom de l'emplacement, nommez l'emplacement TransactionDecision.
  5. Cochez la case Personnaliser l'écriture des valeurs d'emplacement (option activée par défaut).
  6. Sous Configurer l'emplacement, sélectionnez Utiliser le paramètre de session dans le menu déroulant.
  7. Sous Configurer l'emplacement, saisissez le nom du paramètre de session utilisé pour stocker la commande dans le champ de texte (par exemple, $session.params.order).
  8. Cliquez sur Enregistrer.

Pour tenter de remplir un emplacement TransactionDecisionValue, l'Assistant lance une expérience intégrée dans laquelle le Order que vous avez transmis s'affiche directement sur une "carte d'aperçu du panier". L'utilisateur peut dire "planifier la réservation", refuser la transaction ou demander à modifier les détails de la réservation.

L'utilisateur peut également demander à modifier la commande. Dans ce cas, vous devez vous assurer que votre traitement peut traiter les demandes de modification de commande une fois l'expérience d'assemblage du panier terminée.

Gérer le résultat de la décision de transaction

Lorsqu'un emplacement TransactionDecisionValue est rempli, la réponse de l'utilisateur à la décision concernant la transaction est stockée dans un paramètre de session. Cette valeur contient les éléments suivants:

  • ORDER_ACCEPTED,
  • ORDER_REJECTED,
  • CART_CHANGE_REQUESTED
  • USER_CANNOT_TRANSACT.

Pour gérer le résultat d'une décision de transaction:

  1. Dans l'onglet Scenes (Scènes), sélectionnez la scène TransactionDecision que vous venez de créer.
  2. Sous Condition, cliquez sur + pour ajouter une condition.
  3. Dans le champ de texte, saisissez la syntaxe de condition suivante pour vérifier la condition de réussite:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  5. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur que sa réservation est terminée:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your reservation
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. Sous Transition, sélectionnez Terminer la conversation pour mettre fin à la conversation.

  7. Sous Condition, cliquez sur + pour ajouter une condition.

  8. Dans le champ de texte, saisissez la syntaxe de condition suivante pour vérifier les conditions d'échec:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  10. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur que la commande a été refusée:

    candidates:
      - first_simple:
          variants:
            - speech: Looks like you don't want to set up a reservation. Goodbye.
    
  11. Sous Transition, sélectionnez Terminer la conversation pour mettre fin à la conversation.

  12. Sélectionnez la condition else if scene.slots.status == "FINAL".

  13. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il ne peut pas effectuer de transaction:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. Sous Transition, sélectionnez End conversation (Terminer la conversation) pour mettre fin à la conversation si un utilisateur ne parvient pas à effectuer de transactions.

Finaliser la réservation et envoyer un reçu

Lorsque l'emplacement TransactionDecisionValue renvoie le résultat ORDER_ACCEPTED, vous devez immédiatement effectuer le traitement nécessaire pour planifier la réservation (comme la conserver dans votre propre base de données).

Envoyez une réponse simple pour alimenter la conversation. L'utilisateur reçoit une "fiche de reçu réduite" avec votre réponse.

Pour envoyer une première mise à jour de la commande:

  1. Dans l'onglet Scenes (Scènes), sélectionnez votre scène TransactionDecision.
  2. Sous Condition, sélectionnez la condition qui vérifie le résultat de réussite, ORDER_ACCEPTED:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. Pour cette condition, activez Appeler votre webhook et indiquez un nom de gestionnaire d'intent, tel que update_order.

  4. Dans le code de webhook, ajoutez un gestionnaire d'intents pour envoyer une première mise à jour de la commande:

    app.handle('update_order', conv => {
      const currentTime = new Date().toISOString();
      let order = conv.session.params.TransactionDecision.order;
      conv.add(new OrderUpdate({
        'updateMask': {
          'paths': [
            'reservation.status',
            'reservation.user_visible_status_label',
            'reservation.confirmation_code'
          ]
        },
        'order': {
          'merchantOrderId': order.merchantOrderId,
          'lastUpdateTime': currentTime,
          'reservation': {
            'status': 'CONFIRMED',
            'userVisibleStatusLabel': 'Reservation confirmed',
            'confirmationCode': '123ABCDEFGXYZ',
          },
        },
        'reason': 'Reason string'
      }));
    });
    

Envoyer des mises à jour de commande

L'état de la réservation change au cours de sa durée de vie. Envoyez à l'API Orders des mises à jour de l'ordre de réservation de l'utilisateur avec des requêtes HTTP PATCH, contenant l'état et les détails de la commande.

Configurer des requêtes asynchrones vers Orders API

Les requêtes de mise à jour de commande adressées à Orders API sont autorisées par un jeton d'accès. Pour PATCH une mise à jour de commande dans l'API Orders, téléchargez une clé de compte de service JSON associée à votre projet dans la console Actions, puis échangez-la contre un jeton de support qui peut être transmis dans l'en-tête Authorization de la requête HTTP.

Pour récupérer la clé de votre compte de service, procédez comme suit:

  1. Dans la console Google Cloud, accédez à Menu Dataproc > API et services > Identifiants > Créer des identifiants > Clé de compte de service.
  2. Sous Compte de service, sélectionnez Nouveau compte de service.
  3. Définissez le compte de service sur service-account.
  4. Définissez Rôle sur Projet > Propriétaire.
  5. Définissez le type de clé sur JSON.
  6. Sélectionnez Créer.
  7. Une clé de compte de service JSON privée sera téléchargée sur votre ordinateur local.

Dans le code de mise à jour de votre commande, échangez votre clé de service contre un jeton de support à l'aide de la bibliothèque cliente des API Google et du champ d'application "https://www.googleapis.com/auth/actions.order.developer". Vous trouverez la procédure d'installation et des exemples sur la page GitHub de la bibliothèque cliente de l'API.

Reportez-vous à order-update.js dans notre exemple Node.js pour voir un exemple d'échange de clés.

Envoyer des mises à jour de commande

Une fois que vous avez échangé votre clé de compte de service contre un jeton de support OAuth, envoyez des mises à jour de commande en tant que requêtes PATCH autorisées à Orders API.

URL de l'API Orders: PATCH https://actions.googleapis.com/v3/orders/${orderId}

Fournissez les en-têtes suivants dans votre requête:

  • "Authorization: Bearer token" par le jeton de support OAuth pour lequel vous avez échangé votre clé de compte de service.
  • "Content-Type: application/json".

La requête PATCH doit prendre un corps JSON au format suivant:

{ "orderUpdate": OrderUpdate }

L'objet OrderUpdate comprend les champs de niveau supérieur suivants:

  • updateMask : champs de la commande que vous mettez à jour. Pour mettre à jour l'état de la réservation, définissez la valeur sur reservation.status, reservation.userVisibleStatusLabel.
  • order : contenu de la mise à jour. Si vous mettez à jour le contenu de la réservation, définissez la valeur sur l'objet Order mis à jour. Si vous mettez simplement à jour l'état de la réservation (par exemple, de "PENDING" à "FULFILLED"), l'objet contient les champs suivants:

    • merchantOrderId : le même ID que celui défini dans l'objet Order.
    • lastUpdateTime : date et heure de cette mise à jour.
    • purchase : objet contenant les éléments suivants :
      • status : état de la commande sous la forme d'une ReservationStatus (par exemple, CONFIRMED ou CANCELLED).
      • userVisibleStatusLabel : libellé visible par l'utilisateur qui fournit des détails sur l'état de la commande, par exemple "Votre réservation est confirmée".
  • userNotification qui peut s'afficher sur l'appareil de l'utilisateur lorsque cette mise à jour est envoyée. Notez que l'inclusion de cet objet ne garantit pas l'affichage d'une notification sur l'appareil de l'utilisateur.

L'exemple de code suivant montre un exemple de OrderUpdate qui met à jour l'état de l'ordre de réservation sur FULFILLED:

// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request-promise' module for sending an HTTP POST request.
const request = require('request-promise');
// Import the OrderUpdate class from the client library.
const {OrderUpdate} = require('@assistant/conversation');

// Import the service account key used to authorize the request.
// Replacing the string path with a path to your service account key.
// i.e. const serviceAccountKey = 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(
   serviceAccountKey.client_email,
   null,
   serviceAccountKey.private_key,
   ['https://www.googleapis.com/auth/actions.order.developer'],
   null,
);

// Authorize the client
let tokens = await jwtClient.authorize();

// Declare the ID of the order to update.
const orderId = '<UNIQUE_MERCHANT_ORDER_ID>';

// Declare order update
const orderUpdate = new OrderUpdate({
   updateMask: {
     paths: [
       'contents.lineItems.reservation.status',
       'contents.lineItems.reservation.userVisibleStatusLabel'
     ]
   },
   order: {
     merchantOrderId: orderId, // Specify the ID of the order to update
     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.
let options = {
 method: 'PATCH',
 uri: `https://actions.googleapis.com/v3/orders/${orderId}`,
 auth: {
   bearer: tokens.access_token,
 },
 body: {
   header: {
     isInSandbox: true,
   },
   orderUpdate,
 },
 json: true,
};

// Send the PATCH request to the Orders API.
try {
 await request(options);
} catch (e) {
 console.log(`Error: ${e}`);
}

Définir l'état de la réservation

Le ReservationStatus de la mise à jour d'une commande doit décrire l'état actuel de la commande. Dans le champ order.ReservationStatus de votre mise à jour, utilisez l'une des valeurs suivantes:

  • PENDING : la réservation a été "créée" par votre action, mais nécessite un traitement supplémentaire sur votre backend.
  • CONFIRMED : la réservation est confirmée dans votre backend de planification.
  • CANCELLED : l'utilisateur a annulé sa réservation.
  • FULFILLED : la réservation de l'utilisateur a été traitée par le service.
  • CHANGE_REQUESTED : l'utilisateur a demandé une modification de la réservation, et la modification est en cours de traitement.
  • REJECTED - Si vous n'avez pas pu traiter ou confirmer la réservation.

Envoyez des mises à jour de commande pour chaque état pertinent pour votre réservation. Par exemple, si votre réservation nécessite un traitement manuel pour la confirmer après sa demande, envoyez une mise à jour de la commande PENDING jusqu'à ce que ce traitement supplémentaire soit terminé. Toutes les réservations ne nécessitent pas toutes les valeurs d'état.

Tester votre projet

Lorsque vous testez votre projet, vous pouvez activer le mode bac à sable dans la console Actions pour tester votre action sans facturer de mode de paiement. Pour activer le mode bac à sable, procédez comme suit:

  1. Dans la console Actions, cliquez sur Tester dans le menu de navigation.
  2. Cliquez sur Paramètres.
  3. Activez l'option Bac à sable de développement.

Pour les transactions physiques, vous pouvez également définir le champ isInSandbox sur true dans votre exemple. Cette action équivaut à activer le paramètre du mode bac à sable dans la console Actions. Pour voir un extrait de code utilisant isInSandbox, consultez la section Envoyer des informations sur la commande.

Dépannage

Si vous rencontrez des problèmes pendant les tests, consultez nos étapes de dépannage pour les transactions.