非同期オーダー更新

お客様が料理の注文を送信した後、Order with Google サービスに注文更新メッセージを送信して、Google に変更を通知できます。

注文の更新を送信する一般的な理由は次のとおりです。

  • 注文の配送予定時間が利用可能になるか、変わる。
  • 注文の状態は変わります。
  • ご注文の処理はできなくなりました。
  • 注文に含まれるメニュー項目の価格が変更されました。
  • 顧客は、カスタマー サポートやレストランの電話番号など、注文を管理する新しい方法を利用できます。
  • 注文の領収書が利用できるようになります。

以降のセクションでは、注文の更新を使用してこれらのさまざまなシナリオに対処する方法について説明します。

移行状態

注文には次の 6 つのステータスがあります。次の図は、これらの状態と可能な遷移の概要を示しています。

注文の状態遷移

お客様が初めて注文を送信すると、その注文のステータスは CREATEDCONFIRMED、または REJECTED から始まります。状態遷移が有効である限り、注文更新メッセージを送信して注文の状態を更新できます。CREATED 状態は、パートナーのプラットフォームが注文をすぐに確認または拒否できない場合に使用します。ユースケースの例としては、顧客がデリバリー アグリゲータを使用して注文する場合が挙げられます。配送アグリゲータは Google から配信を受け取り、その情報をアグリゲータがレストランに送信します。レストランが注文の受け付けと確認が完了すると、状態は CONFIRMED になります。それ以外の場合は REJECTED になります。

次に、CONFIRMED 状態の注文は IN_PREPARATION 状態に移行します。注文の受け取りと受け取りのどちらのタイプにするかに応じて、READY_FOR_PICKUPIN_TRANSIT のいずれかのステータスを使用します。料理が配達または集荷されると、注文のステータスは FULFILLED に設定されます。

購入者が注文をキャンセルできるようにしている場合は、CANCELLED ステータスを使用できます。CREATEDCONFIRMEDIN_PREPARATIONREADY_FOR_PICKUP、または IN_TRANSIT の状態の間は、注文をキャンセルできます。Order with Google サービスは、キャンセルのポリシーとキャンセル時の支払い状況に応じて払い戻しを行います。

Order with Google サービスは、使用可能なすべての状態と移行をサポートしている必要はありません。ただし、注文の最終状態は FULFILLEDREJECTEDCANCELLED である必要があります

フルフィルメントの目安をお届けする

注文した商品の受け取り(または配送)の準備が整うまでの推定所要時間をユーザーに提示できます。FoodOrderUpdateExtensionestimatedFulfillmentTimeIso8601 フィールドを使用して、お客様の注文の受け取りと配送の準備が整うまでのおおよその期間を指定します。

次の時間に estimatedFulfillmentTimeIso8601 を送信します。

  • 予定時刻が利用可能になったら、CREATED または CONFIRMED の順序ですることをおすすめします。
  • 注文が IN_TRANSIT のときに、より正確な推定時刻を更新するなど、推定時刻が変化した場合。

ユーザーの期待を効果的に管理するには、予測を慎重に行い、固定された日付と時刻ではなく、日付と時刻の範囲を指定します。可能な限り、交通状況などの変動を考慮してください。たとえば、目安のお届け日数が午後 1 時である場合、見積もりの見積もりを午後 12 時 45 分(下限)から午後 1 時 15 分(上限)まで送信できます。

注文管理アクションを提供する

注文の更新を送信する際に、OrderManagementAction の形式で注文を管理できるリソースを顧客に提供できます。注文後、注文の追跡や変更、キャンセルを行うには、注文を行ったショップやレストランに連絡する必要がある場合があります。

OrderManagementAction を使用すると、デバイスでメール、通話、または URL へのリンクを直接行えます。OrderManagementAction には、ユーザーに送信する注文確認と同じ情報を使用します。

注文管理の操作には次のタイプがあります。

  • CUSTOMER_SERVICE: カスタマー サービスに問い合わせるアクションをお客様に提供します。注文を更新する場合は、この管理アクション タイプが必須です。
  • EMAIL: 指定されたメールアドレスにメールを送信するアクションをお客様に提供します。
  • CALL: 指定の電話番号に電話をかけるためのアクションをユーザーに示します。
  • VIEW_DETAIL: 注文の詳細を表示するアクションをお客様に提供します。

