このガイドでは、サイトで管理されている決済方法で現物商品の取引を行う Actions プロジェクトの開発プロセスについて説明します。
取引の流れ
Actions プロジェクトで販売者が管理する決済方法を使用して現物取引を処理する場合、 次のフローを使用します。
- 情報を収集する(省略可) - データの性質に応じて、
取引の開始時にユーザーから以下の情報を収集します。
クリックします。
<ph type="x-smartling-placeholder">
- </ph>
- 取引要件を検証する - 取引要件ヘルパーを使用します。 ユーザーのお支払い情報を確認し、 ユーザーがカートに入れる前に、正しく設定されて利用可能であるかどうかを確認する必要があります。
- 配送先住所をリクエストする - 取引に配達が必要な場合 住所、配送先住所ヘルパー インテントのフルフィルメントをリクエストする ユーザーから入手します。
- 注文を作成する - お客様に 「カート アセンブリ」ユーザーは購入する商品を選べます
- アカウントのリンクの実施 - ユーザーが支払いを使用できるようにする 追加するには、[アカウントのリンク] を使用します。 Google アカウントとサービス アカウントを関連付けることができます。
- 注文を提案 - カートが完成したら、次に注文を提案します。 正しいことを確認します。注文が確認されると、注文の詳細と支払いトークンを含むレスポンスが届きます。
- 注文を確定して領収書を送信する - 注文が確定されたら、在庫追跡や他の納品サービスを更新し、ユーザーに領収書を送信します。
- 注文の最新情報を送信する - 注文フルフィルメントの期間中は、 Orders に PATCH リクエストを送信して、注文の最新情報をユーザーに提供します API
制限と審査のガイドライン
取引を伴うアクションには追加のポリシーが適用されます。取引を含むアクションのレビューには最大で 6 週間ほどかかります。リリース スケジュールを計画する際は、この点を考慮してください。レビュー プロセスがスムーズに進むよう、レビューにアクションを提出する前に、取引に関するポリシーとガイドラインに準拠していることを確認してください。
現物商品を販売するアクションは次の国でのみデプロイできます。
オーストラリア ブラジル カナダ インドネシア |
日本 メキシコ カタール ロシア |
シンガポール スイス タイ トルコ 英国 米国 |
プロジェクトのビルド
取引に関連する会話の例については、Node.js と Java の取引のサンプルをご覧ください。
プロジェクトの設定
アクションを作成するときは、取引を実行することを指定する必要があります。 Actions Console を使用します。また Node.JS クライアント ライブラリを使用する場合は、最新の Orders API の新しいバージョンです
プロジェクトとフルフィルメントを設定する手順は次のとおりです。
- 新しいプロジェクトを作成するか、既存のプロジェクトをインポートします。
- [デプロイ] > [ディレクトリ情報] の順に移動します。
[その他の情報] >トランザクション >[Do your Actions] というチェックボックスをオンにして 「トランザクション API を使用して物理的な商品の取引を実行する」という質問です。
Node.JS クライアント ライブラリを使用してアクションのフルフィルメントを作成する場合は、 フルフィルメント コードを開き、アプリの宣言を更新して
ordersv3
フラグをtrue
に設定します。次のコード スニペットは、サンプルアプリを示しています。 宣言する必要があります。
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, });
ログインの設定
独自の決済方法でユーザーに請求する場合は、ユーザーの Google アカウントとユーザーがサービスに登録したアカウントをリンクして、サービスに保存されている支払方法の取得、提示、請求を行うことをおすすめします。
OAuth 2.0 アカウント リンクを提供 目的とする 要件があります無駄のないユーザー エクスペリエンスを実現するため、OAuth 2.0 アサーション フローを有効にすることを強くおすすめします。
actions.intent.SIGN_IN
インテントを使用して、リクエストできます。
アカウントをリンクします。必要なこと
アカウントのリンクを有効化
Actions Console を使用して、
actions.intent.SIGN_IN
インテント。
このインテントは、accessToken
が
Webhook リクエストの User
オブジェクト。これは、ユーザーがまだ
アカウントをリンクしました。
actions.intent.SIGN_IN
インテントをリクエストすると、
値が "OK"
の SignInStatus
を含む Argument
"CANCELLED"
、"ERROR"
。ステータスが "OK"
の場合、次の項目が表示されます。
User
オブジェクトの accessToken
。
フルフィルメント
ログインをリクエストする
Node.js
app.intent('Sign In', (conv) => { conv.ask(new SignIn('To get your account details')); });
Node.js
conv.ask(new SignIn('To get your account details'));
Java
@ForIntent("Sign In") public ActionResponse signIn(ActionRequest request) { return getResponseBuilder(request).add( new SignIn() .setContext("To get your account details")) .build(); }
Java
return getResponseBuilder(request).add( new SignIn() .setContext("To get your account details")) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.SIGN_IN", "data": { "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec", "optContext": "To get your account details" } } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.SIGN_IN", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec", "optContext": "To get your account details" } } ] } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }
ログインの結果を受け取る
Node.js
app.intent('Sign In Complete', (conv, params, signin) => { if (signin.status !== 'OK') { conv.ask('You need to sign in before making a transaction.'); } else { const accessToken = conv.user.access.token; // possibly do something with access token conv.ask('You must meet all the requirements necessary ' + 'to make a transaction. Try saying ' + '"check transaction requirements".'); conv.ask(new Suggestions(`check requirements`)); } });
Node.js
app.intent('actions.intent.SIGN_IN', (conv, params, signin) => { if (signin.status !== 'OK') { conv.ask('You need to sign in before making a transaction.'); } else { const accessToken = conv.user.access.token; // possibly do something with access token conv.ask('You must meet all the requirements necessary ' + 'to make a transaction. Try saying ' + '"check transaction requirements".'); conv.ask(new Suggestions(`check requirements`)); } });
Java
@ForIntent("Sign In Complete") public ActionResponse signInComplete(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.isSignInGranted()) { responseBuilder .add("You must meet all the requirements necessary to make a " + "transaction. Try saying \"check transaction requirements\".") .addSuggestions(new String[] { "check requirements" }); } else { responseBuilder.add("You need to sign in before making a transaction."); } return responseBuilder.build(); }
Java
@ForIntent("actions.intent.SIGN_IN") public ActionResponse signInComplete(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.isSignInGranted()) { responseBuilder .add("You must meet all the requirements necessary to make a " + "transaction. Try saying \"check transaction requirements\".") .addSuggestions(new String[] { "check requirements" }); } else { responseBuilder.add("You need to sign in before making a transaction."); } return responseBuilder.build(); }
JSON
{ "responseId": "d2123d8d-3f00-466e-b5a9-1a4ed53a7cb7-594de0a7", "queryResult": { "queryText": "actions_intent_SIGN_IN", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentMessages": [ { "text": { "text": [ "" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/merchant_payment", "lifespanCount": 2 }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/google_assistant_input_type_keyboard" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_sign_in", "parameters": { "SIGN_IN": { "@type": "type.googleapis.com/google.actions.v2.SignInValue", "status": "OK" }, "text": "" } } ], "intent": { "name": "projects/df-transactions/agent/intents/105b925b-b186-4f5d-8bde-a9a782a0fa9f", "displayName": "Sign In Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:18Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.SIGN_IN", "rawInputs": [ { "inputType": "KEYBOARD" } ], "arguments": [ { "name": "SIGN_IN", "extension": { "@type": "type.googleapis.com/google.actions.v2.SignInValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:55:52Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }, "inputs": [ { "intent": "actions.intent.SIGN_IN", "rawInputs": [ {} ], "arguments": [ { "name": "SIGN_IN", "extension": { "@type": "type.googleapis.com/google.actions.v2.SignInValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
1. 情報を収集する(省略可)
1a. 取引要件を確認する(省略可)
ユーザー エクスペリエンス
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
インテントをトリガーします。
ユーザーが取引を実行できるかどうかをすばやく確認できます。この
ユーザーが続行できるようになり、設定を修正する機会が与えられます。
取引を完了できないようにします
たとえば、呼び出されたときに、アクションは 「靴の注文とアカウント残高の確認のどちらをご希望ですか?」お客様の声 このインテントを直ちにリクエストする必要があります。これにより、 必要に応じて設定を修正してもらいます 取引を続行できないようにします
取引要件確認のインテントをリクエストすると、結果は次のいずれかになります。
- 要件を満たしている場合は、成功を示すインテントがフルフィルメントに戻り、ユーザーの注文を続行できます。
- 1 つ以上の要件を満たしていない場合、失敗を示すインテントがフルフィルメントに戻ります。この場合、
会話を終了することもできます。
- 障害状態の原因となったエラーがユーザーによって修正できる場合は、デバイスにプロンプトが表示され、問題を解決するようユーザーに促します。会話が音声のみで行われている場合、ユーザーのスマートフォンにハンドオフされます。
フルフィルメント
ユーザーが次の要件を満たしていることを確認するには、
取引要件、取引要件、取引要件、
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
インテントを
TransactionRequirementsCheckSpec オブジェクト。
要件を確認する
クライアント ライブラリを使用して、ユーザーが取引要件を満たしているかどうかを確認します。
Node.js
conv.ask(new TransactionRequirements());
Node.js
conv.ask(new TransactionRequirements());
Java
return getResponseBuilder(request) .add(new TransactionRequirements()) .build();
Java
return getResponseBuilder(request) .add(new TransactionRequirements()) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec" } } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Looks like you're good to go! Next I'll need your delivery address.Try saying \"get delivery address\"." } } ], "suggestions": [ { "title": "get delivery address" } ] } } } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }
要件確認の結果を受け取る
アシスタントはインテントを実行した後、フルフィルメントにリクエストを送信します
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
インテントを含む
表示されます。このリクエストを適切に処理するには、Dialogflow インテントを宣言します
actions_intent_TRANSACTION_REQUIREMENTS_CHECK
イベントによってトリガーされます。トリガーされたら、クライアント ライブラリを使用してフルフィルメントで処理を行います。
Node.js
app.intent('Transaction Check Complete', (conv) => { 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! ` + `Next I'll need your delivery address.` + `Try saying "get delivery address".`); conv.ask(new Suggestions('get delivery address')); } else { // Exit conversation conv.close('Transaction failed.'); } });
Node.js
app.intent('actions.intent.TRANSACTION_REQUIREMENTS_CHECK', (conv) => { 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! ` + `Next I'll need your delivery address.` + `Try saying "get delivery address".`); conv.ask(new Suggestions('get delivery address')); } else { // Exit conversation conv.close('Transaction failed.'); } });
Java
@ForIntent("Transaction Check Complete") public ActionResponse transactionCheckComplete(ActionRequest request) { LOGGER.info("Checking Transaction Requirements Result."); // Check result of transaction requirements check 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) { // Normally take the user through cart building flow responseBuilder .add("Looks like you're good to go! Next " + "I'll need your delivery address. Try saying " + "\"get delivery address\".") .addSuggestions(new String[]{"get delivery address"}); } else { // Exit conversation responseBuilder.add("Transaction failed."); } return responseBuilder.build(); }
Java
@ForIntent("actions.intent.TRANSACTION_REQUIREMENTS_CHECK") public ActionResponse transactionCheckComplete(ActionRequest request) { LOGGER.info("Checking Transaction Requirements Result."); // Check result of transaction requirements check 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) { // Normally take the user through cart building flow responseBuilder .add("Looks like you're good to go! Next " + "I'll need your delivery address. Try saying " + "\"get delivery address\".") .addSuggestions(new String[]{"get delivery address"}); } else { // Exit conversation responseBuilder.add("Transaction failed."); } return responseBuilder.build(); }
JSON
{ "responseId": "db1a333c-2781-41e3-84b1-cc0cc37643d7-594de0a7", "queryResult": { "queryText": "actions_intent_TRANSACTION_REQUIREMENTS_CHECK", "action": "transaction.check.complete", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Failed to get transaction check results", "fulfillmentMessages": [ { "text": { "text": [ "Failed to get transaction check results" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/google_assistant_input_type_keyboard" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/merchant_payment", "lifespanCount": 1 }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_transaction_requirements_check", "parameters": { "TRANSACTION_REQUIREMENTS_CHECK_RESULT": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" }, "text": "" } } ], "intent": { "name": "projects/df-transactions/agent/intents/fd16d86b-60db-4d19-a683-5b52a22f4795", "displayName": "Transaction Check Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:32Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[\"merchant_payment\"]" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "rawInputs": [ { "inputType": "KEYBOARD" } ], "arguments": [ { "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:56:03Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "rawInputs": [ {} ], "arguments": [ { "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
1b. 配送先住所をリクエストする(省略可)
取引に配送先住所が必要な場合は、
actions.intent.DELIVERY_ADDRESS
インテントのフルフィルメント。これは、合計金額や配達先または商品受け取り場所を決定する場合や、ユーザーがサービス地域内にいることを確認する場合に便利です。
このインテントのフルフィルメントをリクエストするときは、reason
オプションを渡します。これは、
を使用すると、住所を取得するアシスタントのリクエストの前に文字列を記述できます。
たとえば、「注文の配送先を確認するため」と指定した場合、アシスタントは
次のような問いかけが考えられます。
「商品の配送先を確認するため、配送先住所が必要です」
ユーザー エクスペリエンス
画面表示が使用できるサーフェスの場合、ユーザーは取引に使用する住所を選択します。また、住所をまだ指定していない場合は、新しい住所を入力できます。
音声のみのサーフェスの場合、アシスタントは取引でデフォルトの住所を使用するかどうかユーザーに確認します。住所が未設定の場合、情報を入力できるように、会話がスマートフォンにハンドオフされます。
住所をリクエストする
Node.js
app.intent('Delivery Address', (conv) => { conv.ask(new DeliveryAddress({ addressOptions: { reason: 'To know where to send the order', }, })); });
Node.js
conv.ask(new DeliveryAddress({ addressOptions: { reason: 'To know where to send the order', }, }));
Java
@ForIntent("Delivery Address") public ActionResponse deliveryAddress(ActionRequest request) { DeliveryAddressValueSpecAddressOptions addressOptions = new DeliveryAddressValueSpecAddressOptions() .setReason("To know where to send the order"); return getResponseBuilder(request) .add(new DeliveryAddress() .setAddressOptions(addressOptions)) .build(); }
Java
DeliveryAddressValueSpecAddressOptions addressOptions = new DeliveryAddressValueSpecAddressOptions() .setReason("To know where to send the order"); return getResponseBuilder(request) .add(new DeliveryAddress() .setAddressOptions(addressOptions)) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.DELIVERY_ADDRESS", "data": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec", "addressOptions": { "reason": "To know where to send the order" } } } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.DELIVERY_ADDRESS", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec", "addressOptions": { "reason": "To know where to send the order" } } } ] } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }
住所を受け取る
アシスタントはインテントを実行した後、フルフィルメントにリクエストを送信します
actions.intent.DELIVERY_ADDRESS
インテントを使用します。
このリクエストを適切に処理するには、リクエストによってトリガーされる Dialogflow インテントを宣言します。
actions_intent_DELIVERY_ADDRESS
イベント。トリガーされたら、クライアント ライブラリを使用してフルフィルメントで処理を行います。
Node.js
app.intent('Delivery Address Complete', (conv) => { const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE'); if (arg && arg.userDecision ==='ACCEPTED') { conv.data.location = arg.location; conv.ask('Great, got your address! Now say "confirm transaction".'); conv.ask(new Suggestions('confirm transaction')); } else { conv.close('Transaction failed.'); } });
Node.js
app.intent('actions.intent.DELIVERY_ADDRESS', (conv) => { const arg = conv.arguments.get('DELIVERY_ADDRESS_VALUE'); if (arg && arg.userDecision ==='ACCEPTED') { conv.data.location = arg.location; conv.ask('Great, got your address! Now say "confirm transaction".'); conv.ask(new Suggestions('confirm transaction')); } else { conv.close('Transaction failed.'); } });
Java
@ForIntent("Delivery Address Complete") public ActionResponse deliveryAddressComplete(ActionRequest request) { Argument deliveryAddressValue = request.getArgument("DELIVERY_ADDRESS_VALUE"); Location deliveryAddress = null; if (deliveryAddressValue != null) { Map<String, Object> map = deliveryAddressValue.getExtension(); if (map != null) { String userDecision = (String) map.get("userDecision"); Location location = (Location) map.get("location"); deliveryAddress = userDecision != null && userDecision.equals("ACCEPTED") ? location : null; } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (deliveryAddress != null) { // Cache delivery address in conversation data for later use Map<String, Object> conversationData = request.getConversationData(); conversationData.put("location", GSON_BUILDER.create().toJson(deliveryAddress, Location.class)); responseBuilder .add("Great, got your address! Now say \"confirm transaction\".") .addSuggestions(new String[] { "confirm transaction" }); } else { responseBuilder.add("Transaction failed.").endConversation(); } return responseBuilder.build(); }
Java
@ForIntent("actions.intent.DELIVERY_ADDRESS") public ActionResponse deliveryAddressComplete(ActionRequest request) { Argument deliveryAddressValue = request.getArgument("DELIVERY_ADDRESS_VALUE"); Location deliveryAddress = null; if (deliveryAddressValue != null) { Map<String, Object> map = deliveryAddressValue.getExtension(); if (map != null) { String userDecision = (String) map.get("userDecision"); Location location = (Location) map.get("location"); deliveryAddress = userDecision != null && userDecision.equals("ACCEPTED") ? location : null; } } ResponseBuilder responseBuilder = getResponseBuilder(request); if (deliveryAddress != null) { // Cache delivery address in conversation data for later use Map<String, Object> conversationData = request.getConversationData(); conversationData.put("location", GSON_BUILDER.create().toJson(deliveryAddress, Location.class)); responseBuilder .add("Great, got your address! Now say \"confirm transaction\".") .addSuggestions(new String[] { "confirm transaction" }); } else { responseBuilder.add("Transaction failed.").endConversation(); } return responseBuilder.build(); }
JSON
{ "responseId": "58b0c305-b437-47ac-8593-4fb0122a19e6-594de0a7", "queryResult": { "queryText": "actions_intent_DELIVERY_ADDRESS", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentMessages": [ { "text": { "text": [ "" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_delivery_address", "parameters": { "DELIVERY_ADDRESS_VALUE": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue", "userDecision": "ACCEPTED", "location": { "coordinates": { "latitude": 37.432524, "longitude": -122.098545 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" } }, "text": "1600 AMPHITHEATRE PKWY" } } ], "intent": { "name": "projects/df-transactions/agent/intents/0be5d130-1760-4355-85e9-4dc01da8bf3c", "displayName": "Delivery Address Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:55Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.DELIVERY_ADDRESS", "rawInputs": [ { "query": "1600 AMPHITHEATRE PKWY" } ], "arguments": [ { "name": "DELIVERY_ADDRESS_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue", "userDecision": "ACCEPTED", "location": { "coordinates": { "latitude": 37.432524, "longitude": -122.098545 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" } } } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:57:20Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }, "inputs": [ { "intent": "actions.intent.DELIVERY_ADDRESS", "rawInputs": [ { "inputType": "VOICE", "query": "1600 AMPHITHEATRE PKWY" } ], "arguments": [ { "name": "DELIVERY_ADDRESS_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue", "userDecision": "ACCEPTED", "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" } } }, { "name": "text", "rawText": "1600 AMPHITHEATRE PKWY", "textValue": "1600 AMPHITHEATRE PKWY" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }
2. 注文を作成する
ユーザー エクスペリエンス
必要なユーザー情報を入手したら、カートを作成します。 組み立てます」ユーザーが注文の作成をガイドするエクスペリエンスです。すべてのアクションは カート アセンブリ フローが若干異なる場合があります。 提供します。
最も基本的なカート アセンブリのエクスペリエンスでは、ユーザーがリストから商品を選択して追加する ただし、会話をデザインして簡単に 向上させることができますカート アセンブリのエクスペリエンスを作成し、 ユーザーは「はい」か「いいえ」で答える簡単な質問で、最近購入した商品を再注文できます。 上位の「おすすめ」のカルーセルやリストカードをユーザーに表示することもできます。または 「推奨」あります。
「リッチコンテンツ ユーザーの選択肢を提示する ユーザーが会話をデザインできるようにして 音声だけで操作できますベスト プラクティスと例については、 優れたカート アセンブリ体験を提供するには、 トランザクション設計ガイドライン
フルフィルメント
会話を通じて、ユーザーが求めているものを
購入し、Order
オブジェクトを作成します。
Order
には少なくとも次のものが含まれている必要があります。
buyerInfo
- 商品を購入しようとしているユーザーに関する情報。transactionMerchant
- プロモーションを実施した販売者に関する情報 できます。contents
-lineItems
として列挙される注文の実際の内容。priceAttributes
- 注文の料金の詳細(合計金額など) 割引額と税金を含めた注文額です
Order
レスポンスのドキュメントをご覧ください。
カートを作成します異なるフィールドを含める必要がある場合があります。
表示されます。
次のサンプルコードは、省略可能なフィールドを含む完全な注文を示しています。
Node.js
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', }, };
Node.js
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', }, };
Java
// Transaction Merchant MerchantV3 transactionMerchant = new MerchantV3() .setId("http://www.example.com") .setName("Example Merchant"); // Line Item PriceAttribute itemPrice = new PriceAttribute() .setType("REGULAR") .setName("Item Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(8990000L) ) .setTaxIncluded(true); PriceAttribute totalItemPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); // Purchase Item Extension PurchaseItemExtension purchaseItemExtension = new PurchaseItemExtension() .setQuantity(1) .setUnitMeasure(new MerchantUnitMeasure() .setMeasure(1.0) .setUnit("POUND")) .setItemOptions(Arrays.asList(new PurchaseItemExtensionItemOption() .setId("ITEM_OPTION_ID") .setName("Pepperoni") .setPrices(Arrays.asList( new PriceAttribute() .setType("REGULAR") .setState("ACTUAL") .setName("Item Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true), new PriceAttribute() .setType("TOTAL") .setState("ACTUAL") .setName("Total Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true) )) .setNote("Extra pepperoni") .setQuantity(1))); LineItemV3 lineItem = new LineItemV3() .setId("LINE_ITEM_ID") .setName("Pizza") .setDescription("A four cheese pizza.") .setPriceAttributes(Arrays.asList(itemPrice, totalItemPrice)) .setNotes(Collections.singletonList("Extra cheese.")) .setPurchase(purchaseItemExtension); // 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"); // Price Attributes PriceAttribute subTotal = new PriceAttribute() .setType("SUBTOTAL") .setName("Subtotal") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); PriceAttribute deliveryFee = new PriceAttribute() .setType("DELIVERY") .setName("Delivery") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L) ) .setTaxIncluded(true); PriceAttribute tax = new PriceAttribute() .setType("TAX") .setName("Tax") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(3780000L) ) .setTaxIncluded(true); PriceAttribute totalPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(15770000L) ) .setTaxIncluded(true); // 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 = "http://example.com"; String orderNote = "Sale event"; // Promotions PromotionV3 promotion = new PromotionV3() .setCoupon("COUPON_CODE"); // Purchase Order Extension Location location = GSON_BUILDER.create().fromJson( (String) conversationData.get("location"), Location.class); PurchaseOrderExtension purchaseOrderExtension = new PurchaseOrderExtension() .setStatus("CREATED") .setUserVisibleStatusLabel("CREATED") .setType("FOOD") .setReturnsInfo(new PurchaseReturnsInfo() .setIsReturnable(false) .setDaysToReturn(1) .setPolicyUrl("https://example.com")) .setFulfillmentInfo(new PurchaseFulfillmentInfo() .setId("FULFILLMENT_SERVICE_ID") .setFulfillmentType("DELIVERY") .setExpectedFulfillmentTime(new TimeV3() .setTimeIso8601("2019-09-25T18:00:00.877Z")) .setLocation(location) .setPrice(new PriceAttribute() .setType("REGULAR") .setName("Delivery price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L)) .setTaxIncluded(true)) .setFulfillmentContact(new UserInfo() .setEmail("johnjohnson@gmail.com") .setFirstName("John") .setLastName("Johnson") .setDisplayName("John Johnson"))) .setPurchaseLocationType("ONLINE_PURCHASE"); OrderV3 order = new OrderV3() .setCreateTime("2019-09-24T18:00:00.877Z") .setLastUpdateTime("2019-09-24T18:00:00.877Z") .setMerchantOrderId(orderId) .setUserVisibleOrderId(orderId) .setTransactionMerchant(transactionMerchant) .setContents(contents) .setBuyerInfo(buyerInfo) .setPriceAttributes(Arrays.asList( subTotal, deliveryFee, tax, totalPrice )) .setFollowUpActions(Arrays.asList( viewDetails, call, email )) .setTermsOfServiceUrl(termsOfServiceUrl) .setNote(orderNote) .setPromotions(Collections.singletonList(promotion)) .setPurchase(purchaseOrderExtension);
Java
// Transaction Merchant MerchantV3 transactionMerchant = new MerchantV3() .setId("http://www.example.com") .setName("Example Merchant"); // Line Item PriceAttribute itemPrice = new PriceAttribute() .setType("REGULAR") .setName("Item Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(8990000L) ) .setTaxIncluded(true); PriceAttribute totalItemPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); // Purchase Item Extension PurchaseItemExtension purchaseItemExtension = new PurchaseItemExtension() .setUnitMeasure(new MerchantUnitMeasure() .setMeasure(1.0) .setUnit("POUND")) .setItemOptions(Arrays.asList(new PurchaseItemExtensionItemOption() .setId("ITEM_OPTION_ID") .setName("Pepperoni") .setPrices(Arrays.asList( new PriceAttribute() .setType("REGULAR") .setState("ACTUAL") .setName("Item Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true), new PriceAttribute() .setType("TOTAL") .setState("ACTUAL") .setName("Total Price") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(1000000L)) .setTaxIncluded(true) )) .setNote("Extra pepperoni"))); LineItemV3 lineItem = new LineItemV3() .setId("LINE_ITEM_ID") .setName("Pizza") .setDescription("A four cheese pizza.") .setPriceAttributes(Arrays.asList(itemPrice, totalItemPrice)) .setNotes(Collections.singletonList("Extra cheese.")) .setPurchase(purchaseItemExtension); // 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"); // Price Attributes PriceAttribute subTotal = new PriceAttribute() .setType("SUBTOTAL") .setName("Subtotal") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(9990000L) ) .setTaxIncluded(true); PriceAttribute deliveryFee = new PriceAttribute() .setType("DELIVERY") .setName("Delivery") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L) ) .setTaxIncluded(true); PriceAttribute tax = new PriceAttribute() .setType("TAX") .setName("Tax") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(3780000L) ) .setTaxIncluded(true); PriceAttribute totalPrice = new PriceAttribute() .setType("TOTAL") .setName("Total Price") .setState("ESTIMATE") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(15770000L) ) .setTaxIncluded(true); // 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 = "http://example.com"; String orderNote = "Sale event"; // Promotions PromotionV3 promotion = new PromotionV3() .setCoupon("COUPON_CODE"); // Purchase Order Extension Location location = GSON_BUILDER.create().fromJson( (String) conversationData.get("location"), Location.class); PurchaseOrderExtension purchaseOrderExtension = new PurchaseOrderExtension() .setStatus("CREATED") .setUserVisibleStatusLabel("CREATED") .setType("FOOD") .setReturnsInfo(new PurchaseReturnsInfo() .setIsReturnable(false) .setDaysToReturn(1) .setPolicyUrl("https://example.com")) .setFulfillmentInfo(new PurchaseFulfillmentInfo() .setId("FULFILLMENT_SERVICE_ID") .setFulfillmentType("DELIVERY") .setExpectedFulfillmentTime(new TimeV3() .setTimeIso8601("2019-09-25T18:00:00.877Z")) .setLocation(location) .setPrice(new PriceAttribute() .setType("REGULAR") .setName("Delivery price") .setState("ACTUAL") .setAmount(new MoneyV3() .setCurrencyCode("USD") .setAmountInMicros(2000000L)) .setTaxIncluded(true)) .setFulfillmentContact(new UserInfo() .setEmail("johnjohnson@gmail.com") .setFirstName("John") .setLastName("Johnson") .setDisplayName("John Johnson"))) .setPurchaseLocationType("ONLINE_PURCHASE"); OrderV3 order = new OrderV3() .setCreateTime("2019-09-24T18:00:00.877Z") .setLastUpdateTime("2019-09-24T18:00:00.877Z") .setMerchantOrderId(orderId) .setUserVisibleOrderId(orderId) .setTransactionMerchant(transactionMerchant) .setContents(contents) .setBuyerInfo(buyerInfo) .setPriceAttributes(Arrays.asList( subTotal, deliveryFee, tax, totalPrice )) .setFollowUpActions(Arrays.asList( viewDetails, call, email )) .setTermsOfServiceUrl(termsOfServiceUrl) .setNote(orderNote) .setPromotions(Collections.singletonList(promotion)) .setPurchase(purchaseOrderExtension);
3. アカウント リンクを実行する
独自の決済方法でユーザーに請求する場合は、ユーザーの Google アカウントとユーザーがサービスに登録したアカウントをリンクして、サービスに保存されている支払方法の取得、提示、請求を行うことをおすすめします。
OAuth 2.0 アカウント リンクを提供 目的とする 要件があります無駄のないユーザー エクスペリエンスを実現するため、OAuth 2.0 アサーション フローを有効にすることを強くおすすめします。
actions.intent.SIGN_IN
インテントを使用して、リクエストできます。
アカウントをリンクします。必要なこと
アカウントのリンクを有効化
Actions Console を使用して、
actions.intent.SIGN_IN
インテント。
このインテントは、accessToken
が
Webhook リクエストの User
オブジェクト。これは、ユーザーがまだ
アカウントをリンクしました。
actions.intent.SIGN_IN
インテントをリクエストすると、
値が "OK"
の SignInStatus
を含む Argument
"CANCELLED"
、"ERROR"
。ステータスが "OK"
の場合、次の項目が表示されます。
User
オブジェクトの accessToken
。
フルフィルメント
ログインをリクエストする
Node.js
app.intent('Sign In', (conv) => { conv.ask(new SignIn('To get your account details')); });
Node.js
conv.ask(new SignIn('To get your account details'));
Java
@ForIntent("Sign In") public ActionResponse signIn(ActionRequest request) { return getResponseBuilder(request).add( new SignIn() .setContext("To get your account details")) .build(); }
Java
return getResponseBuilder(request).add( new SignIn() .setContext("To get your account details")) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.SIGN_IN", "data": { "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec", "optContext": "To get your account details" } } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.SIGN_IN", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.SignInValueSpec", "optContext": "To get your account details" } } ] } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }
ログインの結果を受け取る
Node.js
app.intent('Sign In Complete', (conv, params, signin) => { if (signin.status !== 'OK') { conv.ask('You need to sign in before making a transaction.'); } else { const accessToken = conv.user.access.token; // possibly do something with access token conv.ask('You must meet all the requirements necessary ' + 'to make a transaction. Try saying ' + '"check transaction requirements".'); conv.ask(new Suggestions(`check requirements`)); } });
Node.js
app.intent('actions.intent.SIGN_IN', (conv, params, signin) => { if (signin.status !== 'OK') { conv.ask('You need to sign in before making a transaction.'); } else { const accessToken = conv.user.access.token; // possibly do something with access token conv.ask('You must meet all the requirements necessary ' + 'to make a transaction. Try saying ' + '"check transaction requirements".'); conv.ask(new Suggestions(`check requirements`)); } });
Java
@ForIntent("Sign In Complete") public ActionResponse signInComplete(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.isSignInGranted()) { responseBuilder .add("You must meet all the requirements necessary to make a " + "transaction. Try saying \"check transaction requirements\".") .addSuggestions(new String[] { "check requirements" }); } else { responseBuilder.add("You need to sign in before making a transaction."); } return responseBuilder.build(); }
Java
@ForIntent("actions.intent.SIGN_IN") public ActionResponse signInComplete(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.isSignInGranted()) { responseBuilder .add("You must meet all the requirements necessary to make a " + "transaction. Try saying \"check transaction requirements\".") .addSuggestions(new String[] { "check requirements" }); } else { responseBuilder.add("You need to sign in before making a transaction."); } return responseBuilder.build(); }
JSON
{ "responseId": "d2123d8d-3f00-466e-b5a9-1a4ed53a7cb7-594de0a7", "queryResult": { "queryText": "actions_intent_SIGN_IN", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentMessages": [ { "text": { "text": [ "" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/merchant_payment", "lifespanCount": 2 }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/google_assistant_input_type_keyboard" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_sign_in", "parameters": { "SIGN_IN": { "@type": "type.googleapis.com/google.actions.v2.SignInValue", "status": "OK" }, "text": "" } } ], "intent": { "name": "projects/df-transactions/agent/intents/105b925b-b186-4f5d-8bde-a9a782a0fa9f", "displayName": "Sign In Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:18Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.SIGN_IN", "rawInputs": [ { "inputType": "KEYBOARD" } ], "arguments": [ { "name": "SIGN_IN", "extension": { "@type": "type.googleapis.com/google.actions.v2.SignInValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:55:52Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\"}}" }, "inputs": [ { "intent": "actions.intent.SIGN_IN", "rawInputs": [ {} ], "arguments": [ { "name": "SIGN_IN", "extension": { "@type": "type.googleapis.com/google.actions.v2.SignInValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
4. 注文内容を表示する
注文を作成したら、ユーザーが注文を確定または拒否できる場面を用意する必要があります。actions.intent.TRANSACTION_DECISION
をリクエストする
ユーザーの保存済みの支払い情報を使用して、作成した注文を通知します。
情報です。
ユーザー エクスペリエンス
actions.intent.TRANSACTION_DECISION
インテントをリクエストすると、アシスタントは
が組み込みエクスペリエンスを開始します。この組み込みエクスペリエンスでは、渡した Order
が
「カートのプレビュー カード」に直接レンダリングされます。ユーザーは「注文して」と言うと
取引を拒否する、クレジット カードなどのお支払い方法を変更する、
注文内容の変更をリクエストすることもできます。
ユーザーはこの時点で注文内容の変更をリクエストできます。この例では 変更後は、フルフィルメントが注文変更リクエストを処理できることを確認してください。 カートの組み立て作業を完了します
フルフィルメント
actions.intent.TRANSACTION_DECISION
インテントをリクエストした場合は、
Order
を含む TransactionDecision
orderOptions
と paymentParameters
。paymentParameters
オブジェクトには、ユーザーの ID について記述するフィールドを持つ merchantPaymentOption
が
。
次のコードは、支払いを伴う注文に対する TransactionsDecision
の例を示しています。
Visa クレジット カードを使用する:
Node.js
conv.ask(new TransactionDecision({ orderOptions: { userInfoOptions: { userInfoProperties: [ 'EMAIL', ], }, }, paymentParameters: { merchantPaymentOption: { defaultMerchantPaymentMethodId: '12345678', managePaymentMethodUrl: 'https://example.com/managePayment', merchantPaymentMethod: [ { paymentMethodDisplayInfo: { paymentMethodDisplayName: 'VISA **** 1234', paymentType: 'PAYMENT_CARD', }, paymentMethodGroup: 'Payment method group', paymentMethodId: '12345678', paymentMethodStatus: { status: 'STATUS_OK', statusMessage: 'Status message', }, }, ], }, }, presentationOptions: { actionDisplayName: 'PLACE_ORDER', }, order: order, }));
Node.js
conv.ask(new TransactionDecision({ orderOptions: { userInfoOptions: { userInfoProperties: [ 'EMAIL', ], }, }, paymentParameters: { merchantPaymentOption: { defaultMerchantPaymentMethodId: '12345678', managePaymentMethodUrl: 'https://example.com/managePayment', merchantPaymentMethod: [ { paymentMethodDisplayInfo: { paymentMethodDisplayName: 'VISA **** 1234', paymentType: 'PAYMENT_CARD', }, paymentMethodGroup: 'Payment method group', paymentMethodId: '12345678', paymentMethodStatus: { status: 'STATUS_OK', statusMessage: 'Status message', }, }, ], }, }, presentationOptions: { actionDisplayName: 'PLACE_ORDER', }, order: order, }));
Java
// Create order options OrderOptionsV3 orderOptions = new OrderOptionsV3() .setUserInfoOptions(new UserInfoOptions() .setUserInfoProperties(Collections.singletonList("EMAIL"))); // Create presentation options PresentationOptionsV3 presentationOptions = new PresentationOptionsV3() .setActionDisplayName("PLACE_ORDER"); // Create payment parameters MerchantPaymentMethod merchantPaymentMethod = new MerchantPaymentMethod() .setPaymentMethodDisplayInfo(new PaymentMethodDisplayInfo() .setPaymentMethodDisplayName("VISA **** 1234") .setPaymentType("PAYMENT_CARD")) .setPaymentMethodGroup("Payment method group") .setPaymentMethodId("12345678") .setPaymentMethodStatus(new PaymentMethodStatus() .setStatus("STATUS_OK") .setStatusMessage("Status message")); MerchantPaymentOption merchantPaymentOption = new MerchantPaymentOption() .setDefaultMerchantPaymentMethodId("12345678") .setManagePaymentMethodUrl("https://example.com/managePayment") .setMerchantPaymentMethod(Collections.singletonList(merchantPaymentMethod)); paymentParameters.setMerchantPaymentOption(merchantPaymentOption); return getResponseBuilder(request) .add(new TransactionDecision() .setOrder(order) .setOrderOptions(orderOptions) .setPresentationOptions(presentationOptions) .setPaymentParameters(paymentParameters) ) .build();
Java
// Create order options OrderOptionsV3 orderOptions = new OrderOptionsV3() .setUserInfoOptions(new UserInfoOptions() .setUserInfoProperties(Collections.singletonList("EMAIL"))); // Create presentation options PresentationOptionsV3 presentationOptions = new PresentationOptionsV3() .setActionDisplayName("PLACE_ORDER"); // Create payment parameters MerchantPaymentMethod merchantPaymentMethod = new MerchantPaymentMethod() .setPaymentMethodDisplayInfo(new PaymentMethodDisplayInfo() .setPaymentMethodDisplayName("VISA **** 1234") .setPaymentType("PAYMENT_CARD")) .setPaymentMethodGroup("Payment method group") .setPaymentMethodId("12345678") .setPaymentMethodStatus(new PaymentMethodStatus() .setStatus("STATUS_OK") .setStatusMessage("Status message")); MerchantPaymentOption merchantPaymentOption = new MerchantPaymentOption() .setDefaultMerchantPaymentMethodId("12345678") .setManagePaymentMethodUrl("https://example.com/managePayment") .setMerchantPaymentMethod(Collections.singletonList(merchantPaymentMethod)); paymentParameters.setMerchantPaymentOption(merchantPaymentOption); return getResponseBuilder(request) .add(new TransactionDecision() .setOrder(order) .setOrderOptions(orderOptions) .setPresentationOptions(presentationOptions) .setPaymentParameters(paymentParameters) ) .build();
JSON
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction Decision Placeholder." } } ] }, "systemIntent": { "intent": "actions.intent.TRANSACTION_DECISION", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "userInfoOptions": { "userInfoProperties": [ "EMAIL" ] } }, "paymentParameters": { "merchantPaymentOption": { "defaultMerchantPaymentMethodId": "12345678", "managePaymentMethodUrl": "https://example.com/managePayment", "merchantPaymentMethod": [ { "paymentMethodDisplayInfo": { "paymentMethodDisplayName": "VISA **** 1234", "paymentType": "PAYMENT_CARD" }, "paymentMethodGroup": "Payment method group", "paymentMethodId": "12345678", "paymentMethodStatus": { "status": "STATUS_OK", "statusMessage": "Status message" } } ] } }, "presentationOptions": { "actionDisplayName": "PLACE_ORDER" }, "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "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": { "city": "MOUNTAIN VIEW", "coordinates": { "latitude": 37.432524, "longitude": -122.098545 }, "phoneNumber": "+1 123-456-7890", "postalAddress": { "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "postalCode": "94043-1351", "recipients": [ "John Doe" ], "regionCode": "US" }, "zipCode": "94043-1351" }, "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" } } } } } }, "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/_actions_on_google", "lifespanCount": 99, "parameters": { "data": "{\"location\":{\"coordinates\":{\"latitude\":37.432524,\"longitude\":-122.098545},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}" } } ] }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TRANSACTION_DECISION", "inputValueData": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "userInfoOptions": { "userInfoProperties": [ "EMAIL" ] } }, "paymentParameters": { "merchantPaymentOption": { "defaultMerchantPaymentMethodId": "12345678", "managePaymentMethodUrl": "https://example.com/managePayment", "merchantPaymentMethod": [ { "paymentMethodDisplayInfo": { "paymentMethodDisplayName": "VISA **** 1234", "paymentType": "PAYMENT_CARD" }, "paymentMethodGroup": "Payment method group", "paymentMethodId": "12345678", "paymentMethodStatus": { "status": "STATUS_OK", "statusMessage": "Status message" } } ] } }, "presentationOptions": { "actionDisplayName": "PLACE_ORDER" }, "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "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": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "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" } } } } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction Decision Placeholder." } } ] } } } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\",\"location\":{\"coordinates\":{\"latitude\":37.421578499999995,\"longitude\":-122.0837816},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}}" }
ユーザーの決定を処理する
アシスタントはインテントを実行した後、フルフィルメントにリクエストを送信します
(ユーザーの回答を含む)actions_intent_TRANSACTION_DECISION
インテントを
トランザクションの判断を
要求します通知を受け取ります。
TransactionDecisionValue を含む Argument
。この値には次のものが含まれます。
transactionDecision
- 提案された内容に関するユーザーの判断 できます。指定できる値はORDER_ACCEPTED
、ORDER_REJECTED
、DELIVERY_ADDRESS_UPDATED
さん、CART_CHANGE_REQUESTED
さん、USER_CANNOT_TRANSACT
。deliveryAddress
- 次の場合に更新された配送先住所。 ユーザーが配送先住所を変更した。この場合、transactionDecision
はDELIVERY_ADDRESS_UPDATED
になります。
このリクエストを適切に処理するには、リクエストによってトリガーされる Dialogflow インテントを宣言します。
actions_intent_TRANSACTION_DECISION
イベント。トリガーされたら、
:
Node.js
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE'); if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') { console.log('Order accepted.'); const order = arg.order; }
Node.js
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE'); if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') { console.log('Order accepted.'); const order = arg.order; }
Java
// Check transaction decision value 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"); } ResponseBuilder responseBuilder = getResponseBuilder(request); if ((transactionDecision != null && transactionDecision.equals("ORDER_ACCEPTED"))) { OrderV3 order = ((OrderV3) extension.get("order")); }
Java
// Check transaction decision value 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"); } ResponseBuilder responseBuilder = getResponseBuilder(request); if ((transactionDecision != null && transactionDecision.equals("ORDER_ACCEPTED"))) { OrderV3 order = ((OrderV3) extension.get("order")); }
JSON
{ "responseId": "aba44717-4236-4602-af55-e5ae1fc2d97a-594de0a7", "queryResult": { "queryText": "actions_intent_TRANSACTION_DECISION", "action": "transaction.decision.complete", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Failed to get transaction decision", "fulfillmentMessages": [ { "text": { "text": [ "Failed to get transaction decision" ] } } ], "outputContexts": [ { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_audio_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_account_linking" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_screen_output" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_capability_web_browser" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/google_assistant_input_type_voice" }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/_actions_on_google", "lifespanCount": 97, "parameters": { "data": "{\"location\":{\"coordinates\":{\"latitude\":37.432524,\"longitude\":-122.098545},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"}}" } }, { "name": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy/contexts/actions_intent_transaction_decision", "parameters": { "TRANSACTION_DECISION_VALUE": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue", "transactionDecision": "ORDER_ACCEPTED", "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "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": "Line 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": "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": {}, "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" } } }, "text": "" } } ], "intent": { "name": "projects/df-transactions/agent/intents/fd16d86b-60db-4d19-a683-5b52a22f4795", "displayName": "Transaction Decision Complete" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-09-23T19:49:32Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy", "type": "ACTIVE", "conversationToken": "[\"merchant_payment\"]" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_DECISION", "rawInputs": [ { "inputType": "KEYBOARD" } ], "arguments": [ { "name": "TRANSACTION_DECISION_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue", "transactionDecision": "ORDER_ACCEPTED", "order": { "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T19:00:00.877Z", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "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": "Line 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": "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": {}, "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" } } } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] } }, "session": "projects/df-transactions/agent/sessions/ABwppHGYEP2Fj7tJBxoaKMevL6lZ2rs063lOEWhSW5etZWVOoJe7Dzm_bLejRTYIYXL3D78ER7YvA5aN9Wpy" }
JSON
{ "user": { "locale": "en-US", "lastSeen": "2019-11-11T23:57:31Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGFwStZlYaQ9YT8rg9t_idVsxZrku1pUDrEbGSJmSUMatVdPwPEEQSCe1IwIBoN4sS4Weyn9pmgetEgbsWgw3JSvQmw", "type": "ACTIVE", "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\",\"location\":{\"coordinates\":{\"latitude\":37.421578499999995,\"longitude\":-122.0837816},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}}" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_DECISION", "rawInputs": [ {} ], "arguments": [ { "name": "TRANSACTION_DECISION_VALUE", "extension": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue", "transactionDecision": "ORDER_ACCEPTED", "order": { "googleOrderId": "05528125187071048269", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "buyerInfo": { "email": "janedoe@example.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T18:00:00.877Z", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "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 } ], "description": "A four cheese pizza.", "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "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 } ], "unitMeasure": { "measure": 1, "unit": "POUND" } }, "vertical": { "@type": "type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseItemExtension", "quantity": 1, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "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 } ], "unitMeasure": { "measure": 1, "unit": "POUND" } } } ] }, "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", "paymentData": { "paymentResult": { "merchantPaymentMethodId": "12345678" }, "paymentInfo": { "paymentMethodDisplayInfo": { "paymentType": "PAYMENT_CARD", "paymentMethodDisplayName": "VISA **** 1234" }, "paymentMethodProvenance": "PAYMENT_METHOD_PROVENANCE_MERCHANT" } }, "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CREATED", "type": "FOOD", "returnsInfo": { "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "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", "userVisibleStatusLabel": "CREATED" }, "vertical": { "@type": "type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseOrderExtension", "status": "CREATED", "type": "FOOD", "returnsInfo": { "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "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", "userVisibleStatusLabel": "CREATED" } } } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] } ] }
5. 注文を確定して領収書を送る
actions.intent.TRANSACTION_DECISION
インテントが「
transactionDecision
ORDER_ACCEPTED
に関係なく、
「確認」するために処理が必要になるその順序(たとえば、
ユーザーに請求する
などが考えられます
この回答で会話を終了することもできますが、シンプルな回答を含める必要があります
会話が進みますこの最初の orderUpdate
を指定すると、
折りたたまれた状態の領収書がユーザーに表示されます回答が表示されます
このカードは、ユーザーが後で注文履歴で確認できる領収書とまったく同じものです。
注文の確認時に、注文オブジェクトに userVisibleOrderId
を含めることができます。
ユーザーに表示される注文の IDmerchantOrderId
は再利用できます
指定する必要があります
OrderUpdate の一部 オブジェクトには フォローアップ アクション このオブジェクトは、注文の詳細の下部に URL ボタンとして表されます。 アシスタントの注文履歴で確認できます。
フルフィルメント
Node.js
// Set lastUpdateTime and update status of order const order = arg.order; order.lastUpdateTime = '2019-09-24T19:00:00.877Z'; order.purchase.status = 'CONFIRMED'; order.purchase.userVisibleStatusLabel = 'Order confirmed'; // Send synchronous order update conv.ask(`Transaction completed! Your order` + ` ${conv.data.latestOrderId} is all set!`); conv.ask(new Suggestions('send order update')); conv.ask(new OrderUpdate({ type: 'SNAPSHOT', reason: 'Reason string', order: order, }));
Node.js
// Set lastUpdateTime and update status of order const order = arg.order; order.lastUpdateTime = '2019-09-24T19:00:00.877Z'; order.purchase.status = 'CONFIRMED'; order.purchase.userVisibleStatusLabel = 'Order confirmed'; // Send synchronous order update conv.ask(`Transaction completed! Your order ` + `${conv.data.latestOrderId} is all set!`); conv.ask(new Suggestions('send order update')); conv.ask(new OrderUpdate({ type: 'SNAPSHOT', reason: 'Reason string', order: order, }));
Java
OrderV3 order = ((OrderV3) extension.get("order")); order.setLastUpdateTime("2019-09-24T19:00:00.877Z"); // Update order status PurchaseOrderExtension purchaseOrderExtension = order.getPurchase(); purchaseOrderExtension.setStatus("CONFIRMED"); purchaseOrderExtension.setUserVisibleStatusLabel("Order confirmed"); order.setPurchase(purchaseOrderExtension); // Order update OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setType("SNAPSHOT") .setReason("Reason string") .setOrder(order); Map<String, Object> conversationData = request.getConversationData(); String orderId = (String) conversationData.get("latestOrderId"); responseBuilder .add("Transaction completed! Your order " + orderId + " is all set!") .addSuggestions(new String[] {"send order update"}) .add(new StructuredResponse().setOrderUpdateV3(orderUpdate));
Java
OrderV3 order = ((OrderV3) extension.get("order")); order.setLastUpdateTime("2019-09-24T19:00:00.877Z"); // Update order status PurchaseOrderExtension purchaseOrderExtension = order.getPurchase(); purchaseOrderExtension.setStatus("CONFIRMED"); purchaseOrderExtension.setUserVisibleStatusLabel("Order confirmed"); order.setPurchase(purchaseOrderExtension); // Order update OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setType("SNAPSHOT") .setReason("Reason string") .setOrder(order); Map<String, Object> conversationData = request.getConversationData(); String orderId = (String) conversationData.get("latestOrderId"); responseBuilder .add("Transaction completed! Your order " + orderId + " is all set!") .addSuggestions(new String[] {"send order update"}) .add(new StructuredResponse().setOrderUpdateV3(orderUpdate));
JSON
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! Your order undefined is all set!" } }, { "structuredResponse": { "orderUpdateV3": { "order": { "buyerInfo": { "displayName": "Jane Doe", "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe" }, "contents": { "lineItems": [ { "description": "A four cheese pizza.", "id": "LINE_ITEM_ID", "name": "Pizza", "notes": [ "Extra cheese." ], "priceAttributes": [ { "amount": { "amountInMicros": 8990000, "currencyCode": "USD" }, "name": "Line Item Price", "state": "ACTUAL", "taxIncluded": true, "type": "REGULAR" }, { "amount": { "amountInMicros": 9990000, "currencyCode": "USD" }, "name": "Total Price", "state": "ACTUAL", "taxIncluded": true, "type": "TOTAL" } ], "purchase": { "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "note": "Extra pepperoni", "prices": [ { "amount": { "amountInMicros": 1000000, "currencyCode": "USD" }, "name": "Item Price", "state": "ACTUAL", "taxIncluded": true, "type": "REGULAR" }, { "amount": { "amountInMicros": 1000000, "currencyCode": "USD" }, "name": "Total Price", "state": "ACTUAL", "taxIncluded": true, "type": "TOTAL" } ], "quantity": 1, "subOptions": [] } ], "quantity": 1, "unitMeasure": { "measure": 1, "unit": "POUND" } } } ] }, "createTime": "2019-09-24T18:00:00.877Z", "followUpActions": [ { "openUrlAction": { "url": "http://example.com" }, "title": "View details", "type": "VIEW_DETAILS" }, { "openUrlAction": { "url": "tel:+16501112222" }, "title": "Call us", "type": "CALL" }, { "openUrlAction": { "url": "mailto:person@example.com" }, "title": "Email us", "type": "EMAIL" } ], "lastUpdateTime": "2019-09-24T19:00:00.877Z", "merchantOrderId": "ORDER_ID", "note": "Sale event", "priceAttributes": [ { "amount": { "amountInMicros": 9990000, "currencyCode": "USD" }, "name": "Subtotal", "state": "ESTIMATE", "taxIncluded": true, "type": "SUBTOTAL" }, { "amount": { "amountInMicros": 2000000, "currencyCode": "USD" }, "name": "Delivery", "state": "ACTUAL", "taxIncluded": true, "type": "DELIVERY" }, { "amount": { "amountInMicros": 3780000, "currencyCode": "USD" }, "name": "Tax", "state": "ESTIMATE", "taxIncluded": true, "type": "TAX" }, { "amount": { "amountInMicros": 15770000, "currencyCode": "USD" }, "name": "Total Price", "state": "ESTIMATE", "taxIncluded": true, "type": "TOTAL" } ], "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "fulfillmentInfo": { "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "fulfillmentContact": { "displayName": "John Johnson", "email": "johnjohnson@gmail.com", "firstName": "John", "lastName": "Johnson" }, "fulfillmentType": "DELIVERY", "id": "FULFILLMENT_SERVICE_ID", "location": {}, "price": { "amount": { "amountInMicros": 2000000, "currencyCode": "USD" }, "name": "Delivery Price", "state": "ACTUAL", "taxIncluded": true, "type": "REGULAR" } }, "purchaseLocationType": "ONLINE_PURCHASE", "returnsInfo": { "daysToReturn": 1, "isReturnable": false, "policyUrl": "http://www.example.com" }, "status": "CONFIRMED", "type": "FOOD", "userVisibleStatusLabel": "Order confirmed" }, "termsOfServiceUrl": "www.example.com", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "userVisibleOrderId": "ORDER_ID" }, "reason": "Reason string", "type": "SNAPSHOT" } } } ], "suggestions": [ { "title": "send order update" } ] } } } }
JSON
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! Your order ORDER_ID is all set!" } }, { "structuredResponse": { "orderUpdateV3": { "type": "SNAPSHOT", "reason": "Reason string", "order": { "googleOrderId": "05528125187071048269", "merchantOrderId": "ORDER_ID", "userVisibleOrderId": "ORDER_ID", "buyerInfo": { "email": "janedoe@example.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "createTime": "2019-09-24T18:00:00.877Z", "lastUpdateTime": "2019-09-24T19:00:00.877Z", "transactionMerchant": { "id": "http://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "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 } ], "description": "A four cheese pizza.", "notes": [ "Extra cheese." ], "purchase": { "quantity": 1, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "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 } ], "unitMeasure": { "measure": 1, "unit": "POUND" } }, "vertical": { "@type": "type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseItemExtension", "quantity": 1, "itemOptions": [ { "id": "ITEM_OPTION_ID", "name": "Pepperoni", "prices": [ { "type": "REGULAR", "name": "Item Price", "state": "ACTUAL", "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 } ], "unitMeasure": { "measure": 1, "unit": "POUND" } } } ] }, "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", "paymentData": { "paymentResult": { "merchantPaymentMethodId": "12345678" }, "paymentInfo": { "paymentMethodDisplayInfo": { "paymentType": "PAYMENT_CARD", "paymentMethodDisplayName": "VISA **** 1234" }, "paymentMethodProvenance": "PAYMENT_METHOD_PROVENANCE_MERCHANT" } }, "promotions": [ { "coupon": "COUPON_CODE" } ], "purchase": { "status": "CONFIRMED", "type": "FOOD", "returnsInfo": { "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "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", "userVisibleStatusLabel": "Order confirmed" }, "vertical": { "@type": "type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseOrderExtension", "status": "CREATED", "type": "FOOD", "returnsInfo": { "daysToReturn": 1, "policyUrl": "http://www.example.com" }, "fulfillmentInfo": { "id": "FULFILLMENT_SERVICE_ID", "fulfillmentType": "DELIVERY", "expectedFulfillmentTime": { "timeIso8601": "2019-09-25T18:00:00.877Z" }, "location": { "coordinates": { "latitude": 37.421578499999995, "longitude": -122.0837816 }, "zipCode": "94043-1351", "city": "MOUNTAIN VIEW", "postalAddress": { "regionCode": "US", "postalCode": "94043-1351", "administrativeArea": "CA", "locality": "MOUNTAIN VIEW", "addressLines": [ "1600 AMPHITHEATRE PKWY" ], "recipients": [ "John Doe" ] }, "phoneNumber": "+1 123-456-7890" }, "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", "userVisibleStatusLabel": "CREATED" } } } } } ], "suggestions": [ { "title": "send order update" } ] } } } ], "conversationToken": "{\"data\":{\"paymentType\":\"merchant_payment\",\"location\":{\"coordinates\":{\"latitude\":37.421578499999995,\"longitude\":-122.0837816},\"zipCode\":\"94043-1351\",\"city\":\"MOUNTAIN VIEW\",\"postalAddress\":{\"regionCode\":\"US\",\"postalCode\":\"94043-1351\",\"administrativeArea\":\"CA\",\"locality\":\"MOUNTAIN VIEW\",\"addressLines\":[\"1600 AMPHITHEATRE PKWY\"],\"recipients\":[\"John Doe\"]},\"phoneNumber\":\"+1 123-456-7890\"},\"latestOrderId\":\"ORDER_ID\"}}" }
6. 注文の更新情報を送信する
全期間を通じて、注文のステータスをユーザーに通知し続ける必要があります。HTTP を送信してユーザーの注文の最新情報を送信する 注文のステータスと詳細を含む PATCH リクエストを Orders API に送信します。
Orders API に非同期リクエストを設定する
Orders API への注文更新リクエストはアクセス権によって承認される
あります。Orders API で注文の更新を PATCH するには、JSON をダウンロードしてください。
サービス アカウント キーを使用して ID を交換し、
サービス アカウント キーに、署名なしトークンの
HTTP リクエストの Authorization
ヘッダー。
サービス アカウント キーを取得するには、次の手順に従います。
- Google Cloud コンソールで次の操作を行います。 メニュー 💻? > に移動API とサービス >クルデンシャル >認証情報を作成 >サービス アカウント キー。
- [サービス アカウント] で [新しいサービス アカウント] を選択します。
- サービス アカウントを
service-account
に設定します。 - [役割] を [プロジェクト] > [オーナー] に設定します。
- キータイプを [JSON] に設定します。
- [作成] を選択します。
- 非公開の JSON サービス アカウント キーがローカルマシンにダウンロードされます。
注文更新コードで、サービスキーを署名なしトークンと交換できます Google API クライアント ライブラリと "https://www.googleapis.com/auth/actions.order.developer" スコープを使用します。インストール手順と API クライアント ライブラリの GitHub ページの例。
また、Node.js と Java のサンプルで order-update.js
を参照することもできます。
鍵交換の例を見てみましょう。
注文の更新情報を送信する
サービス アカウント キーを OAuth 署名なしトークンと交換したら、 承認済みの PATCH リクエストとして注文の更新情報を Orders API に送信できます。
Orders API の URL:
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
- 更新の内容。Deployment を更新する場合は、 更新したOrder
オブジェクトに値を設定します。 注文のステータスを更新する場合(例:"CONFIRMED"
から"SHIPPED"
など)、オブジェクトには 次のフィールドがあります。merchantOrderId
-Order
オブジェクトで設定したのと同じ ID。lastUpdateTime
- この更新のタイムスタンプ。purchase
- 以下を含むオブジェクト。 <ph type="x-smartling-placeholder">- </ph>
status
-PurchaseStatus
としての注文のステータス。 例: 「SHIPPED
」または「DELIVERED
」。userVisibleStatusLabel
- 詳細情報を提供するユーザー向けのラベル (「ご注文は発送され、 あります。
userNotification
(省略可) - AuserNotification
この更新の送信時にユーザーのデバイスに表示できるオブジェクトです。備考 このオブジェクトを含めても、通知が アクセスします。
次のサンプルコードは、バージョンを更新する OrderUpdate
の例を示しています。
DELIVERED
への注文のステータス:
Node.js
// 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 Actions on Google client library. const {OrderUpdate} = require('actions-on-google'); // 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: [ 'lastUpdateTime', 'purchase.status', 'purchase.userVisibleStatusLabel', ].join(','), 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); conv.close(`The order has been updated.`); } catch (e) { console.log(`Error: ${e}`); conv.close(`There was an error sending an order update.`); }
Node.js
// 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 Actions on Google client library. const {OrderUpdate} = require('actions-on-google'); // 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: [ 'lastUpdateTime', 'purchase.status', 'purchase.userVisibleStatusLabel', ].join(','), 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); conv.close(`The order has been updated.`); } catch (e) { console.log(`Error: ${e}`); conv.close(`There was an error sending an order update.`); }
Java
// Setup service account credentials String serviceAccountFile = MyActionsApp.class.getClassLoader() .getResource(SERVICE_ACCOUNT_KEY_FILE_NAME) .getFile(); InputStream actionsApiServiceAccount = new FileInputStream( serviceAccountFile); ServiceAccountCredentials serviceAccountCredentials = (ServiceAccountCredentials) ServiceAccountCredentials.fromStream(actionsApiServiceAccount) .createScoped(Collections.singleton( "https://www.googleapis.com/auth/actions.order.developer")); AccessToken token = serviceAccountCredentials.refreshAccessToken(); // Setup request with headers HttpPatch patchRequest = new HttpPatch( "https://actions.googleapis.com/v3/orders/" + orderId); patchRequest.setHeader("Content-type", "application/json"); patchRequest.setHeader("Authorization", "Bearer " + token.getTokenValue()); // Create order update FieldMask fieldMask = FieldMask.newBuilder().addAllPaths(Arrays.asList( "lastUpdateTime", "purchase.status", "purchase.userVisibleStatusLabel")) .build(); OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setOrder(new OrderV3() .setMerchantOrderId(orderId) .setLastUpdateTime(Instant.now().toString()) .setPurchase(new PurchaseOrderExtension() .setStatus("DELIVERED") .setUserVisibleStatusLabel("Order delivered."))) .setUpdateMask(FieldMaskUtil.toString(fieldMask)) .setReason("Order status was updated to delivered."); // 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()); patchRequest.setEntity(entity); // Make request HttpClient httpClient = HttpClientBuilder.create().build(); HttpResponse response = httpClient.execute(patchRequest); LOGGER.info(response.getStatusLine().getStatusCode() + " " + response .getStatusLine().getReasonPhrase()); return getResponseBuilder(request) .add("The order has been updated.") .build();
Java
// Setup service account credentials String serviceAccountFile = MyActionsApp.class.getClassLoader() .getResource(SERVICE_ACCOUNT_KEY_FILE_NAME) .getFile(); InputStream actionsApiServiceAccount = new FileInputStream( serviceAccountFile); ServiceAccountCredentials serviceAccountCredentials = (ServiceAccountCredentials) ServiceAccountCredentials.fromStream(actionsApiServiceAccount) .createScoped(Collections.singleton( "https://www.googleapis.com/auth/actions.order.developer")); AccessToken token = serviceAccountCredentials.refreshAccessToken(); // Setup request with headers HttpPatch patchRequest = new HttpPatch( "https://actions.googleapis.com/v3/orders/" + orderId); patchRequest.setHeader("Content-type", "application/json"); patchRequest.setHeader("Authorization", "Bearer " + token.getTokenValue()); // Create order update FieldMask fieldMask = FieldMask.newBuilder().addAllPaths(Arrays.asList( "lastUpdateTime", "purchase.status", "purchase.userVisibleStatusLabel")) .build(); OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setOrder(new OrderV3() .setMerchantOrderId(orderId) .setLastUpdateTime(Instant.now().toString()) .setPurchase(new PurchaseOrderExtension() .setStatus("DELIVERED") .setUserVisibleStatusLabel("Order delivered."))) .setUpdateMask(FieldMaskUtil.toString(fieldMask)) .setReason("Order status was updated to delivered."); // 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()); patchRequest.setEntity(entity); // Make request HttpClient httpClient = HttpClientBuilder.create().build(); HttpResponse response = httpClient.execute(patchRequest); LOGGER.info(response.getStatusLine().getStatusCode() + " " + response .getStatusLine().getReasonPhrase()); return getResponseBuilder(request) .add("The order has been updated.") .build();
購入ステータスを設定する
注文の更新の status
注文の現在の状態を示す必要がありますアップデートの order.purchase.status
次のいずれかの値を使用します。
CREATED
- ユーザーが注文を承諾しています。アクションからみると、バックエンドで手動処理が必要な状態です。CONFIRMED
- 注文は有効で、納品へ向け処理中です。IN_PREPARATION
- 注文は発送または配達の準備中です(食品など) 調理中や梱包中の商品などですREADY_FOR_PICKUP
- 注文を受け取る準備ができています。DELIVERED
- 受取人への配達が完了しました。OUT_OF_STOCK
- 注文の 1 つ以上の商品が在庫切れです。CHANGE_REQUESTED
- ユーザーが注文の変更をリクエストし、変更が あります。RETURNED
- 配送後にユーザーから返品されました。REJECTED
- 注文を処理または請求できない場合。あるいは、注文を有効にできない場合。CANCELLED
- ユーザーが注文をキャンセルしました。
注文状況に関連するステータスごとに
あります。たとえば、取引で次の処理を手動で行う必要がある場合。
注文後に注文を記録すると、次の期限までに CREATED
の注文更新情報を送信します。
追加の処理が行われます。すべての注文でステータス値が必要になるとは限りません。
トラブルシューティング
テスト中に問題が発生した場合は、取引に関するトラブルシューティングの手順をご覧ください。