Réservations de compilation (Dialogflow)

Ce guide vous accompagne tout au long du processus de développement d'un projet Actions. qui utilise Orders API pour effectuer des réservations.

Flux de transactions

Lorsque votre projet Actions gère les réservations, utilise le flux suivant:

  1. Valider les exigences concernant les transactions (facultatif) : utilisez l'outil d'aide. au début de la conversation pour vous assurer que l'utilisateur est capable effectuer une transaction.
  2. Créer l'ordre : guidez l'utilisateur tout au long d'une "montage chariot" où il construit les détails de sa réservation.
  3. Proposez la commande : une fois le panier est terminée, proposez la réservation "order" à l’utilisateur, afin qu’il puisse confirmer qu’elle est correcte. Si la réservation est confirmée, reçoivent une réponse avec les détails de la réservation.
  4. Finalisez la commande et envoyez un reçu : une fois la commande confirmée, mettez à jour votre système de réservation et envoyer un reçu pour l'utilisateur.
  5. Envoyer des mises à jour de la commande : au cours de la durée de vie de la réservation, des mises à jour de l'état de la réservation de l'utilisateur en envoyant des requêtes PATCH au Orders API.

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 compte de ce temps lors de la planification de votre calendrier de publication. Pour faciliter le processus d'examen, assurez-vous de respecter les Règles et consignes relatives aux transactions avant d'envoyer votre action pour examen.

Vous ne pouvez déployer des actions qui utilisent Orders API 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 des exemples complets de conversations transactionnelles, consultez nos exemples de transactions dans Node.js et Java.

Configuration du projet

Lorsque vous créez votre action, vous devez indiquer que vous souhaitez effectuer des transactions dans la console Actions. De plus, si vous à l'aide de la bibliothèque cliente Node.JS, configurez votre fulfillment pour utiliser la dernière version d'Orders API.

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

  1. Créez un projet ou importez un projet existant.
  2. Accédez à Déployer > Informations de l'annuaire.
  3. Sous Informations supplémentaires > Transactions > cochez la case "Do your Actions (Actions utiliser l'API Transactions pour effectuer des transactions de biens physiques.

  4. Si vous utilisez la bibliothèque cliente Node.JS pour créer le fulfillment de votre action, ouvrez votre code de fulfillment et mettez à jour la délégation de votre application pour définir l'indicateur ordersv3 sur true. L'extrait de code suivant montre un exemple d'application pour Orders version 3.

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. Valider les exigences concernant les transactions (facultatif)

Expérience utilisateur

Dès que l'utilisateur a indiqué qu'il souhaite configurer une réservation, nous vous recommandons de déclencher actions.intent.TRANSACTION_REQUIREMENTS_CHECK pour s'assurer qu'ils peuvent une réservation. Par exemple, lorsqu'elle est appelée, votre action peut demander : « voudriez-vous réserver une place ? » Si l'utilisateur dit "yes", vous devez demander cet intent immédiatement. Ainsi, vous aurez la garantie qu'il peut continuer et lui donner la possibilité de corriger les paramètres l’empêchant de poursuivre la transaction.

Demander les transactions L'intent de vérification des exigences aboutit à l'un des résultats suivants:

  • Si les conditions sont remplies, le fulfillment reçoit un intent avec une et vous pouvez passer à la création de la commande de l'utilisateur.
  • Si une ou plusieurs des conditions requises ne le sont pas, votre traitement reçoit l'intent avec une condition d'échec. Dans ce cas, mettez fin à la conversation ou ne s'éloigne pas du flux de réservation.

    Si l'utilisateur peut corriger l'erreur, il est automatiquement invité à le faire. sur leur appareil. Si la conversation se déroule sur une surface vocale uniquement comme une enceinte intelligente, elle est transmise sur le téléphone de l'utilisateur.

Fulfillment

Pour s’assurer qu’un utilisateur répond aux les exigences relatives aux transactions, le traitement des l'intent actions.intent.TRANSACTION_REQUIREMENTS_CHECK avec une Un objet TransactionRequirementsCheckSpec.

Vérifier les exigences

Vérifiez si un utilisateur satisfait aux exigences de réservation à l'aide de la bibliothèque cliente:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
conv.ask(new TransactionRequirements());
<ph type="x-smartling-placeholder">
</ph>
Java
return getResponseBuilder(request)
    .add("Placeholder for transaction requirements text")
    .add(new TransactionRequirements())
    .build();
<ph type="x-smartling-placeholder">
</ph>
JSON Dialogflow

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK",
        "data": {
          "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec"
        }
      }
    }
  }
}
<ph type="x-smartling-placeholder">
</ph>
JSON SDK Actions

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK",
          "inputValueData": {
            "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec"
          }
        }
      ]
    }
  ]
}
Recevoir le résultat d'une vérification des exigences

