As of August 7th 2019, the Orders v2 API was deprecated and replaced by Orders version 3. If you've built an Action that handles physical transactions prior to this date, follow this guide to update your Action to use Orders v3.
API changes
Version 3 of the Orders API features the following key changes from version 2:
- Request structure - The version 3 order structure contains all of the order details, rather than only containing the cart contents.
- Order updates - The version 3 Orders API handles order updates in
addition to handling the order placement, so your endpoint doesn't need to
use the Actions API to send users updates about their orders. You also send
updates as PATCH requests to the Orders API that update the existing
order
object, rather than POST requests to send status updates. - Payment facilitation - Actions that use Google Pay with the version 3 Orders API nest their payment gateway details in a new JSON structure that allows for more extensibility and compliance with EU laws.
Migrate Node.JS to v3
Follow these steps to migrate an Action that uses the Node.JS client library.
1. Add the Orders v3 flag
The client library functions that you've used to handle transactions are updated for Orders version 3, you just need to add a flag to your fulfillment code that updates the functions to send version 3 JSON.
Add the following code to your fulfillment:
const {dialogflow} = require('actions-on-google'); const app = dialogflow({ordersv3: true});
2. Update your cart assembly
The ProposedOrder
type has been replaced with the more detailed Order
object. Refer to the JSON reference to convert your ProposedOrder
cart into
an Order
cart.
3. Update payment parameters
The structure of payment information in the order proposal step is different between API versions.
In your actions.intent.TRANSACTION_DECISION
intent request, replace the old
paymentOptions
object with the new paymentParameters
object. Most of
the contained fields are the same, save for some changes to the JSON object's
structure.
The following code snippets show an example actions.intent.TRANSACTION_DECISION
intent request for Google Pay using version 3, and an old version 2 request for
comparison.
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, }));
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, }));
Note that the Dialogflow JSON below describes a webhook response.
{ "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" } } } } } } }
Note that the Dialogflow JSON below describes a webhook response.
{ "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. Send updates with the Orders API
Version 3 of the Orders API handles order updates, so you no longer need to
send POST requests to the Actions API. Instead, you send a PATCH request
to the Orders API that updates the contents of your Order
object.
Retrieve a new bearer token
You can use the same JSON service account key that you used to retrieve a bearer token for the Actions API, you need to request a new bearer token for the Orders API. Exchange your service key for a bearer token using the Google APIs client library and the "https://www.googleapis.com/auth/actions.order.developer" scope.
You can find installation steps and examples on the API client library GitHub page.
You can also reference the updated order-update.js
in our Node.js sample for an example Orders API key exchange.
Send updates
The process of sending an order update with the Orders API is similar to sending updates with the Actions API, though you send a PATCH request instead of a POST request. The PATCH request should take a JSON body of the following format:
{ "orderUpdate": OrderUpdate" }
The OrderUpdate
format is also different in version 3. Refer to the PATCH request reference
and update your OrderUpdate
fields accordingly. The following code snippet
shows an example PATCH request that updates an order's status to "DELIVERED
":
// 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; } }); });
Handle additional order statuses
Version 3 of the Orders API supports additional order status values that weren't available in version 2. You should send order updates for every status that's relevant to each transaction.
The following status values are new to version 3:
IN_PREPARATION
- Order is being prepared for shipment/delivery, such as food being cooked or an item being packaged.READY_FOR_PICKUP
- Order is available for pick-up by the recipient.DELIVERED
- Order has been delivered to the recipientOUT_OF_STOCK
- One or more items in the order is out-of-stock.CHANGE_REQUESTED
- User requested a change to the order, and the change is being processed.
The FULFILLED
status is deprecated and replaced with DELIVERED
.
Migrate Java to v3
Follow these steps to migrate an Action that uses the Java client library.
1. Update your cart assembly
The ProposedOrder
type has been replaced with the more detailed Order
object. Refer to the JSON reference to convert your ProposedOrder
cart into
an Order
cart.
2. Update payment parameters
The structure of payment information in the order proposal step is different between API versions.
In your actions.intent.TRANSACTION_DECISION
intent request, replace the old
paymentOptions
object with the new paymentParameters
object. Most of
the contained fields are the same, save for some changes to the JSON object's
structure.
The following code snippets show an example actions.intent.TRANSACTION_DECISION
intent request for Google Pay using version 3, and an old version 2 request for
comparison.
// 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();
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();
Note that the Dialogflow JSON below describes a webhook response.
{ "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" } } } } } } }
Note that the Dialogflow JSON below describes a webhook response.
{ "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. Send updates with the Orders API
Version 3 of the Orders API handles order updates, so you no longer need to
send POST requests to the Actions API. Instead, you send a PATCH request
to the Orders API that updates the contents of your Order
object.
Retrieve a new bearer token
You can use the same JSON service account key that you used to retrieve a bearer token for the Actions API, you need to request a new bearer token for the Orders API. Exchange your service key for a bearer token using the Google APIs client library and the "https://www.googleapis.com/auth/actions.order.developer" scope.
You can find installation steps and examples on the API client library GitHub page.
You can also reference the updated order-update.js
in our Java sample for an example Orders API key exchange.
Send updates
The process of sending an order update with the Orders API is similar to sending updates with the Actions API, though you send a PATCH request instead of a POST request. The PATCH request should take a JSON body of the following format:
{ "orderUpdate": OrderUpdate" }
The OrderUpdate
format is also different in version 3. Refer to the PATCH request reference
and update your OrderUpdate
fields accordingly. The following code snippet
shows an example PATCH request that updates an order's status to "DELIVERED
":
// 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);
Handle additional order statuses
Version 3 of the Orders API supports additional order status values that weren't available in version 2. You should send order updates for every status that's relevant to each transaction.
The following status values are new to version 3:
IN_PREPARATION
- Order is being prepared for shipment/delivery, such as food being cooked or an item being packaged.READY_FOR_PICKUP
- Order is available for pick-up by the recipient.DELIVERED
- Order has been delivered to the recipientOUT_OF_STOCK
- One or more items in the order is out-of-stock.CHANGE_REQUESTED
- User requested a change to the order, and the change is being processed.
The FULFILLED
status is deprecated and replaced with DELIVERED
.