Создание резерваций

В этом руководстве описывается процесс разработки проекта Actions, который использует API заказов для размещения бронирования.

Поток транзакций

Когда ваш проект Actions обрабатывает резервирование, он использует следующий процесс:

  1. Проверка требований к транзакциям (необязательно) . Используйте помощник по требованиям к транзакциям в начале разговора, чтобы убедиться, что пользователь способен выполнить транзакцию.
  2. Создайте заказ . Проведите пользователя через «сборку корзины», где он формирует детали своего бронирования.
  3. Предложить заказ . Как только «корзина» будет заполнена, предложите пользователю резервирование «заказа», чтобы он мог подтвердить его правильность. Если бронирование подтверждено, вы получите ответ с деталями бронирования.
  4. Завершите заказ и отправьте квитанцию . После подтверждения заказа обновите свою систему бронирования и отправьте пользователю квитанцию.
  5. Отправка обновлений заказов . В течение срока действия резервирования предоставляйте пользователю обновления статуса резервирования, отправляя запросы PATCH в API заказов.

Ограничения и рекомендации по проверке

Имейте в виду, что к Действиям, использующим транзакции и API заказов, применяются дополнительные политики. Проверка действий с транзакциями может занять до шести недель, поэтому учтите это время при планировании графика выпуска. Чтобы облегчить процесс проверки, убедитесь, что вы соблюдаете правила и рекомендации для транзакций, прежде чем отправлять свое действие на проверку.

Вы можете развертывать Действия, использующие Orders API, только в следующих странах:

Австралия
Бразилия
Канада
Индонезия
Япония
Мексика
Катар
Россия
Сингапур
Швейцария
Таиланд
Турция
Великобритания
Соединенные Штаты

Создайте свой проект

Подробный пример транзакционных диалогов можно найти в нашем примере транзакций в Node.js.

Настраивать

При создании своего Действия вы должны указать, что хотите выполнять транзакции в консоли Действия .

Чтобы настроить проект и выполнить его, выполните следующие действия:

  1. Создайте новый проект или импортируйте существующий проект.
  2. Перейдите к «Развертывание» > «Информация о каталоге» .
  3. В разделе «Дополнительная информация» > «Транзакции» > установите флажок «Используют ли ваши действия API транзакций для выполнения транзакций с физическими товарами?».

Проверка требований транзакции (необязательно)

Как только пользователь указал, что желает создать резервирование, вам следует убедиться, что он может запросить резервирование. Например, при вызове ваше Действие может спросить: «Хотите ли вы зарезервировать место?» Если пользователь говорит «да», вы должны убедиться, что он может продолжить, и дать ему возможность исправить любые настройки, мешающие ему продолжить транзакцию. Для этого вам следует перейти к сцене, которая выполняет проверку требований транзакции.

Создать сцену проверки требований к транзакции

  1. На вкладке «Сцены» добавьте новую сцену с именем TransactionRequirementsCheck .
  2. В разделе «Заполнение слотов» нажмите + , чтобы добавить новый слот.
  3. В разделе «Выбор типа» выберите actions.type.TransactionRequirementsCheckResult в качестве типа слота.
  4. В поле имени слота присвойте слоту имя TransactionRequirementsCheck .
  5. Установите флажок Настроить обратную запись значения слота (включено по умолчанию).
  6. Нажмите Сохранить .

Проверка требований транзакции приводит к одному из следующих результатов:

  • Если требования соблюдены, параметру сеанса присваивается условие успеха и можно приступать к построению заказа пользователя.
  • Если одно или несколько требований не могут быть выполнены, параметр сеанса устанавливается с условием сбоя. В этом случае вам следует отвести разговор от транзакционного опыта или завершить разговор.
    • Если какие-либо ошибки, приводящие к состоянию сбоя, могут быть исправлены пользователем, ему будет предложено устранить эти проблемы на своем устройстве. Если разговор происходит на поверхности только для голосовой связи, будет инициирована передача обслуживания на телефон пользователя.

