物理的な商品の取引を v3 に移行する(Dialogflow)

2019 年 8 月 7 日に Orders v2 API のサポートが終了し、Orders バージョン 3 に置き換えられました。この日より前に物理的な取引を処理するアクションを作成した場合は、このガイドに従ってアクションを更新して Orders v3 を使用してください。

API の変更

バージョン 3 の Orders API には、バージョン 2 から次のような変更が行われています。

  • リクエスト構造 - バージョン 3 の注文構造には、カートの内容だけではなく、注文の詳細がすべて含まれます。
  • 注文の更新 - バージョン 3 の Orders API は、注文の処理に加えて注文の更新を処理するため、エンドポイントが Actions API を使用してユーザーに注文に関する最新情報を送信する必要はありません。また、ステータス更新を送信する POST リクエストではなく、PATCH リクエストとして更新を Orders API に送信し、既存の order オブジェクトを更新します。
  • 支払いの円滑化 - バージョン 3 の Orders API で Google Pay を使用するアクションは、支払いゲートウェイの詳細を新しい JSON 構造にネストします。これにより、拡張性と EU 法へのコンプライアンスが向上します。

Node.JS を v3 に移行する

Node.JS クライアント ライブラリを使用するアクションを移行する手順は次のとおりです。

1. Orders v3 フラグを追加する

Orders バージョン 3 では、トランザクションの処理に使用したクライアント ライブラリ関数が更新されています。関数を更新するフラグをフルフィルメント コードに追加してバージョン 3 の JSON を送信するだけです。

次のコードをフルフィルメントに追加します。

Node.js
const {dialogflow} = require('actions-on-google');
const app = dialogflow({ordersv3: true});

2. カート アセンブリを更新する

ProposedOrder タイプは、より詳細な Order オブジェクトに置き換えられました。ProposedOrder カートを Order カートに変換するには、JSON リファレンスをご覧ください。

3. 支払いパラメータを更新する

注文提案ステップの支払い情報の構造は、API バージョンによって異なります。

actions.intent.TRANSACTION_DECISION インテント リクエストで、古い paymentOptions オブジェクトを新しい paymentParameters オブジェクトに置き換えます。含まれているフィールドのほとんどは同じです。JSON オブジェクトの構造にいくつかの変更を加えてください。

次のコード スニペットは、Google Pay の actions.intent.TRANSACTION_DECISION インテント リクエスト(バージョン 3 を使用)と、比較用の古いバージョン 2 リクエストの例を示しています。

Node.JS New(v3)
conv.ask(new TransactionDecision({
  orderOptions: {
    requestDeliveryAddress: false,
    userInfoOptions: {
      userInfoProperties: [
        'EMAIL',
      ],
    },
  },
  paymentParameters: {
    googlePaymentOption: {
      // facilitationSpec is expected to be a serialized JSON string
      facilitationSpec: JSON.stringify({
        apiVersion: 2,
        apiVersionMinor: 0,
        merchantInfo: {
          merchantName: 'Example Merchant',
        },
        allowedPaymentMethods: [
          {
            type: 'CARD',
            parameters: {
              allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
              allowedCardNetworks: [
                'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'],
            },
            tokenizationSpecification: {
              type: 'PAYMENT_GATEWAY',
              parameters: {
                gateway: 'example',
                gatewayMerchantId: 'exampleGatewayMerchantId',
              },
            },
          },
        ],
        transactionInfo: {
          totalPriceStatus: 'FINAL',
          totalPrice: '10.00',
          currencyCode: 'USD',
        },
      }),
    },
  },
  presentationOptions: {
    actionDisplayName: 'PLACE_ORDER',
  },
  order: order,
}));
Node.JS Old(v2)
conv.ask(new TransactionDecision({
  orderOptions: {
    requestDeliveryAddress: false,
  },
  paymentOptions: {
    googleProvidedOptions: {
      prepaidCardDisallowed: false,
      supportedCardNetworks: ['VISA', 'AMEX', 'DISCOVER', 'MASTERCARD'],
      tokenizationParameters: {
        tokenizationType: 'PAYMENT_GATEWAY',
        // These will be provided by payment processor,
        // like Stripe, Braintree, Vantiv, Ayden, etc.
        parameters: {
          'gateway': 'stripe',
          'stripe:publishableKey': (conv.sandbox ? 'pk_test_key' : 'pk_live_key'),
          'stripe:version': '2018-11-08'
        },
      },
    },
  },
  proposedOrder: order,
}));
JSON New (v3)

