Создавайте физические транзакции с помощью Google Pay

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

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

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

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

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

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

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

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

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

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

Настраивать

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

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

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

1. Сбор информации (необязательно)

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

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

Создать сцену проверки требований к транзакции
  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: >-
                You are ready to purchase physical goods.
    
  6. В разделе «Переход» выберите другую сцену, позволяющую пользователю продолжить разговор и приступить к совершению транзакции.

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

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

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

Запросить адрес доставки

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

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

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

При настройке слота вы можете указать reason , которая позволит вам предварять запрос Ассистента на получение адреса строкой. Строка причины по умолчанию — «знать, куда отправить заказ». Поэтому Ассистент может спросить пользователя: «Чтобы знать, куда отправить заказ, мне нужно узнать ваш адрес доставки».

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

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

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

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

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

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Great! Your order will be delivered to
                $session.params.TransactionDeliveryAddress.location.postalAddress.locality
                $session.params.TransactionDeliveryAddress.location.postalAddress.administrativeArea
                $session.params.TransactionDeliveryAddress.location.postalAddress.regionCode
                $session.params.TransactionDeliveryAddress.location.postalAddress.postalCode
    
  6. В разделе «Переход» выберите другую сцену, позволяющую пользователю продолжить разговор.

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

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

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

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

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

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

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

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

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

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

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

Обратитесь к документации по ответу 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: 'Pizza',
        description: 'A four cheese pizza.',
        priceAttributes: [
          {
            type: 'REGULAR',
            name: 'Item Price',
            state: 'ACTUAL',
            amount: {
              currencyCode: 'USD',
              amountInMicros: 8990000,
            },
            taxIncluded: true,
          },
          {
            type: 'TOTAL',
            name: 'Total Price',
            state: 'ACTUAL',
            amount: {
              currencyCode: 'USD',
              amountInMicros: 9990000,
            },
            taxIncluded: true,
          },
        ],
        notes: [
          'Extra cheese.',
        ],
        purchase: {
          quantity: 1,
          unitMeasure: {
            measure: 1,
            unit: 'POUND',
          },
          itemOptions: [
            {
              id: 'ITEM_OPTION_ID',
              name: 'Pepperoni',
              prices: [
                {
                  type: 'REGULAR',
                  state: 'ACTUAL',
                  name: 'Item Price',
                  amount: {
                    currencyCode: 'USD',
                    amountInMicros: 1000000,
                  },
                  taxIncluded: true,
                },
                {
                  type: 'TOTAL',
                  name: 'Total Price',
                  state: 'ACTUAL',
                  amount: {
                    currencyCode: 'USD',
                    amountInMicros: 1000000,
                  },
                  taxIncluded: true,
                },
              ],
              note: 'Extra pepperoni',
              quantity: 1,
              subOptions: [],
            },
          ],
        },
      },
    ],
  },
  buyerInfo: {
    email: 'janedoe@gmail.com',
    firstName: 'Jane',
    lastName: 'Doe',
    displayName: 'Jane Doe',
  },
  priceAttributes: [
    {
      type: 'SUBTOTAL',
      name: 'Subtotal',
      state: 'ESTIMATE',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 9990000,
      },
      taxIncluded: true,
    },
    {
      type: 'DELIVERY',
      name: 'Delivery',
      state: 'ACTUAL',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 2000000,
      },
      taxIncluded: true,
    },
    {
      type: 'TAX',
      name: 'Tax',
      state: 'ESTIMATE',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 3780000,
      },
      taxIncluded: true,
    },
    {
      type: 'TOTAL',
      name: 'Total Price',
      state: 'ESTIMATE',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 15770000,
      },
      taxIncluded: true,
    },
  ],
  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',
  note: 'Sale event',
  promotions: [
    {
      coupon: 'COUPON_CODE',
    },
  ],
  purchase: {
    status: 'CREATED',
    userVisibleStatusLabel: 'CREATED',
    type: 'FOOD',
    returnsInfo: {
      isReturnable: false,
      daysToReturn: 1,
      policyUrl: 'http://www.example.com',
    },
    fulfillmentInfo: {
      id: 'FULFILLMENT_SERVICE_ID',
      fulfillmentType: 'DELIVERY',
      expectedFulfillmentTime: {
        timeIso8601: '2019-09-25T18:00:00.877Z',
      },
      location: location,
      price: {
        type: 'REGULAR',
        name: 'Delivery Price',
        state: 'ACTUAL',
        amount: {
          currencyCode: 'USD',
          amountInMicros: 2000000,
        },
        taxIncluded: true,
      },
      fulfillmentContact: {
        email: 'johnjohnson@gmail.com',
        firstName: 'John',
        lastName: 'Johnson',
        displayName: 'John Johnson',
      },
    },
    purchaseLocationType: 'ONLINE_PURCHASE',
  },
};

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

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

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