各注文更新には、少なくとも 1 つの注文管理アクションが含まれている必要があります。ただし、提供される注文管理アクションは、注文の状態によって異なります。 たとえば、注文のステータスが CONFIRMED の場合、CUSTOMER_SERVICE アクションでカスタマー サービスの電話番号を指定できます。注文ステータスが IN_TRANSIT に更新されると、CUSTOMER_SERVICE アクションでフルフィルメント レストランの電話番号を指定できます。

注文の更新を送信しています

Order with Google サービスに注文の更新を送信するには、AsyncOrderUpdateRequestMessage メッセージ タイプを使用します。Google は AsyncOrderUpdateResponseMessage で応答します。たとえば、注文が有効で受理されたことをお客様に伝えたい場合、AsyncOrderUpdateRequestMessageラベルを送信して、注文の状態をCONFIRMEDAccepted by restaurant」に変更できます。

注文更新の図

注文更新メッセージの設定

AsyncOrderUpdateRequestMessage を Google に送信する際は、OrderUpdate フィールドを使用して注文の状態に関する情報を含める必要があります。

次の例は、注文状態ごとの AsyncOrderUpdateRequestMessage の例を示しています。

CONFIRMED

この例は、領収書と配送予定日で注文が確定されたことをユーザーに通知する注文更新リクエストのサンプルです。

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "CONFIRMED",
        "label": "Provider confirmed"
      },
      "receipt": {
        "userVisibleOrderId": "userVisibleId1234"
      },
      "updateTime": "2017-07-17T12:00:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
        "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601": "2017-07-17T13:00:00Z/2017-07-17T13:30:00Z"
      }
    }
  }
}
    

棄却

次の例は、注文が拒否されたことをユーザーに知らせる、注文更新リクエストのサンプルです。

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "REJECTED",
        "label": "Order rejected"
      },
      "updateTime": "2017-05-10T02:30:00.000Z",
      "rejectionInfo": {
        "type": "UNKNOWN",
        "reason": "Sorry, the restaurant cannot take your order right now."
      },
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
      "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
      "foodOrderErrors": [
        {
        "error": "NO_CAPACITY",
        "description": "Sorry, the restaurant cannot take your order right now."
        }
      ]
      }
    }
  }
}
    

CANCELLED

この例では、注文がキャンセルされた理由をお客様に通知する注文更新リクエストの例を示しています。

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "CANCELLED",
        "label": "Order cancelled"
      },
      "updateTime": "2017-05-10T02:30:00.000Z",
      "cancellationInfo": {
        "reason": "Customer requested"
      },
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ]
    }
  }
}
    

準備中

この例は、現在料理の準備が進行中であることをユーザーに通知する注文更新リクエストのサンプルです。

{
  "isInSandbox":true,
  "customPushMessage":{
    "orderUpdate":{
      "actionOrderId":"sample_action_order_id",
      "orderState":{
        "state":"IN_PREPARATION",
        "label":"Order is being prepared"
      },
      "receipt": {
        "userVisibleOrderId": "userVisibleId1234"
      },
      "updateTime":"2018-04-15T11:30:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension":{
        "@type":"type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601":"PT20M"
      }
    }
  }
}
    

READY_FOR_PICKUP(受け取り / 受け取り)

次の例は、料理の受け取り準備ができたことをユーザーに通知する注文更新リクエストのサンプルです。

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "READY_FOR_PICKUP",
        "label": "Order is ready for pickup"
      },
      "receipt": {
        "userVisibleOrderId": "userVisibleId1234"
      },
      "updateTime": "2018-04-15T12:00:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
        "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601": "PT20M"
      }
    }
  }
}
    

IN_TRANSIT

次の例は、注文が配送中であることをユーザーに伝える通知で、配送予定日を示しています。

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
        "state": "IN_TRANSIT",
        "label": "Order is on the way"
      },
      "inTransitInfo": {
        "updatedTime": "2017-07-17T12:00:00Z"
      },
      "updateTime": "2017-07-17T12:00:00Z",
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ],
      "infoExtension": {
        "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
        "estimatedFulfillmentTimeIso8601": "PT20M"
      }
    }
  }
}
  

FULFILLED

次の例は、注文が集荷または配達されたことをユーザーに通知する注文更新リクエストの例です。