Une fois que l'Assistant a traité l'intent, il envoie une requête à votre traitement. avec l'intent actions.intent.TRANSACTION_REQUIREMENTS_CHECK et le résultat. de la vérification.

Pour traiter correctement cette requête, déclarez un intent Dialogflow déclenché par l'événement actions_intent_TRANSACTION_REQUIREMENTS_CHECK. Lorsqu'elle est déclenchée, gérez cet intent dans votre traitement:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
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.');
}
<ph type="x-smartling-placeholder">
</ph>
Java
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();
<ph type="x-smartling-placeholder">
</ph>
JSON Dialogflow

Notez que le code JSON ci-dessous décrit une requête webhook.

{
  "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": ""
}
<ph type="x-smartling-placeholder">
</ph>
JSON SDK Actions

Notez que le code JSON ci-dessous décrit une requête webhook.

{
  "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. Créer la commande

Expérience utilisateur

Une fois que vous avez les informations utilisateur dont vous avez besoin, construisez un « panier assemblage" expérience qui guide l'utilisateur dans la création de sa réservation. Toutes les Le processus d'assemblage du chariot varie légèrement en fonction des Google Cloud.

Dans une expérience de base d'assemblage du panier, un utilisateur sélectionne des options dans une liste à ajouter à leur réservation, mais vous pouvez concevoir la conversation de façon à simplifier l'expérience utilisateur. Par exemple, créez une expérience d'assemblage de chariot qui permet au de planifier une réservation mensuelle avec une simple question par oui ou non. Vous pouvez également présenter à l'utilisateur une fiche de carrousel ou de liste "recommandé" des réservations.

Nous vous recommandons d'utiliser les des réponses pour présenter les options visuellement, mais aussi de concevoir la conversation afin que l’utilisateur puisse construire son panier par simple commande vocale. Pour découvrir quelques bonnes pratiques et des exemples d'assemblage du panier, consultez les consignes de conception des transactions.

Fulfillment

Tout au long de votre conversation, recueillez les détails de la réservation qu'un utilisateur souhaite d'acheter, puis de construire un objet Order.

Votre Order doit au moins contenir les éléments suivants:

  • buyerInfo : informations sur l'utilisateur qui planifie la réservation.
  • transactionMerchant : informations sur le marchand qui facilite la réservation.
  • contents : détails réels de la réservation indiqués en tant que lineItems.

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

L'exemple de code ci-dessous montre une commande de réservation complète, avec des champs facultatifs:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
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',
  };
<ph type="x-smartling-placeholder">
</ph>
Java
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;
}
<ph type="x-smartling-placeholder">
</ph>
JSON

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "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. Proposer l'ordre

Présentez l'ordre de réservation à l'utilisateur pour qu'il la confirme ou refuser. Demander le actions.intent.TRANSACTION_DECISION et fournir le Order que vous avez créé.

Expérience utilisateur

Lorsque vous demandez l'intent actions.intent.TRANSACTION_DECISION, l'Assistant lance une expérience intégrée dans laquelle Order est directement sur une "fiche d'aperçu du panier". L'utilisateur peut dire « planifier une réservation », refuser la transaction ou demander de modifier les détails de la réservation.

À ce stade, 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 après terminer l’expérience d’assemblage du chariot.

Fulfillment

Lorsque vous demandez Intent actions.intent.TRANSACTION_DECISION, créer un TransactionDecision contenant le Order et orderOptions

Le code suivant montre un exemple de TransactionsDecision pour une commande:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
conv.ask(new TransactionDecision({
  orderOptions: {
    requestDeliveryAddress: 'false',
  },
  presentationOptions: {
    actionDisplayName: 'RESERVE',
  },
  order: order,
}));
<ph type="x-smartling-placeholder">
</ph>
Java
// 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();
<ph type="x-smartling-placeholder">
</ph>
JSON Dialogflow

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "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"
          }
        }
      }
    }
  }
}
<ph type="x-smartling-placeholder">
</ph>
JSON SDK Actions

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "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"
            }
          }
        }
      ]
    }
  ]
}
Gérer la décision de l'utilisateur

Une fois que l'utilisateur a répondu à la commande proposée, votre traitement reçoit la L'intent actions_intent_TRANSACTION_DECISION avec un argument contenant un TransactionDecisionValue Cette valeur contiendra les éléments suivants:

  • transactionDecision : décision de l'utilisateur concernant la proposition commande. Les valeurs possibles sont ORDER_ACCEPTED, ORDER_REJECTED, CART_CHANGE_REQUESTED et USER_CANNOT_TRANSACT.