Обработка требований транзакции Проверка результата

  1. На вкладке «Сцены» выберите только что созданную сцену TransactionRequirementsCheck .
  2. В разделе «Условие» нажмите «+» , чтобы добавить новое условие.
  3. В текстовом поле введите следующий синтаксис условия, чтобы проверить условие успеха:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. Наведите курсор на только что добавленное условие и щелкните стрелку вверх, чтобы поместить его перед if scene.slots.status == "FINAL" .

  5. Включите запросы на отправку и предоставьте простое приглашение, сообщающее пользователю, что он готов совершить транзакцию:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Looks like you're good to go!.
    
  6. В разделе «Переход» выберите другую сцену, позволяющую пользователю продолжить разговор и приступить к совершению транзакции.

  7. Выберите условие else if scene.slots.status == "FINAL" .

  8. Включите запросы на отправку и предоставьте простой запрос, сообщающий пользователю, что он не может совершить транзакцию:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. В разделе «Переход» выберите «Завершить разговор» , чтобы завершить разговор, если пользователь не может совершать транзакции.

Создайте порядок

Получив необходимую информацию о пользователе, создайте «сборку корзины», которая поможет пользователю создать резервирование. Для каждого действия будет немного отличаться процесс сборки тележки, соответствующий его сервису.

При базовой сборке корзины пользователь выбирает варианты из списка, чтобы добавить их к своему резервированию, хотя вы можете спланировать диалог так, чтобы упростить взаимодействие с пользователем. Например, создайте интерфейс сборки корзины, который позволит пользователю планировать ежемесячное бронирование с помощью простого вопроса «да» или «нет». Вы также можете предоставить пользователю карусель или список «рекомендуемых» бронирований.

Мы рекомендуем использовать расширенные ответы, чтобы визуально представить варианты пользователя, а также спланировать разговор так, чтобы пользователь мог создавать свою корзину, используя только свой голос. Некоторые рекомендации и примеры сборки тележек см. в Руководстве по проектированию .

Создать заказ

В ходе разговора собирайте сведения о бронировании пользователя, а затем создайте объект Order .

Как минимум ваш Order должен содержать следующее:

  • buyerInfo — Информация о пользователе, совершающем покупку.
  • transactionMerchant — Информация о продавце, который осуществил заказ.
  • contents — фактическое содержимое заказа, указанное как lineItems .

Обратитесь к документации по ответу Order , чтобы создать корзину. Обратите внимание, что вам может потребоваться включить разные поля в зависимости от бронирования.

В приведенном ниже примере кода показан полный заказ на резервирование, включая необязательные поля:

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'
 };

Создание вариантов заказа и представления

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

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

Сохранение данных заказа в параметре сеанса

После выполнения сохраните данные заказа в параметре сеанса. Объект заказа будет использоваться в сценах одного и того же сеанса.

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

Предложить заказ

После создания заказа на резервирование необходимо предоставить его пользователю для подтверждения или отклонения. Для этого вам следует перейти к сцене, которая принимает решение о транзакции.

Создать сцену принятия решения о транзакции

  1. На вкладке «Сцены» добавьте новую сцену с именем TransactionDecision .
  2. В разделе «Заполнение слотов» нажмите + , чтобы добавить новый слот.
  3. В разделе «Выбрать тип» выберите actions.type.TransactionDecisionValue в качестве типа слота.
  4. В поле имени слота дайте слоту имя TransactionDecision .
  5. Установите флажок Настроить обратную запись значения слота (включено по умолчанию).
  6. В разделе «Настроить слот» выберите « Использовать параметр сеанса» в раскрывающемся списке.
  7. В разделе «Настроить слот» введите в текстовое поле имя параметра сеанса, используемого для хранения заказа (т. е. $session.params.order ).
  8. Нажмите Сохранить .

Пытаясь заполнить слот TransactionDecisionValue , Помощник инициирует встроенный процесс, в котором переданный вами Order отображается непосредственно на «карточке предварительного просмотра корзины». Пользователь может сказать «запланировать бронирование», отклонить транзакцию или попросить изменить детали бронирования.