{
  "isInSandbox": true,
  "customPushMessage": {
    "orderUpdate": {
      "actionOrderId": "sample_action_order_id",
      "orderState": {
      "state": "FULFILLED",
      "label": "Order delivered"
      },
      "updateTime": "2017-05-10T02:30:00.000Z",
      "fulfillmentInfo": {
        "deliveryTime": "2017-05-10T02:30:00.000Z"
      },
      "orderManagementActions": [
        {
          "type": "CUSTOMER_SERVICE",
          "button": {
            "title": "Contact customer service",
            "openUrlAction": {
              "url": "mailto:support@example.com"
            }
          }
        },
        {
          "type": "EMAIL",
          "button": {
            "title": "Email restaurant",
            "openUrlAction": {
              "url": "mailto:person@example.com"
            }
          }
        },
        {
          "type": "CALL_RESTAURANT",
          "button": {
            "title": "Call restaurant",
            "openUrlAction": {
              "url": "tel:+16505554679"
            }
          }
        },
        {
          "type": "CALL_DRIVER",
          "button": {
            "title": "Call driver",
            "openUrlAction": {
              "url": "tel:+16505554681"
            }
          }
        }
      ]
    }
  }
}
    

さまざまなユースケースでの注文更新リクエストの例については、注文の高度な更新を実装するをご覧ください。

認証トークンを生成してメッセージを送信する

注文の更新には、Order with Google サービスが Google の Order with Google ウェブサービスから送信されたメッセージであることを確認するために、認証トークンが必要です。

プロジェクトの注文更新を実装する手順は次のとおりです。

  1. 次の手順で認証トークンを生成します。
    1. Google Auth ライブラリを使用して、サービス アカウント ファイルから認証情報を読み取ります。
    2. 次の API スコープを使用してトークンをリクエストします。https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. このトークンを使用して、認証済みの HTTP POST リクエストを次のエンドポイントに送信します。https://actions.googleapis.com/v2/conversations:send
  3. リクエストの一部として、Content-Type ヘッダーを application/json に設定します。

次の例は、注文の更新を実装する方法を示しています。

Node.js

このコードは、Node.js 用の Google 認証ライブラリを使用します。

const {auth} = require('google-auth-library')
const request = require('request');
// The service account client secret file downloaded from the Google Cloud Console
const serviceAccountJson = require('./service-account.json')
// order-update.json is a file that contains the payload
const jsonBody = require('./order-update.json')

/**
 * Get the authorization token using a service account.
 */
async function getAuthToken() {
  let client = auth.fromJSON(serviceAccountJson)
  client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation']
  const tokens = await client.authorize()
  return tokens.access_token;
}

/**
 * Send an order update request
 */
async function sendOrderUpdate() {
  const token = await getAuthToken()
  request.post({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    url: 'https://actions.googleapis.com/v2/conversations:send',
    body: jsonBody,
    json: true
  },
  (err, res, body) => {
    if (err) { return console.log(err); }
    console.log(`Response: ${JSON.stringify(res)}`)
  })
}
    

Python

このコードは、Python 用の Google 認証ライブラリを使用します。

from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
import json

# service-account.json is the service account client secret file downloaded from the
# Google Cloud Console
credentials = service_account.Credentials.from_service_account_file(
    'service-account.json')

scoped_credentials = credentials.with_scopes(
    ['https://www.googleapis.com/auth/actions.fulfillment.conversation'])

authed_session = AuthorizedSession(scoped_credentials)

# order-update.json is a file that contains the payload
json_payload=json.load(open('order-update.json'))

response = authed_session.post(
    'https://actions.googleapis.com/v2/conversations:send',
    json=json_payload)
    

Java

このコードは、Java 用の Google 認証ライブラリを使用します。

/**
 * Get the authorization token using a service account.
 */
private static String getAuthToken() {
  InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json");
  ServiceAccountCredentials.Builder credentialsSimpleBuilder =
      ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder();
  credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/actions.fulfillment.conversation"));
  AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken();
  return accessToken.getTokenValue();
}

/**
 * Send an order update request
 */
public void sendOrderUpdate() {
  String authToken = getAuthToken();
  // Execute POST request
  executePostRequest("https://actions.googleapis.com/v2/conversations:send",
      authToken, "update_order_example.json",);
}
    

注文が正常に更新されるとエラーがない場合は、ペイロードが空の HTTP 200 レスポンスが返されます。アップデートの形式が正しくないなどの問題があると、Google はエラーを返します。