Pour gérer cette requête, déclarez un intent Dialogflow déclenché par l'événement actions_intent_TRANSACTION_DECISION. Gérer cet intent dans votre traitement:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE');
if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') {
  console.log('order accepted');
  const order = arg.order;
}
<ph type="x-smartling-placeholder">
</ph>
Java
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"));
}
<ph type="x-smartling-placeholder">
</ph>
JSON Dialogflow

Notez que le code JSON ci-dessous décrit une requête webhook.

{
  "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": ""
}
<ph type="x-smartling-placeholder">
</ph>
JSON SDK Actions

Notez que le code JSON ci-dessous décrit une requête webhook.

{
  "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. Finaliser la réservation et envoyer un reçu

Lorsque l'intent actions.intent.TRANSACTION_DECISION est renvoyé avec une transactionDecision de ORDER_ACCEPTED, vous pouvez effectuer n'importe quelle un traitement est nécessaire pour planifier la réservation (comme sa persistance votre propre base de données).

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

Fulfillment

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
// 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,
}));
<ph type="x-smartling-placeholder">
</ph>
Java
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();
<ph type="x-smartling-placeholder">
</ph>
JSON Dialogflow

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "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"
                }
              }
            }
          }
        ]
      }
    }
  }
}
<ph type="x-smartling-placeholder">
</ph>
JSON SDK Actions

Notez que le code JSON ci-dessous décrit une réponse webhook.

{
  "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. Envoyer des mises à jour de commande

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

Configurer des requêtes asynchrones dans Orders API

Les requêtes de mise à jour de commandes envoyées à Orders API sont autorisées par un accès à partir d'un jeton d'accès. Pour valider une mise à jour de commande dans Orders API, téléchargez un fichier JSON la clé de compte de service associée à votre projet dans la console Actions, puis la clé la clé du compte de service pour un jeton de support pouvant être transmis 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 ▾ > 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 votre code de mise à jour des commandes, é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 &quot;https://www.googleapis.com/auth/actions.order.developer&quot;. Vous trouverez les étapes d'installation et sur la page GitHub de la bibliothèque cliente de l'API.

Référencer order-update.js dans nos exemples Node.js et Java pour est un exemple d'échange de clés.

Envoyer des mises à jour de commande

Après avoir échangé votre clé de compte de service contre un jeton de support OAuth, envoyez les mises à jour de commandes en tant que requêtes PATCH autorisées à l'API Orders

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

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

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

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

{ "orderUpdate": OrderUpdate }

OrderUpdate comporte 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 contenu de la réservation, définissez sa valeur sur l'objet Order mis à jour. Si vous ne faites que mettre à jour l'état de la réservation (par exemple, "PENDING" à "FULFILLED"), l'objet contient les champs suivants:

    • merchantOrderId : ID que vous avez défini dans l'objet Order.
    • lastUpdateTime : code temporel de cette mise à jour.
    • purchase : objet contenant les éléments suivants : <ph type="x-smartling-placeholder">
        </ph>
      • status : état de la commande (ReservationStatus). tel que "CONFIRMED" ou "CANCELLED".
      • userVisibleStatusLabel : libellé visible par l'utilisateur fournissant des informations sur l'état de la commande, par exemple "Votre réservation est confirmée".
  • userNotification (facultatif) – A userNotification qui peut s'afficher sur l'appareil de l'utilisateur lors de l'envoi de cette mise à jour. Remarque que l'inclusion de cet objet ne garantit pas l'affichage d'une notification l'appareil de l'utilisateur.

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

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Node.js
// 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;
        }
    });
});
<ph type="x-smartling-placeholder">
</ph>
Java
// 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);
Définir l'état de la réservation

ReservationStatus de la mise à jour d'une commande doit décrire l'état actuel de l'ordonnance. Dans les 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é réalisée par le service.
  • CHANGE_REQUESTED : l'utilisateur a demandé à modifier la réservation. Cette modification est en cours de traitement.
  • REJECTED - Si vous n'avez pas pu traiter confirmer la réservation.

Envoyez des notifications de commande pour chaque état pertinent pour votre réservation. Par exemple, si votre réservation nécessite un traitement manuel pour confirmer la réservation après sa demande, envoyer une mise à jour de la commande PENDING jusqu'au qu'un traitement supplémentaire est effectué. Toutes les réservations ne nécessitent pas toutes les valeurs d'état.

Dépannage

Si vous rencontrez des problèmes lors des tests, consultez notre procédure de dépannage. pour les transactions.