На этом этапе пользователь также может запросить изменения в заказе. В этом случае вам следует убедиться, что ваш отдел выполнения может обрабатывать запросы на изменение заказа после завершения сборки корзины.

Обработка результата решения транзакции

Когда слот TransactionDecisionValue заполнен, ответ пользователя на решение о транзакции будет сохранен в параметре сеанса. Это значение содержит следующее:

  • ORDER_ACCEPTED ,
  • ORDER_REJECTED ,
  • CART_CHANGE_REQUESTED
  • USER_CANNOT_TRANSACT .

Чтобы обработать результат решения транзакции:

  1. На вкладке «Сцены» выберите только что созданную сцену TransactionDecision .
  2. В разделе «Условие» нажмите «+» , чтобы добавить новое условие.
  3. В текстовом поле введите следующий синтаксис условия, чтобы проверить условие успеха:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. Наведите курсор на только что добавленное условие и щелкните стрелку вверх, чтобы поместить его перед if scene.slots.status == "FINAL" .

  5. Включите отправку запросов и предоставьте простое сообщение, сообщающее пользователю, что его бронирование завершено:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your reservation
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. В разделе «Переход» выберите «Завершить разговор» , чтобы завершить разговор.

  7. В разделе «Условие» нажмите «+» , чтобы добавить новое условие.

  8. В текстовом поле введите следующий синтаксис условия, чтобы проверить условия сбоя:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. Наведите курсор на только что добавленное условие и щелкните стрелку вверх, чтобы поместить его перед if scene.slots.status == "FINAL" .

  10. Включите запросы на отправку и предоставьте простое приглашение, сообщающее пользователю, что заказ был отклонен:

    candidates:
      - first_simple:
          variants:
            - speech: Looks like you don't want to set up a reservation. Goodbye.
    
  11. В разделе «Переход» выберите «Завершить разговор» , чтобы завершить разговор.

  12. Выберите условие else if scene.slots.status == "FINAL" .

  13. Включите запросы на отправку и предоставьте простой запрос, сообщающий пользователю, что он не может совершить транзакцию:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. В разделе «Переход» выберите «Завершить разговор» , чтобы завершить разговор, если пользователь не может совершать транзакции.

Завершите бронирование и отправьте квитанцию

Когда слот TransactionDecisionValue возвращает результат ORDER_ACCEPTED , вы должны немедленно выполнить любую обработку, необходимую для планирования резервирования (например, сохранить его в собственной базе данных).

Отправьте простой ответ, чтобы поддержать разговор. Вместе с вашим ответом пользователь получает «свернутую карточку квитанции».

Чтобы отправить первоначальное обновление заказа:

  1. На вкладке «Сцены» выберите сцену TransactionDecision .
  2. В разделе «Условие» выберите условие, которое проверяет успешный результат, ORDER_ACCEPTED :

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. Для этого условия включите «Вызов веб-перехватчика» и укажите имя обработчика намерений, например update_order .

  4. В код вебхука добавьте обработчик намерений для отправки первоначального обновления заказа:

    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'
      }));
    });
    

Отправлять обновления заказов

Статус резервирования меняется в течение срока его действия. Отправьте обновления заказа на резервирование пользователя с помощью HTTP-запросов PATCH в API заказов, содержащих статус заказа и подробную информацию.

Настройте асинхронные запросы к API заказов.

Запросы на обновление заказов к Orders API авторизуются токеном доступа. Чтобы добавить обновление заказа в Orders API, загрузите ключ учетной записи службы JSON, связанный с вашим проектом консоли действий, а затем замените ключ учетной записи службы на токен носителя, который можно передать в заголовок Authorization HTTP-запроса.

Чтобы получить ключ сервисной учетной записи, выполните следующие действия:

  1. В консоли Google Cloud перейдите в Меню ☰ > API и службы > Учетные данные > Создать учетные данные > Ключ учетной записи службы .
  2. В разделе «Учетная запись службы» выберите «Новая учетная запись службы» .
  3. Установите учетную запись службы на service-account .
  4. Установите роль « Проект» > «Владелец» .
  5. Установите тип ключа JSON .
  6. Выберите Создать .
  7. Ключ частной учетной записи службы JSON будет загружен на ваш локальный компьютер.

