Как построить предложенный заказ с тем, что выбрал пользователь? - PullRequest
0 голосов
/ 04 февраля 2019

Я строю проект AOG (действия в Google), который будет выполнять базовые функции транзакций.Так как я все еще немного новичок в AOG, я полностью застрял в том, как взять то, что выбрал пользователь (будь то карусель, базовая карта и т. Д.), И передать значение / ключ аргумента, которые они выбрали, в предложенныйзаказ или предварительный просмотр заказа, прежде чем они завершат свою транзакцию.

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

    app.intent('delivery_address_complete', (conv) => {
       const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE');
       if (arg.userDecision ==='ACCEPTED') {
           conv.ask('Ok, what would you like to order?');
           conv.ask(new Suggestions(intentSuggestions));
           conv.ask(new Carousel({
               items: {
              // Add the first item to the carousel
                  SELECTION_KEY_COFFEE: {
                      synonyms: [
                          'Coffee'
                      ],
                      title: 'Coffee',
                      description: 'Sweet cream and sugar coffee.',
                      image: new Image({
                          url: IMG_URL_COFFEE,
                          alt: 'Image alternate text',
                      }),
              },
         }));

     }
    });


    const yesOrno = [
    'Yes',
    'No'
    ];

    app.intent('actions.intent.OPTION', (conv ) => {
        conv.ask('Okay, are you ready to proceed?');
        conv.ask(new Suggestions(yesOrno));
      });


    app.intent('transaction_decision_action', (conv) => {
      const order = {
       id: UNIQUE_ORDER_ID,
       cart: {
          merchant: {
             id: 'coffee',
        name: 'Coffee Store',
         },
           lineItems: [
           {
              name: 'My Memoirs',
              id: 'coffee_1',
          price: {
            amount: {
                 currencyCode: 'USD',
                 nanos: 990000000,
                 units: 3,
            },
            type: 'ACTUAL',
          },
          quantity: 1,
          subLines: [
            {
              note: 'coffee',
            },
          ],
          type: 'REGULAR',
        },

       otherItems: [
      {
        name: 'Subtotal',
        id: 'subtotal',
        price: {
          amount: {
            currencyCode: 'USD',
            nanos: 220000000,
            units: 32,
          },
          type: 'ESTIMATE',
        },
        type: 'SUBTOTAL',
      },
      {
        name: 'Tax',
        id: 'tax',
        price: {
          amount: {
            currencyCode: 'USD',
            nanos: 780000000,
            units: 2,
          },
          type: 'ESTIMATE',
        },
        type: 'TAX',
      },
    ],
    totalPrice: {
      amount: {
        currencyCode: 'USD',
        nanos: 0,
        units: 35,
      },
      type: 'ESTIMATE',
    },
  };

Обратите внимание: в основном это пустышкакод, так что если происходят какие-то вещи, такие как перерасход или цены, не имеющие смысла, я не пытаюсь решить эту проблему.

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

Если быть более точным:

  • Я могу создать order объект, которыйтребуется, и я знаю, как отправить его в Google (а затем и пользователю) как часть объекта ProposedOrder, который становится частью объекта TransactionDecision.(Обработчик намерений "action_decision_action "в приведенном выше коде.)
  • Чего я не понимаю, так это как построить order на основе того, что пользователь говорит, или выбирает на карусели или в списке элементов, которые я 'мы им показали.(Например, что мне делать в обработчике намерений "actions.intent.OPTION" выше?)

edit: Это также может устранить любую путаницу.Это видео-представление того, что я пытаюсь сделать (упомянуто в комментариях ниже):

  • youtube.com / watch? V = LlgMcJBnNN8 с 1:02 до 1: 29 Я знаю, как это сделать, я в замешательстве (в примере с видео), как они смогли получить «бутерброд с индейкой» и «зеленый смузи», добавленные к предварительному просмотру заказа в 1:35 после выбора карусели

1 Ответ

0 голосов
/ 08 февраля 2019

То, что вы хотите сделать, это то, что Google называет построение заказа .Как видно по этой ссылке

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

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

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

Так что нет единого способа сделать то, о чем вы просите.Тем не менее, есть несколько советов, которые вы можете и должны сделать для создания предлагаемого заказа .

Управление заказом

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

  • В контексте диалогового потока
  • В хранилище сеансов пользователя
  • В базе данных или хранилище данных длясеанс

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

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

Для этого примера мы собираемся пойти по этой последней схеме (потому что еепроще показать) и сохранить его в объекте хранения сеанса с помощью библиотеки actions-on-google.

Итак, для начала, когда мы запускаем действие или когда мы знаем, что примем заказ, мынужно инициализировать наш список предметов, которые заказываются, с помощью чего-то вроде

conv.user.data.items = [];

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

Для некоторых типов заказов может иметь смысл сказать пользователю «У меня все будет как обычно».В подобных случаях нам нужен Intent, который обрабатывает эту фразу (или обрабатывает ответ «да» на наши запросы), и Intent Handler, который просматривает обычный заказ пользователя и добавляет его к элементам.Возможно, что-то вроде этого:

app.intent('order.usual', conv => {
  // Get their user profile from our database
  // The "loadUser" function is up to you, and has little to do with AoG
  return loadUser( conv )
    .then( user => {
      // Add each item in their usual order to the current items
      let usualOrder = user.usualOrder;
      usualOrder.forEach( item => conv.user.data.items.push( item ) );

      // Send a message back to the user
      conv.add( "You got it! Do you want anything else?" );
    });
});

Добавление элемента из списка

Если вы предоставили пользователю карусель или список возможных элементов, вашжизнь немного легче (хотя вы можете не думать об этом в данный момент).Вам нужно настроить намерение Dialogflow, которое обрабатывает событие actions_intent_OPTION (которое в этом случае я назову order.option).

order.option Intent

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

app.intent('order.option', (conv, params, option) => {
  // The item is the option sent
  let item = option;

  // Add the item to the list of items
  conv.user.data.items.push( item );

  // Send a message back to the user
  conv.add( "I've put that in your cart. Anything else?" );
});

Добавление элементапо имени

Но помните, пользователь может вести разговор в любом направлении в любое время.Поэтому они могут попросить предмет, который вы в данный момент не видите в карусели.Лучший способ справиться с этим - создать тип объекта в диалоговом потоке (в качестве примера я назову item)

item Entity Type

Изатем Intent, который захватывает некоторые фразы, выражающие пользователя, который просит добавить их (который я назову order.name и который имеет параметр itemName, который пользователь должен включить).

[Intent[8]

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

app.intent('order.name', (conv, params) => {
  // Get the name
  let itemName = params['itemName'];

  // Look it up to find out what they ordered
  // You need to implement the itemFromName function
  return itemFromName( itemName )
    .then( item => {
      // Add the item
      conv.user.data.items.push( item );

      // And reply
      conv.add( "You got it! Anything else?" );
    });
});

ГотовоПостроение заказа

После того, как вы закончили собирать все, что хотите, ваш обработчик намерений должен упорядочить заказ, собрав полный список lineItems из массива conv.user.data.items, которым мы былисоставление, расчет налога, итогов и всех других частей order.

Затем нам нужно предложить заказ , отправив объект TransactionDecision, который содержит наш заказ в proposedOrder параметр.Умно, нет?Возможно, что-то вроде этого:

app.intent('review', conv => {
  // Get the items the user has saved
  let items = conv.user.data.items;

  // Turn these into more complete lineItems
  // You will need to provide the "itemToLineItem" function
  let lineItems = items.map( itemToLineItem );

  // Get some other objects we need
  // You'll need to define these functions, too
  let orderId = generateOrderId();
  let subtotal = computeSubtotal( lineItems );
  let tax = computeTax( lineItems );
  let total = computerTotal( subtotal, tax );

  // Build the order object
  let order = buildOrder( lineItems, subtotal, tax, total );

  conv.ask(new TransactionDecision({
    orderOptions: {
      requestDeliveryAddress: false,
    },
    paymentOptions: {
      googleProvidedOptions: {
        prepaidCardDisallowed: false,
        supportedCardNetworks: ['VISA', 'AMEX'],
        // These will be provided by payment processor,
        // like Stripe, Braintree, or Vantiv.
        tokenizationParameters: {
          tokenizationType: 'PAYMENT_GATEWAY',
          parameters: {
            'gateway': 'stripe',
            'stripe:publishableKey': (conv.sandbox ? 'pk_test_key' : 'pk_live_key'),
            'stripe:version': '2017-04-06'
          },
        },
      },
    },
    proposedOrder: order,
  }));
});

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

Заключение

Многое из того, что вам нужно сделать, в действительности сводится к

  • Сборинформация о том, что пользователь хочет заказать, в основном сохраняя идентификаторы этих элементов
  • Превращение этого списка элементов в полный объект заказа
  • Отправка этого заказа для просмотра пользователем
...