const orderOptions = {
      'requestDeliveryAddress': true,
      'userInfoOptions': {
        'userInfoProperties': ['EMAIL']
      }
    };

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

Создать параметры платежа

Ваш объект paymentParameters будет включать параметры токенизации, которые изменяются в зависимости от того, какой процессор Google Pay вы планируете использовать (например, Stripe, Braintree, ACI и т. д.).

const paymentParamenters = {
      'googlePaymentOption': {
        // facilitationSpec is expected to be a serialized JSON string
        'facilitationSpec': JSON.stringify({
          'apiVersion': 2,
          'apiVersionMinor': 0,
          'merchantInfo': {
            'merchantName': 'Example Merchant',
          },
          'allowedPaymentMethods': [
            {
              'type': 'CARD',
              'parameters': {
                'allowedAuthMethods': ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
                'allowedCardNetworks': [
                  'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'],
              },
              'tokenizationSpecification': {
                'type': 'PAYMENT_GATEWAY',
                'parameters': {
                  'gateway': 'example',
                  'gatewayMerchantId': 'exampleGatewayMerchantId',
                },
              },
            },
          ],
          'transactionInfo': {
            'totalPriceStatus': 'FINAL',
            'totalPrice': '15.77',
            'currencyCode': 'USD',
          },
        }),
      },
    };

Содержимое объекта tokenizationSpecification будет разным для каждого платежного шлюза. В следующей таблице показаны параметры, используемые каждым шлюзом:

ПРИМЕР
"parameters": {
  "gateway": "example",
  "gatewayMerchantId": "exampleGatewayMerchantId"
}
МСА
"parameters": {
  "gateway": "aciworldwide",
  "gatewayMerchantId": "YOUR_ENTITY_ID"
}
АДЬЕН
"parameters": {
  "gateway": "adyen",
  "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"
}
АЛЬФА-БАНК
"parameters": {
  "gateway": "alfabank",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUE_MEDIA
"parameters": {
  "gateway": "bluemedia",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
БЛЮСНЭП
"parameters": {
  "gateway": "bluesnap",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
БРЕЙНТРИ
"parameters": {
  "gateway": "braintree",
  "braintree:apiVersion": "v1",
  "braintree:sdkVersion": braintree.client.VERSION,
  "braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID",
  "braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY"
}
CHASE_PAYMENTECH
"parameters": {
  "gateway": "chase",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ACCOUNT_NUMBER"
}
ПРОВЕРИТЬ
"parameters": {
  "gateway": "checkoutltd",
  "gatewayMerchantId": "YOUR_PUBLIC_KEY"
}
ОБЛАЧНЫЕ ПЛАТЕЖИ
"parameters": {
  "gateway": "cloudpayments",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
КИБЕРИСТОЧНИК
"parameters": {
  "gateway": "cybersource",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
ДАТАТРАНС
"parameters": {
  "gateway": "datatrans",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
ЭБАНКС
"parameters": {
  "gateway": "ebanx",
  "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY"
}
ПЕРВЫЕ_ДАННЫЕ
"parameters": {
  "gateway": "firstdata",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
ГЛОБАЛЬНЫЕ_ПЛАТЕЖИ
"parameters": {
  "gateway": "globalpayments",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
ГОПАЙ
"parameters": {
  "gateway": "gopay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
ХИТРУСТ
"parameters": {
  "gateway": "hitrustpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
РАЗРЕШЕНИЯ
"parameters": {
  "gateway": "imsolutions",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
ЛИРА
"parameters": {
  "gateway": "lyra",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
MPGS
"parameters": {
  "gateway": "mpgs",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
MONEY_MAIL_RU
"parameters": {
  "gateway": "moneymailru",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
НЬЮЭБПАЙ
"parameters": {
  "gateway": "newebpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
НЭКСИ
"parameters": {
  "gateway": "nexi",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
НМИ
"parameters": {
  "gateway": "creditcall",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYSAFE
"parameters": {
  "gateway": "paysafe",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
ПАЙТУРА
"parameters": {
  "gateway": "payture",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
ПАЮ
"parameters": {
  "gateway": "payu",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PRZELEWY24
"parameters": {
  "gateway": "przelewy24",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
РБКМАНИ
"parameters": {
  "gateway": "rbkmoney",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
СБЕРБАНК
"parameters": {
  "gateway": "sberbank",
  "gatewayMerchantId": "YOUR_ORGANIZATION_NAME"
}
КВАДРАТ
"parameters": {
  "gateway": "square",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
ПОЛОСКА
"parameters": {
  "gateway": "stripe",
  "stripe:version": "2018-10-31",
  "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY"
}
ТАППАЙ
"parameters": {
  "gateway": "tappay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
Тинькофф
"parameters": {
  "gateway": "tinkoff",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
ЮНИТЕЛЛЕР
"parameters": {
  "gateway": "uniteller",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
ВАНТИВ
"parameters": {
  "gateway": "vantiv",
  "vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID",
  "vantiv:merchantOrderId": "YOUR_ORDER_ID",
  "vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID",
  "vantiv:merchantReportGroup": "*web"
}
ВОРЛПДЕЙ
"parameters": {
  "gateway": "worldpay",
  "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"
}
ЯНДЕКС
"parameters": {
  "gateway": "yandexcheckout",
  "gatewayMerchantId": "YOUR_SHOP_ID"
}

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

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

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

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

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

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

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

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

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

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

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

  • ORDER_ACCEPTED ,
  • ORDER_REJECTED ,
  • DELIVERY_ADDRESS_UPDATED ,
  • 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 order
                $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: Look like you don't want to order anything. 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 , вы должны немедленно выполнить любую обработку, необходимую для «подтверждения» заказа (например, сохранение его в вашей собственной базе данных и взимание платы с пользователя).

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

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

Часть объекта OrderUpdate должна будет содержать объект последующих действий, который проявляется в виде кнопок URL-адресов в нижней части сведений о заказе, которые пользователь может найти в истории заказов Ассистента.

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

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

  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': [
            'purchase.status',
            'purchase.user_visible_status_label'
          ]
        },
        'order': {
          'merchantOrderId': order.merchantOrderId,
          'lastUpdateTime': currentTime,
          'purchase': {
            'status': 'CONFIRMED',
            'userVisibleStatusLabel': 'Order confirmed'
          },
        },
        '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 — поля обновляемого заказа. Чтобы обновить статус заказа, установите значение purchase.status, purchase.userVisibleStatusLabel .
  • order - Содержимое обновления. Если вы обновляете содержимое заказа, установите значение обновленного объекта Order . Если вы обновляете статус заказа (например, с "CONFIRMED" на "SHIPPED" ), объект содержит следующие поля:

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

В следующем образце кода показан пример OrderUpdate , который обновляет статус заказа на DELIVERED :

// 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 order update
const orderUpdate = new OrderUpdate({
    updateMask: {
      paths: [
        'purchase.status',
        'purchase.user_visible_status_label'
      ]
    },
    order: {
      merchantOrderId: orderId, // Specify the ID of the order to update
      lastUpdateTime: new Date().toISOString(),
      purchase: {
        status: 'DELIVERED',
        userVisibleStatusLabel: 'Order delivered',
      },
    },
    reason: 'Order status updated to delivered.',
});

// 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}`);
}
Установить статус покупки

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

  • CREATED — заказ принят пользователем и «создан» с точки зрения вашего действия, но требует ручной обработки на вашем сервере.
  • CONFIRMED – заказ активен и обрабатывается для выполнения.
  • IN_PREPARATION — заказ готовится к отправке/доставке, например, готовится еда или упаковывается товар.
  • READY_FOR_PICKUP — заказ доступен для получения получателем.
  • DELIVERED – заказ доставлен получателю.
  • OUT_OF_STOCK — одного или нескольких товаров в заказе нет в наличии.
  • CHANGE_REQUESTED — Пользователь запросил изменение заказа, изменение находится в обработке.
  • RETURNED — заказ был возвращен пользователем после доставки.
  • REJECTED — если вам не удалось обработать, оплатить или иным образом «активировать» заказ.
  • CANCELLED – заказ отменен пользователем.

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

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

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

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

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

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

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