В коде обновления заказа замените свой сервисный ключ на токен на предъявителя, используя клиентскую библиотеку API Google и область действия «https://www.googleapis.com/auth/actions.order.developer» . Шаги и примеры установки вы можете найти на странице API клиентской библиотеки GitHub .

Ссылка на order-update.js в нашем примере Node.js для примера обмена ключами.

Отправлять обновления заказов

После того как вы заменили ключ своей сервисной учетной записи на токен носителя OAuth, отправьте обновления заказов в виде авторизованных запросов PATCH в Orders API.

URL-адрес API заказов: PATCH https://actions.googleapis.com/v3/orders/${orderId}

Укажите в своем запросе следующие заголовки:

  • "Authorization: Bearer token" с токеном носителя OAuth, на который вы обменяли ключ своей учетной записи службы.
  • "Content-Type: application/json" .

Запрос PATCH должен принимать тело JSON следующего формата:

{ "orderUpdate": OrderUpdate }

Объект OrderUpdate состоит из следующих полей верхнего уровня:

  • updateMask — поля обновляемого заказа. Чтобы обновить статус резервирования, установите значение reservation.status, reservation.userVisibleStatusLabel .
  • order - Содержимое обновления. Если вы обновляете содержимое резервирования, установите значение обновленного объекта Order . Если вы просто обновляете статус резервирования (например, с "PENDING" на "FULFILLED" ), объект содержит следующие поля:

    • merchantOrderId — тот же идентификатор, который вы установили в своем объекте Order .
    • lastUpdateTime — отметка времени этого обновления.
    • purchase — объект, содержащий следующее:
      • status — статус заказа в виде ReservationStatus , например « CONFIRMED » или « CANCELLED ».
      • userVisibleStatusLabel — метка, обращенная к пользователю и предоставляющая подробную информацию о статусе заказа, например «Ваше бронирование подтверждено».
  • userNotification (необязательно) — объект userNotification , который может отображаться на устройстве пользователя при отправке этого обновления. Обратите внимание: включение этого объекта не гарантирует появление уведомления на устройстве пользователя.

В следующем примере кода показан пример OrderUpdate , который обновляет статус заказа на резервирование на 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}`);
}

Установить статус бронирования

ReservationStatus обновления заказа должен описывать текущее состояние заказа. В поле order.ReservationStatus вашего обновления используйте одно из следующих значений:

  • PENDING – бронирование было «создано» вашим действием, но требует дополнительной обработки на вашем сервере.
  • CONFIRMED — бронирование подтверждено в вашей системе планирования.
  • CANCELLED – пользователь отменил бронирование.
  • FULFILLED — бронирование пользователя было выполнено сервисом.
  • CHANGE_REQUESTED — пользователь запросил изменение бронирования, изменение обрабатывается.
  • REJECTED – если вам не удалось обработать или иным образом подтвердить бронирование.

Отправляйте обновления заказов для каждого статуса, соответствующего вашему бронированию. Например, если ваше бронирование требует ручной обработки для подтверждения бронирования после его запроса, отправьте обновление заказа PENDING до тех пор, пока не будет выполнена дополнительная обработка. Не каждое резервирование требует каждого значения статуса.

Проверьте свой проект

При тестировании вашего проекта вы можете включить режим «песочницы» в консоли «Действия», чтобы протестировать свое действие без взимания платы за способ оплаты. Чтобы включить режим песочницы, выполните следующие действия:

  1. В консоли «Действия» нажмите «Тест» в области навигации.
  2. Нажмите «Настройки» .
  3. Включите опцию «Песочница разработки» .

Для физических транзакций вы также можете установить для поля isInSandbox значение true в вашем примере. Это действие эквивалентно включению режима песочницы в консоли «Действия». Чтобы просмотреть фрагмент кода, использующий isInSandbox , см. раздел «Отправка обновлений заказа» .

Поиск неисправностей

Если во время тестирования у вас возникнут какие-либо проблемы, прочтите наши инструкции по устранению неполадок для транзакций.