下記の Dialogflow JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.TRANSACTION_DECISION",
        "data": {
          "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec",
          "orderOptions": {
            "requestDeliveryAddress": "false"
          },
          "paymentParameters": {
            "googlePaymentOption": {
              "facilitationSpec": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"Example Merchant\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\",\"CRYPTOGRAM_3DS\"],\"allowedCardNetworks\":[\"AMEX\",\"DISCOVER\",\"JCB\",\"MASTERCARD\",\"VISA\"]},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gateway\":\"example\",\"gatewayMerchantId\":\"exampleGatewayMerchantId\"}}}],\"transactionInfo\":{\"totalPriceStatus\":\"FINAL\",\"totalPrice\":\"10.00\",\"currencyCode\":\"USD\"}}"
            }
          },
          "presentationOptions": {
            "actionDisplayName": "PLACE_ORDER"
          },
          "order": {
            "createTime": "2019-08-01T17:12:13.765Z",
            "lastUpdateTime": "2019-08-01T17:12:13.765Z",
            "merchantOrderId": "UNIQUE_ORDER_ID",
            "userVisibleOrderId": "USER_VISIBLE_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
                    }
                  ],
                  "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
                          }
                        ],
                        "note": "Extra pepperoni",
                        "quantity": 1,
                        "subOptions": []
                      }
                    ]
                  }
                }
              ]
            },
            "buyerInfo": {
              "email": "janedoe@gmail.com",
              "firstName": "Jane",
              "lastName": "Doe",
              "displayName": "Jane Doe"
            },
            "priceAttributes": [
              {
                "type": "TOTAL",
                "name": "Total Price",
                "state": "ESTIMATE",
                "amount": {
                  "currencyCode": "USD",
                  "amountInMicros": 15770000
                },
                "taxIncluded": true
              },
              {
                "type": "TAX",
                "name": "Tax",
                "state": "ESTIMATE",
                "amount": {
                  "currencyCode": "USD",
                  "amountInMicros": 3780000
                },
                "taxIncluded": true
              },
              {
                "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
              }
            ],
            "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": "2017-01-16T01:30:15.01Z"
                },
                "location": {
                  "zipCode": "94086",
                  "city": "Sunnyvale",
                  "postalAddress": {
                    "regionCode": "US",
                    "postalCode": "94086",
                    "administrativeArea": "CA",
                    "locality": "Sunnyvale",
                    "addressLines": [
                      "222, Some other Street"
                    ]
                  }
                },
                "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"
            }
          }
        }
      }
    }
  }
}
JSON 古いバージョン(v2)

下記の Dialogflow JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.TRANSACTION_DECISION",
        "data": {
          "@type": "type.googleapis.com/google.actions.v2.TransactionDecisionValueSpec",
          "orderOptions": {
            "requestDeliveryAddress": false
          },
          "paymentOptions": {
            "googleProvidedOptions": {
              "prepaidCardDisallowed": false,
              "supportedCardNetworks": [
                "VISA",
                "AMEX",
                "DISCOVER",
                "MASTERCARD"
              ],
              "tokenizationParameters": {
                "tokenizationType": "PAYMENT_GATEWAY",
                "parameters": {
                  "gateway": "stripe",
                  "stripe:publishableKey": "pk_test_key",
                  "stripe:version": "2018-11-08"
                }
              }
            }
          },
          "proposedOrder": {
            "id": "UNIQUE_ORDER_ID222",
            "cart": {
              "merchant": {
                "id": "book_store_id",
                "name": "A Book Store"
              },
              "lineItems": [
                {
                  "name": "My Memoirs",
                  "id": "mymemoirs_id",
                  "price": {
                    "amount": {
                      "currencyCode": "USD",
                      "nanos": 990000000,
                      "units": 8
                    },
                    "type": "ACTUAL"
                  },
                  "quantity": 1,
                  "subLines": [
                    {
                      "note": "By Bestselling Novelist"
                    }
                  ],
                  "type": "REGULAR"
                },
                {
                  "name": "Biography",
                  "id": "biography_id",
                  "price": {
                    "amount": {
                      "currencyCode": "USD",
                      "nanos": 990000000,
                      "units": 10
                    },
                    "type": "ACTUAL"
                  },
                  "quantity": 1,
                  "subLines": [
                    {
                      "note": "Signed copy"
                    }
                  ],
                  "type": "REGULAR"
                }
              ],
              "notes": "Sale event",
              "otherItems": []
            },
            "otherItems": [
              {
                "name": "Subtotal",
                "id": "subtotal",
                "price": {
                  "amount": {
                    "currencyCode": "USD",
                    "nanos": 980000000,
                    "units": 19
                  },
                  "type": "ESTIMATE"
                },
                "type": "SUBTOTAL"
              },
              {
                "name": "Tax",
                "id": "tax",
                "price": {
                  "amount": {
                    "currencyCode": "USD",
                    "nanos": 780000000,
                    "units": 2
                  },
                  "type": "ESTIMATE"
                },
                "type": "TAX"
              }
            ],
            "totalPrice": {
              "amount": {
                "currencyCode": "USD",
                "nanos": 760000000,
                "units": 22
              },
              "type": "ESTIMATE"
            }
          }
        }
      }
    }
  }
}

4. Orders API を使用して更新を送信する

Orders API のバージョン 3 では注文の更新が処理されるため、Actions API に POST リクエストを送信する必要はありません。代わりに、PATCH リクエストを Orders API に送信して Order オブジェクトのコンテンツを更新します。

新しい署名なしトークンを取得する

Actions API 用の署名なしトークンの取得に使用したのと同じ JSON サービス アカウント キーを使用できますが、Orders API 用の新しい署名なしトークンをリクエストする必要があります。Google API クライアント ライブラリと "https://www.googleapis.com/auth/actions.order.developer" スコープを使用して、サービスキーを署名なしトークンと交換します。

インストール手順と例については、API クライアント ライブラリの GitHub ページをご覧ください。 Orders API キー交換の例については、Node.js サンプルの更新された order-update.js をご覧ください。

最新情報を通知する

Orders API で注文の更新を送信するプロセスは Actions API での更新の送信と似ていますが、POST リクエストの代わりに PATCH リクエストを送信します。PATCH リクエストは、次の形式の JSON 本文を受け取ります。

{ "orderUpdate": OrderUpdate" }

バージョン 3 では OrderUpdate の形式も異なります。PATCH リクエストのリファレンスを参照し、OrderUpdate フィールドを更新します。次のコード スニペットは、注文のステータスを「DELIVERED」に更新する PATCH リクエストの例を示しています。

Node.js
// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request' module for sending an HTTP POST request.
const request = require('request');
// 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. Replace the string path with a path to your service account key.
const key = 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(
    key.client_email,
    null,
    key.private_key,
    ['https://www.googleapis.com/auth/actions.order.developer'],
    null
);
// Authorize the client asynchronously, passing in a callback to run upon authorization.
jwtClient.authorize((err, tokens) => {
    if (err) {
        console.log(err);
        return;
    }
    // Declare the ID of the order to update.
    const orderId = '<UNIQUE_MERCHANT_ORDER_ID>';

    const orderUpdate = new OrderUpdate({
        updateMask: [
          'lastUpdateTime',
          'purchase.status',
          'purchase.userVisibleStatusLabel',
        ].join(','),
        order: {
          merchantOrderId: orderId,
          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.
    const bearer = 'Bearer ' + tokens.access_token;
    const options = {
        method: 'PATCH',
        url: `https://actions.googleapis.com/v3/orders/${orderId}`,
        headers: {
          'Authorization': bearer,
        },
        body: {
          header: {
            'isInSandbox': true,
          },
          orderUpdate,
        },
        json: true,
      };
    // Send the PATCH request to the Orders API.
    request.patch(options, (err, httpResponse, body) => {
        if (err) {
            console.log('There was an error...');
            console.log(err);
            return;
        }
    });
});

追加の注文ステータスを処理する

Orders API バージョン 3 では、バージョン 2 では使用できなかった追加の注文ステータス値がサポートされています。各取引に関連するすべてのステータスについて、注文の更新を送信する必要があります。

バージョン 3 の新しいステータス値は次のとおりです。

  • IN_PREPARATION - 注文の発送または配達の準備中(料理の調理や商品の梱包など)。
  • READY_FOR_PICKUP - 注文を受け取る準備ができています。
  • DELIVERED - 受取人への配達が完了しました。
  • OUT_OF_STOCK - 注文の 1 つ以上の商品が在庫切れです。
  • CHANGE_REQUESTED - ユーザーが注文の変更をリクエストし、変更の処理中です。

FULFILLED ステータスは廃止され、DELIVERED に代わりました。

Java から v3 への移行

次の手順に従って、Java クライアント ライブラリを使用するアクションを移行します。

1. カート アセンブリを更新する

ProposedOrder タイプは、より詳細な Order オブジェクトに置き換えられました。ProposedOrder カートを Order カートに変換するには、JSON リファレンスをご覧ください。

2. 支払いパラメータを更新する

注文提案ステップの支払い情報の構造は、API バージョンによって異なります。

actions.intent.TRANSACTION_DECISION インテント リクエストで、古い paymentOptions オブジェクトを新しい paymentParameters オブジェクトに置き換えます。含まれているフィールドのほとんどは同じです。JSON オブジェクトの構造にいくつかの変更を加えてください。

次のコード スニペットは、Google Pay の actions.intent.TRANSACTION_DECISION インテント リクエスト(バージョン 3 を使用)と、比較用の古いバージョン 2 リクエストの例を示しています。

Java(v3)
// Create order options
OrderOptionsV3 orderOptions = new OrderOptionsV3()
    .setRequestDeliveryAddress(false)
    .setUserInfoOptions(new UserInfoOptions()
        .setUserInfoProperties(Collections.singletonList("EMAIL")));

// Create presentation options
PresentationOptionsV3 presentationOptions = new PresentationOptionsV3()
    .setActionDisplayName("PLACE_ORDER");

// Create payment parameters
JSONObject merchantInfo = new JSONObject();
merchantInfo.put("merchantName", "Example Merchant");

JSONObject facilitationSpec = new JSONObject();
facilitationSpec.put("apiVersion", 2);
facilitationSpec.put("apiVersionMinor", 0);
facilitationSpec.put("merchantInfo", merchantInfo);

JSONObject allowedPaymentMethod = new JSONObject();
allowedPaymentMethod.put("type", "CARD");

JSONArray allowedAuthMethods = new JSONArray();
allowedAuthMethods.addAll(Arrays.asList("PAN_ONLY", "CRYPTOGRAM_3DS"));
JSONArray allowedCardNetworks = new JSONArray();
allowedCardNetworks.addAll(Arrays.asList("AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA"));

JSONObject allowedPaymentMethodParameters = new JSONObject();
allowedPaymentMethodParameters.put("allowedAuthMethods", allowedAuthMethods);
allowedPaymentMethodParameters.put("allowedCardNetworks", allowedCardNetworks);

allowedPaymentMethod.put("parameters", allowedPaymentMethodParameters);

JSONObject tokenizationSpecificationParameters = new JSONObject();
tokenizationSpecificationParameters.put("gateway", "example");
tokenizationSpecificationParameters.put("gatewayMerchantId", "exampleGatewayMerchantId");

JSONObject tokenizationSpecification = new JSONObject();
tokenizationSpecification.put("type", "PAYMENT_GATEWAY");
tokenizationSpecification.put("parameters", tokenizationSpecificationParameters);
allowedPaymentMethod.put("tokenizationSpecification", tokenizationSpecification);

JSONArray allowedPaymentMethods = new JSONArray();
allowedPaymentMethods.add(allowedPaymentMethod);

facilitationSpec.put("allowedPaymentMethods", allowedPaymentMethods);

JSONObject transactionInfo = new JSONObject();
transactionInfo.put("totalPriceStatus", "FINAL");
transactionInfo.put("totalPrice", "10.00");
transactionInfo.put("currencyCode", "USD");

facilitationSpec.put("transactionInfo", transactionInfo);

GooglePaymentOption googlePaymentOption = new GooglePaymentOption()
    .setFacilitationSpec(facilitationSpec.toJSONString());

PaymentParameters paymentParameters = new PaymentParameters()
    .setGooglePaymentOption(googlePaymentOption);

// Ask for transaction decision
return getResponseBuilder(request)
    .add("Placeholder for transaction decision text")
    .add(new TransactionDecision()
        .setOrder(order)
        .setOrderOptions(orderOptions)
        .setPresentationOptions(presentationOptions)
        .setPaymentParameters(paymentParameters)
    )
    .build();
Java 旧(v2)
OrderOptions orderOptions;
PaymentOptions paymentOptions;

// Setup Google provided payment options
Map<String, String> parameters = new HashMap<>();
parameters.put("gateway", "stripe");
parameters.put("stripe:publishableKey", request.isInSandbox() ? "pk_test_key" : "pk_live_key");
parameters.put("stripe:version", "2017-04-06");
PaymentMethodTokenizationParameters tokenizationParameters =
    new PaymentMethodTokenizationParameters()
        .setTokenizationType("PAYMENT_GATEWAY")
        .setParameters(parameters);
orderOptions = new OrderOptions().setRequestDeliveryAddress(false);
GoogleProvidedPaymentOptions googleProvidedPaymentOptions =
    new GoogleProvidedPaymentOptions()
        .setPrepaidCardDisallowed(false)
        .setSupportedCardNetworks(Arrays.asList("VISA", "AMEX"))
        .setTokenizationParameters(tokenizationParameters);
paymentOptions = new PaymentOptions().setGoogleProvidedOptions(googleProvidedPaymentOptions);

return getResponseBuilder(request)
    .add("Placeholder for transaction decision text")
    .add(
        new TransactionDecision()
            .setOrderOptions(orderOptions)
            .setPaymentOptions(paymentOptions)
            .setProposedOrder(proposedOrder))
    .build();
JSON New (v3)

下記の Dialogflow JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.TRANSACTION_DECISION",
        "data": {
          "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec",
          "orderOptions": {
            "requestDeliveryAddress": "false"
          },
          "paymentParameters": {
            "googlePaymentOption": {
              "facilitationSpec": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"Example Merchant\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\",\"CRYPTOGRAM_3DS\"],\"allowedCardNetworks\":[\"AMEX\",\"DISCOVER\",\"JCB\",\"MASTERCARD\",\"VISA\"]},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gateway\":\"example\",\"gatewayMerchantId\":\"exampleGatewayMerchantId\"}}}],\"transactionInfo\":{\"totalPriceStatus\":\"FINAL\",\"totalPrice\":\"10.00\",\"currencyCode\":\"USD\"}}"
            }
          },
          "presentationOptions": {
            "actionDisplayName": "PLACE_ORDER"
          },
          "order": {
            "createTime": "2019-08-01T17:12:13.765Z",
            "lastUpdateTime": "2019-08-01T17:12:13.765Z",
            "merchantOrderId": "UNIQUE_ORDER_ID",
            "userVisibleOrderId": "USER_VISIBLE_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
                    }
                  ],
                  "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
                          }
                        ],
                        "note": "Extra pepperoni",
                        "quantity": 1,
                        "subOptions": []
                      }
                    ]
                  }
                }
              ]
            },
            "buyerInfo": {
              "email": "janedoe@gmail.com",
              "firstName": "Jane",
              "lastName": "Doe",
              "displayName": "Jane Doe"
            },
            "priceAttributes": [
              {
                "type": "TOTAL",
                "name": "Total Price",
                "state": "ESTIMATE",
                "amount": {
                  "currencyCode": "USD",
                  "amountInMicros": 15770000
                },
                "taxIncluded": true
              },
              {
                "type": "TAX",
                "name": "Tax",
                "state": "ESTIMATE",
                "amount": {
                  "currencyCode": "USD",
                  "amountInMicros": 3780000
                },
                "taxIncluded": true
              },
              {
                "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
              }
            ],
            "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": "2017-01-16T01:30:15.01Z"
                },
                "location": {
                  "zipCode": "94086",
                  "city": "Sunnyvale",
                  "postalAddress": {
                    "regionCode": "US",
                    "postalCode": "94086",
                    "administrativeArea": "CA",
                    "locality": "Sunnyvale",
                    "addressLines": [
                      "222, Some other Street"
                    ]
                  }
                },
                "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"
            }
          }
        }
      }
    }
  }
}
JSON 古いバージョン(v2)

下記の Dialogflow JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.TRANSACTION_DECISION",
        "data": {
          "@type": "type.googleapis.com/google.actions.v2.TransactionDecisionValueSpec",
          "orderOptions": {
            "requestDeliveryAddress": false
          },
          "paymentOptions": {
            "googleProvidedOptions": {
              "prepaidCardDisallowed": false,
              "supportedCardNetworks": [
                "VISA",
                "AMEX",
                "DISCOVER",
                "MASTERCARD"
              ],
              "tokenizationParameters": {
                "tokenizationType": "PAYMENT_GATEWAY",
                "parameters": {
                  "gateway": "stripe",
                  "stripe:publishableKey": "pk_test_key",
                  "stripe:version": "2018-11-08"
                }
              }
            }
          },
          "proposedOrder": {
            "id": "UNIQUE_ORDER_ID222",
            "cart": {
              "merchant": {
                "id": "book_store_id",
                "name": "A Book Store"
              },
              "lineItems": [
                {
                  "name": "My Memoirs",
                  "id": "mymemoirs_id",
                  "price": {
                    "amount": {
                      "currencyCode": "USD",
                      "nanos": 990000000,
                      "units": 8
                    },
                    "type": "ACTUAL"
                  },
                  "quantity": 1,
                  "subLines": [
                    {
                      "note": "By Bestselling Novelist"
                    }
                  ],
                  "type": "REGULAR"
                },
                {
                  "name": "Biography",
                  "id": "biography_id",
                  "price": {
                    "amount": {
                      "currencyCode": "USD",
                      "nanos": 990000000,
                      "units": 10
                    },
                    "type": "ACTUAL"
                  },
                  "quantity": 1,
                  "subLines": [
                    {
                      "note": "Signed copy"
                    }
                  ],
                  "type": "REGULAR"
                }
              ],
              "notes": "Sale event",
              "otherItems": []
            },
            "otherItems": [
              {
                "name": "Subtotal",
                "id": "subtotal",
                "price": {
                  "amount": {
                    "currencyCode": "USD",
                    "nanos": 980000000,
                    "units": 19
                  },
                  "type": "ESTIMATE"
                },
                "type": "SUBTOTAL"
              },
              {
                "name": "Tax",
                "id": "tax",
                "price": {
                  "amount": {
                    "currencyCode": "USD",
                    "nanos": 780000000,
                    "units": 2
                  },
                  "type": "ESTIMATE"
                },
                "type": "TAX"
              }
            ],
            "totalPrice": {
              "amount": {
                "currencyCode": "USD",
                "nanos": 760000000,
                "units": 22
              },
              "type": "ESTIMATE"
            }
          }
        }
      }
    }
  }
}

3. Orders API を使用して更新を送信する

Orders API のバージョン 3 では注文の更新が処理されるため、Actions API に POST リクエストを送信する必要はありません。代わりに、PATCH リクエストを Orders API に送信して Order オブジェクトのコンテンツを更新します。

新しい署名なしトークンを取得する

Actions API 用の署名なしトークンの取得に使用したのと同じ JSON サービス アカウント キーを使用できますが、Orders API 用の新しい署名なしトークンをリクエストする必要があります。Google API クライアント ライブラリと "https://www.googleapis.com/auth/actions.order.developer" スコープを使用して、サービスキーを署名なしトークンと交換します。

インストール手順と例については、API クライアント ライブラリの GitHub ページをご覧ください。 Orders API キー交換の例については、Java サンプルの更新された order-update.js も参照してください。

最新情報を通知する

Orders API で注文の更新を送信するプロセスは Actions API での更新の送信と似ていますが、POST リクエストの代わりに PATCH リクエストを送信します。PATCH リクエストは、次の形式の JSON 本文を受け取ります。

{ "orderUpdate": OrderUpdate" }

バージョン 3 では OrderUpdate の形式も異なります。PATCH リクエストのリファレンスを参照し、OrderUpdate フィールドを更新します。次のコード スニペットは、注文のステータスを「DELIVERED」に更新する PATCH リクエストの例を示しています。

Java
// Create order update
FieldMask fieldMask = FieldMask.newBuilder().addAllPaths(Arrays.asList(
    "last_update_time",
    "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());
request.setEntity(entity);

// Make request
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse response = httpClient.execute(request);

追加の注文ステータスを処理する

Orders API バージョン 3 では、バージョン 2 では使用できなかった追加の注文ステータス値がサポートされています。各取引に関連するすべてのステータスについて、注文の更新を送信する必要があります。

バージョン 3 の新しいステータス値は次のとおりです。

  • IN_PREPARATION - 注文の発送または配達の準備中(料理の調理や商品の梱包など)。
  • READY_FOR_PICKUP - 注文を受け取る準備ができています。
  • DELIVERED - 受取人への配達が完了しました。
  • OUT_OF_STOCK - 注文の 1 つ以上の商品が在庫切れです。
  • CHANGE_REQUESTED - ユーザーが注文の変更をリクエストし、変更の処理中です。

FULFILLED ステータスは廃止され、DELIVERED に代わりました。