Hướng dẫn này sẽ trình bày quy trình phát triển một dự án Actions (Hành động) sử dụng Orders API để đặt chỗ.
Luồng giao dịch
Khi dự án Actions của bạn xử lý các yêu cầu đặt trước, sử dụng quy trình sau:
- Xác thực các yêu cầu về giao dịch (không bắt buộc) – Sử dụng trình trợ giúp về yêu cầu giao dịch khi bắt đầu cuộc trò chuyện để đảm bảo người dùng có thể thực hiện một giao dịch.
- Tạo đơn đặt hàng – Hướng dẫn người dùng tìm hiểu "lắp ráp giỏ hàng" nơi họ tạo thông tin chi tiết về giao dịch đặt phòng.
- Đề xuất đơn đặt hàng - Sau khi "giỏ hàng" đã hoàn tất, hãy đề xuất "đơn đặt hàng" đặt trước đến người dùng để họ có thể xác nhận thông tin đó là chính xác. Nếu yêu cầu đặt chỗ được xác nhận, bạn sẽ sẽ nhận được phản hồi kèm theo thông tin đặt chỗ.
- Hoàn tất đơn đặt hàng và gửi biên nhận – Sau khi đơn đặt hàng được xác nhận, hãy cập nhật hệ thống đặt chỗ của bạn và gửi biên nhận cho người dùng.
- Gửi thông tin cập nhật về đơn đặt hàng – Trong suốt thời gian đặt trước, cập nhật trạng thái đặt trước của người dùng bằng cách gửi yêu cầu PATCH đến API đơn đặt hàng.
Các quy định hạn chế và nguyên tắc về bài đánh giá
Xin lưu ý rằng các chính sách bổ sung áp dụng cho những Hành động sử dụng giao dịch và Orders API. Chúng tôi có thể mất đến 6 tuần để xem xét các Hành động có giao dịch, vì vậy, hãy tính thời gian đó khi lên kế hoạch cho lịch phát hành. Để quá trình xem xét diễn ra suôn sẻ, hãy đảm bảo rằng bạn tuân thủ các chính sách và nguyên tắc đối với giao dịch trước khi gửi Hành động đi xem xét.
Bạn chỉ có thể triển khai những Hành động sử dụng Orders API ở những quốc gia sau:
Úc Braxin Canada Indonesia |
Nhật Bản Mexico Quatar Nga |
Singapore Thuỵ Sĩ Thái Lan Thổ Nhĩ Kỳ Vương quốc Anh Hoa Kỳ |
Xây dựng dự án của bạn
Để biết thêm ví dụ về các cuộc trò chuyện giao dịch, hãy xem các mẫu giao dịch của chúng tôi trong Node.js và Java.
Thiết lập dự án
Khi tạo Hành động, bạn phải nêu rõ rằng bạn muốn thực hiện giao dịch trong bảng điều khiển Actions. Ngoài ra, nếu bạn đang bằng cách sử dụng thư viện ứng dụng Node.JS, hãy thiết lập phương thức thực hiện của bạn để sử dụng phiên bản của Orders API.
Để thiết lập dự án và phương thức thực hiện, hãy làm như sau:
- Tạo dự án mới hoặc nhập dự án hiện có.
- Chuyển đến phần Triển khai > Thông tin về thư mục.
Trong Thông tin bổ sung > Giao dịch > chọn hộp có nội dung "Thực hiện hành động của bạn sử dụng API Giao dịch để thực hiện các giao dịch hàng hoá thực tế không?".
Nếu bạn đang dùng thư viện ứng dụng Node.JS để xây dựng phương thức thực hiện cho Hành động, mở mã thực hiện đơn hàng rồi cập nhật quá trình tách biệt ứng dụng để đặt giá trị
ordersv3
gắn cờ thànhtrue
. Đoạn mã sau đây cho thấy một ứng dụng mẫu khai báo cho Đơn đặt hàng phiên bản 3.
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, });
1. Xác thực các yêu cầu về giao dịch (không bắt buộc)
Trải nghiệm người dùng
Ngay khi người dùng cho biết họ muốn thiết lập một yêu cầu đặt trước, bạn nên kích hoạt
actions.intent.TRANSACTION_REQUIREMENTS_CHECK
ý định để đảm bảo họ có thể
yêu cầu đặt chỗ. Ví dụ: khi được gọi, Hành động của bạn có thể yêu cầu:
"bạn có muốn đặt trước chỗ ngồi không?" Nếu người dùng nói
"yes" (có), bạn nên yêu cầu ý định này ngay lập tức. Điều này sẽ đảm bảo
để họ có thể tiếp tục và cho họ cơ hội khắc phục bất kỳ chế độ cài đặt nào
ngăn họ tiếp tục giao dịch.
Yêu cầu giao dịch các yêu cầu của việc kiểm tra ý định sẽ dẫn đến một trong các kết quả sau:
- Nếu đáp ứng các yêu cầu, phương thức thực hiện của bạn sẽ nhận được một ý định kèm theo điều kiện thành công và bạn có thể tiến hành tạo đơn đặt hàng của người dùng.
Nếu có một hoặc nhiều yêu cầu không được đáp ứng, phương thức thực hiện của bạn sẽ nhận được ý định có điều kiện không thành công. Trong trường hợp này, hãy kết thúc cuộc trò chuyện hoặc thoát khỏi quy trình đặt trước.
Nếu người dùng có thể khắc phục lỗi, họ sẽ tự động được nhắc giải quyết các vấn đề đó trên thiết bị của họ. Nếu cuộc trò chuyện đang diễn ra trên nền tảng chỉ dành cho giọng nói như một chiếc loa thông minh, nó được truyền đến điện thoại của người dùng.
Quy trình thực hiện đơn hàng
Để đảm bảo người dùng đáp ứng
các yêu cầu về giao dịch, thực hiện yêu cầu
Ý định actions.intent.TRANSACTION_REQUIREMENTS_CHECK
bằng một
Đối tượng TransactionRequirementsCheckSpec.
Kiểm tra các yêu cầu
Kiểm tra xem người dùng có đáp ứng các yêu cầu đặt trước với thư viện ứng dụng hay không:
conv.ask(new TransactionRequirements());
return getResponseBuilder(request) .add("Placeholder for transaction requirements text") .add(new TransactionRequirements()) .build();
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec" } } } } }
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK", "inputValueData": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec" } } ] } ] }
Nhận kết quả kiểm tra yêu cầu
Sau khi thực hiện ý định, Trợ lý sẽ gửi cho bạn một yêu cầu thực hiện
với ý định actions.intent.TRANSACTION_REQUIREMENTS_CHECK
kèm theo kết quả
của séc.
Để xử lý yêu cầu này đúng cách, hãy khai báo ý định Dialogflow được kích hoạt bằng
sự kiện actions_intent_TRANSACTION_REQUIREMENTS_CHECK
. Khi được kích hoạt,
xử lý ý định này trong phương thức thực hiện của bạn:
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!`); } else { conv.close('Transaction failed.'); }
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) { responseBuilder.add("Looks like you're good to go! Now say 'confirm transaction'"); } else { responseBuilder.add("Transaction failed"); } return responseBuilder.build();
Xin lưu ý rằng tệp JSON bên dưới mô tả một yêu cầu webhook.
{ "responseId": "", "queryResult": { "queryText": "", "action": "", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "", "fulfillmentMessages": [], "outputContexts": [], "intent": { "name": "reservation_transaction_check_complete_df", "displayName": "reservation_transaction_check_complete_df" }, "intentDetectionConfidence": 1, "diagnosticInfo": {}, "languageCode": "" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "isInSandbox": true, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "inputs": [ { "rawInputs": [], "intent": "", "arguments": [ { "extension": { "@type": "type.googleapis.com/google.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" }, "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT" } ] } ], "user": {}, "conversation": {}, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "" }
Xin lưu ý rằng tệp JSON bên dưới mô tả một yêu cầu webhook.
{ "user": {}, "device": {}, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "conversation": {}, "inputs": [ { "rawInputs": [], "intent": "reservation_transaction_check_complete_asdk", "arguments": [ { "extension": { "@type": "type.googleapis.com/google.transactions.v3.TransactionRequirementsCheckResult", "resultType": "CAN_TRANSACT" }, "name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT" } ] } ], "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
2. Tạo đơn đặt hàng
Trải nghiệm người dùng
Sau khi có thông tin người dùng cần thiết, hãy tạo "giỏ hàng" lắp ráp" để hướng dẫn người dùng tạo giao dịch đặt trước. Mỗi Hành động sẽ có quy trình lắp ráp giỏ hàng hơi khác sao cho phù hợp với .
Trong trải nghiệm lắp ráp giỏ hàng cơ bản, người dùng chọn các tùy chọn trong danh sách để thêm cho thông tin đặt chỗ của họ, mặc dù bạn có thể thiết kế cuộc trò chuyện để đơn giản hoá trải nghiệm người dùng. Ví dụ: tạo trải nghiệm lắp ráp giỏ hàng cho phép người dùng đặt trước hàng tháng với một câu hỏi đơn giản có hoặc không. Bạn cũng có thể hiển thị cho người dùng băng chuyền hoặc thẻ danh sách "được đề xuất" đặt chỗ.
Bạn nên sử dụng thành phần nhiều để đưa ra lựa chọn của người dùng trực quan, mà còn thiết kế cuộc trò chuyện để người dùng có thể tạo giỏ hàng chỉ bằng giọng nói. Để xem một số phương pháp hay nhất và ví dụ về trải nghiệm lắp ráp giỏ hàng, hãy xem Nguyên tắc thiết kế giao dịch.
Quy trình thực hiện đơn hàng
Trong suốt cuộc trò chuyện của bạn, hãy thu thập thông tin đặt chỗ mà người dùng muốn
để mua rồi tạo đối tượng Order
.
Order
của bạn ít nhất phải có các thông tin sau:
buyerInfo
– Thông tin về người dùng lên lịch đặt chỗ.transactionMerchant
– Thông tin về người bán đang hỗ trợ lịch đặt chỗ.contents
– Thông tin thực tế của yêu cầu đặt chỗ được liệt kê làlineItems
.
Tham khảo tài liệu phản hồi về Order
để tạo giỏ hàng. Xin lưu ý rằng bạn có thể cần phải bao gồm các trường khác nhau
tùy thuộc vào yêu cầu đặt chỗ.
Mã mẫu dưới đây hiển thị một đơn đặt hàng đặt trước hoàn chỉnh, bao gồm các trường không bắt buộc:
app.intent('build_reservation_df', (conv) => { const now = new Date().toISOString(); const order = { createTime: now, lastUpdateTime: now, merchantOrderId: 'UNIQUE_ORDER_ID', userVisibleOrderId: 'USER_VISIBLE_ORDER_ID', transactionMerchant: { id: 'https://www.example.com', name: 'Example Merchant', }, contents: { lineItems: [ { id: 'LINE_ITEM_ID', name: 'Dinner reservation', description: 'A world of flavors all in one destination.', reservation: { status: 'PENDING', userVisibleStatusLabel: 'Reservation is pending.', type: 'RESTAURANT', reservationTime: { timeIso8601: '2020-01-16T01:30:15.01Z', }, userAcceptableTimeRange: { timeIso8601: '2020-01-15/2020-01-17', }, partySize: 6, staffFacilitators: [ { name: 'John Smith', }, ], location: { zipCode: '94086', city: 'Sunnyvale', postalAddress: { regionCode: 'US', postalCode: '94086', administrativeArea: 'CA', locality: 'Sunnyvale', addressLines: [ '222, Some other Street', ], }, }, }, }, ], }, buyerInfo: { email: 'janedoe@gmail.com', firstName: 'Jane', lastName: 'Doe', displayName: 'Jane Doe', }, followUpActions: [ { type: 'VIEW_DETAILS', title: 'View details', openUrlAction: { url: 'https://example.com', }, }, { type: 'CALL', title: 'Call us', openUrlAction: { url: 'tel:+16501112222', }, }, { type: 'EMAIL', title: 'Email us', openUrlAction: { url: 'mailto:person@example.com', }, }, ], termsOfServiceUrl: 'https://www.example.com', };
private static OrderV3 createOrder() { // Transaction Merchant MerchantV3 transactionMerchant = new MerchantV3() .setId("http://www.example.com") .setName("Example Merchant"); // Line Item // Reservation Item Extension ReservationItemExtension reservationItemExtension = new ReservationItemExtension() .setStatus("PENDING") .setUserVisibleStatusLabel("Reservation pending.") .setType("RESTAURANT") .setReservationTime(new TimeV3() .setTimeIso8601("2020-01-16T01:30:15.01Z")) .setUserAcceptableTimeRange(new TimeV3() .setTimeIso8601("2020-01-15/2020-01-17")) .setPartySize(6) .setStaffFacilitators(Collections.singletonList(new StaffFacilitator() .setName("John Smith"))) .setLocation(new Location() .setZipCode("94086") .setCity("Sunnyvale") .setPostalAddress(new PostalAddress() .setRegionCode("US") .setPostalCode("94086") .setAdministrativeArea("CA") .setLocality("Sunnyvale") .setAddressLines( Collections.singletonList("222, Some other Street")))); LineItemV3 lineItem = new LineItemV3() .setId("LINE_ITEM_ID") .setName("Dinner reservation") .setDescription("A world of flavors all in one destination.") .setReservation(reservationItemExtension); // 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"); // 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 = "https://example.com"; String now = Instant.now().toString(); OrderV3 order = new OrderV3() .setCreateTime(now) .setLastUpdateTime(now) .setMerchantOrderId("UNIQUE_ORDER_ID") .setUserVisibleOrderId("UNIQUE_USER_VISIBLE_ORDER_ID") .setTransactionMerchant(transactionMerchant) .setContents(contents) .setBuyerInfo(buyerInfo) .setFollowUpActions(Arrays.asList( viewDetails, call, email )) .setTermsOfServiceUrl(termsOfServiceUrl); return order; }
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_DECISION", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "order": { "createTime": "2019-07-17T18:25:30.182Z", "lastUpdateTime": "2019-07-17T18:25:30.182Z", "merchantOrderId": "UNIQUE_ORDER_ID", "userVisibleOrderId": "USER_VISIBLE_ORDER_ID", "transactionMerchant": { "id": "https://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Dinner reservation", "description": "A world of flavors all in one destination.", "reservation": { "status": "PENDING", "userVisibleStatusLabel": "Reservation is pending.", "type": "RESTAURANT", "reservationTime": { "timeIso8601": "2020-01-16T01:30:15.01Z" }, "userAcceptableTimeRange": { "timeIso8601": "2020-01-15/2020-01-17" }, "partySize": 6, "staffFacilitators": [ { "name": "John Smith" } ], "location": { "zipCode": "94086", "city": "Sunnyvale", "postalAddress": { "regionCode": "US", "postalCode": "94086", "administrativeArea": "CA", "locality": "Sunnyvale", "addressLines": [ "222, Some other Street" ] } } } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "followUpActions": [ { "type": "VIEW_DETAILS", "title": "View details", "openUrlAction": { "url": "https://example.com" } }, { "type": "CALL", "title": "Call us", "openUrlAction": { "url": "tel:+16501112222" } }, { "type": "EMAIL", "title": "Email us", "openUrlAction": { "url": "mailto:person@example.com" } } ], "termsOfServiceUrl": "https://www.example.com" }, "orderOptions": { "requestDeliveryAddress": false, "userInfoOptions": { "userInfoProperties": [ "EMAIL" ] } }, "presentationOptions": { "actionDisplayName": "RESERVE" } } } } } }
3. Đề xuất đơn đặt hàng
Trình đơn đặt chỗ của bạn cho người dùng để họ xác nhận hoặc
từ chối. Yêu cầu actions.intent.TRANSACTION_DECISION
ý định và cung cấp Order
mà bạn đã tạo.
Trải nghiệm người dùng
Khi bạn yêu cầu ý định actions.intent.TRANSACTION_DECISION
, Trợ lý
bắt đầu một trải nghiệm tích hợp sẵn trong đó Order
hiển thị trực tiếp trên "thẻ xem trước giỏ hàng". Người dùng có thể nói "lên lịch đặt chỗ",
từ chối giao dịch hoặc yêu cầu thay đổi thông tin đặt chỗ.
Vào thời điểm này, người dùng cũng có thể yêu cầu thay đổi đơn đặt hàng. Trong trường hợp này, bạn cần đảm bảo phương thức thực hiện đơn hàng của mình có thể xử lý các yêu cầu thay đổi đơn đặt hàng sau hoàn tất quy trình lắp ráp giỏ hàng.
Quy trình thực hiện đơn hàng
Khi bạn yêu cầu
Ý định actions.intent.TRANSACTION_DECISION
, hãy tạo một
TransactionDecision
chứa Order
và orderOptions
Đoạn mã sau đây cho thấy ví dụ về TransactionsDecision
cho một đơn đặt hàng:
conv.ask(new TransactionDecision({ orderOptions: { requestDeliveryAddress: 'false', }, presentationOptions: { actionDisplayName: 'RESERVE', }, order: order, }));
// Create order options OrderOptionsV3 orderOptions = new OrderOptionsV3() .setRequestDeliveryAddress(false) .setUserInfoOptions(new UserInfoOptions() .setUserInfoProperties(Collections.singletonList("EMAIL"))); // Create presentation options PresentationOptionsV3 presentationOptions = new PresentationOptionsV3() .setActionDisplayName("RESERVE"); // Ask for transaction decision return getResponseBuilder(request) .add("Placeholder for transaction decision text") .add(new TransactionDecision() .setOrder(order) .setOrderOptions(orderOptions) .setPresentationOptions(presentationOptions) ) .build();
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.TRANSACTION_DECISION", "data": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "requestDeliveryAddress": "false" }, "presentationOptions": { "actionDisplayName": "RESERVE" }, "order": { "createTime": "2019-07-17T18:25:30.184Z", "lastUpdateTime": "2019-07-17T18:25:30.184Z", "merchantOrderId": "UNIQUE_ORDER_ID", "userVisibleOrderId": "USER_VISIBLE_ORDER_ID", "transactionMerchant": { "id": "https://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Dinner reservation", "description": "A world of flavors all in one destination.", "reservation": { "status": "PENDING", "userVisibleStatusLabel": "Reservation is pending.", "type": "RESTAURANT", "reservationTime": { "timeIso8601": "2020-01-16T01:30:15.01Z" }, "userAcceptableTimeRange": { "timeIso8601": "2020-01-15/2020-01-17" }, "partySize": 6, "staffFacilitators": [ { "name": "John Smith" } ], "location": { "zipCode": "94086", "city": "Sunnyvale", "postalAddress": { "regionCode": "US", "postalCode": "94086", "administrativeArea": "CA", "locality": "Sunnyvale", "addressLines": [ "222, Some other Street" ] } } } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "followUpActions": [ { "type": "VIEW_DETAILS", "title": "View details", "openUrlAction": { "url": "https://example.com" } }, { "type": "CALL", "title": "Call us", "openUrlAction": { "url": "tel:+16501112222" } }, { "type": "EMAIL", "title": "Email us", "openUrlAction": { "url": "mailto:person@example.com" } } ], "termsOfServiceUrl": "https://www.example.com" } } } } } }
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TRANSACTION_DECISION", "inputValueData": { "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec", "orderOptions": { "requestDeliveryAddress": "false" }, "presentationOptions": { "actionDisplayName": "RESERVE" }, "order": { "createTime": "2019-07-17T18:25:30.057Z", "lastUpdateTime": "2019-07-17T18:25:30.057Z", "merchantOrderId": "UNIQUE_ORDER_ID", "userVisibleOrderId": "USER_VISIBLE_ORDER_ID", "transactionMerchant": { "id": "https://www.example.com", "name": "Example Merchant" }, "contents": { "lineItems": [ { "id": "LINE_ITEM_ID", "name": "Dinner reservation", "description": "A world of flavors all in one destination.", "reservation": { "status": "PENDING", "userVisibleStatusLabel": "Reservation is pending.", "type": "RESTAURANT", "reservationTime": { "timeIso8601": "2020-01-16T01:30:15.01Z" }, "userAcceptableTimeRange": { "timeIso8601": "2020-01-15/2020-01-17" }, "partySize": 6, "staffFacilitators": [ { "name": "John Smith" } ], "location": { "zipCode": "94086", "city": "Sunnyvale", "postalAddress": { "regionCode": "US", "postalCode": "94086", "administrativeArea": "CA", "locality": "Sunnyvale", "addressLines": [ "222, Some other Street" ] } } } } ] }, "buyerInfo": { "email": "janedoe@gmail.com", "firstName": "Jane", "lastName": "Doe", "displayName": "Jane Doe" }, "followUpActions": [ { "type": "VIEW_DETAILS", "title": "View details", "openUrlAction": { "url": "https://example.com" } }, { "type": "CALL", "title": "Call us", "openUrlAction": { "url": "tel:+16501112222" } }, { "type": "EMAIL", "title": "Email us", "openUrlAction": { "url": "mailto:person@example.com" } } ], "termsOfServiceUrl": "https://www.example.com" } } } ] } ] }
Xử lý quyết định của người dùng
Sau khi người dùng phản hồi đơn đặt hàng được đề xuất, phương thức thực hiện đơn hàng của bạn sẽ nhận được
Ý định actions_intent_TRANSACTION_DECISION
với một đối số chứa
TransactionDecisionValue
Giá trị này sẽ bao gồm:
transactionDecision
- Quyết định của người dùng về đề xuất đơn đặt hàng. Các giá trị có thể làORDER_ACCEPTED
,ORDER_REJECTED
,CART_CHANGE_REQUESTED
vàUSER_CANNOT_TRANSACT
.
Để xử lý yêu cầu này, hãy khai báo ý định Dialogflow được kích hoạt bằng
sự kiện actions_intent_TRANSACTION_DECISION
. Xử lý ý định này trong
phương thức thực hiện của bạn:
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE'); if (arg && arg.transactionDecision === 'ORDER_ACCEPTED') { console.log('order accepted'); const order = arg.order; }
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"); } if ((transactionDecision != null && transactionDecision.equals("ORDER_ACCEPTED"))) { OrderV3 order = ((OrderV3) extension.get("order")); }
Xin lưu ý rằng tệp JSON bên dưới mô tả một yêu cầu webhook.
{ "responseId": "", "queryResult": { "queryText": "", "action": "", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "", "fulfillmentMessages": [], "outputContexts": [], "intent": { "name": "reservation_get_transaction_decision_df", "displayName": "reservation_get_transaction_decision_df" }, "intentDetectionConfidence": 1, "diagnosticInfo": {}, "languageCode": "" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "isInSandbox": true, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "inputs": [ { "rawInputs": [], "intent": "", "arguments": [] } ], "user": {}, "conversation": {}, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "" }
Xin lưu ý rằng tệp JSON bên dưới mô tả một yêu cầu webhook.
{ "user": {}, "device": {}, "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "conversation": {}, "inputs": [ { "rawInputs": [], "intent": "reservation_get_transaction_decision_asdk", "arguments": [] } ], "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] }
4. Hoàn tất yêu cầu đặt chỗ và gửi biên nhận
Khi ý định actions.intent.TRANSACTION_DECISION
trả về với một
transactionDecision
trong số ORDER_ACCEPTED
, thực hiện bất kỳ thứ gì
quá trình xử lý là bắt buộc để lên lịch đặt trước (chẳng hạn như duy trì nó trong
cơ sở dữ liệu của riêng bạn).
Gửi một câu trả lời đơn giản để duy trì cuộc trò chuyện. Người dùng nhận được "thẻ biên nhận đã thu gọn" cùng với phản hồi của bạn.
Quy trình thực hiện đơn hàng
// Set lastUpdateTime and update status of reservation order.lastUpdateTime = new Date().toISOString(); order.reservation.status = 'CONFIRMED'; order.reservation.userVisibleStatusLabel = 'Reservation confirmed'; order.reservation.confirmationCode = '123ABCDEFGXYZ'; // Send synchronous order update conv.ask(`Transaction completed! You're all set!`); conv.ask(new OrderUpdate({ type: 'SNAPSHOT', reason: 'Reason string', order: order, }));
ResponseBuilder responseBuilder = getResponseBuilder(request); order.setLastUpdateTime(Instant.now().toString()); // Set reservation status to confirmed and provide confirmation code LineItemV3 lineItem = order.getContents().getLineItems().get(0); ReservationItemExtension reservationItemExtension = lineItem.getReservation(); reservationItemExtension.setStatus("CONFIRMED"); reservationItemExtension.setUserVisibleStatusLabel("Reservation confirmed."); reservationItemExtension.setConfirmationCode("123ABCDEFGXYZ"); lineItem.setReservation(reservationItemExtension); order.getContents().getLineItems().set(0, lineItem); // Order update OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setType("SNAPSHOT") .setReason("Reason string") .setOrder(order); responseBuilder .add("Transaction completed! You're all set! Would you like to do anything else?") .add(new StructuredResponse().setOrderUpdateV3(orderUpdate)); return responseBuilder.build();
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! You're all set!" } }, { "structuredResponse": { "orderUpdateV3": { "type": "SNAPSHOT", "reason": "Reason string", "order": { "merchantOrderId": "UNIQUE_ORDER_ID", "reservation": { "status": "CONFIRMED", "userVisibleStatusLabel": "Reservation confirmed", "confirmationCode": "123ABCDEFGXYZ" }, "lastUpdateTime": "2019-07-17T18:25:30.187Z" } } } } ] } } } }
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Transaction completed! You're all set!" } }, { "structuredResponse": { "orderUpdateV3": { "type": "SNAPSHOT", "reason": "Reason string", "order": { "merchantOrderId": "UNIQUE_ORDER_ID", "reservation": { "status": "CONFIRMED", "userVisibleStatusLabel": "Reservation confirmed", "confirmationCode": "123ABCDEFGXYZ" }, "lastUpdateTime": "2019-07-17T18:25:30.059Z" } } } } ] } } } ] }
5. Gửi thông tin cập nhật về đơn đặt hàng
Trạng thái đặt trước thay đổi trong khoảng thời gian vòng đời của nó. Gửi thông tin cập nhật về đơn đặt hàng đặt trước của người dùng bằng HTTP PATCH yêu cầu tới Orders API, chứa trạng thái và thông tin chi tiết của đơn đặt hàng.
Thiết lập các yêu cầu không đồng bộ cho Orders API
Các yêu cầu cập nhật đơn đặt hàng đối với Orders API được cấp phép bằng quyền truy cập
mã thông báo. Để cập nhật thông tin đơn đặt hàng cho Orders API, hãy tải một tệp JSON xuống
khoá tài khoản dịch vụ được liên kết với dự án Actions Console của bạn, sau đó trao đổi
mã tài khoản dịch vụ cho mã thông báo mang có thể được truyền vào
Tiêu đề Authorization
của yêu cầu HTTP.
Để truy xuất khoá tài khoản dịch vụ, hãy làm theo các bước sau:
- Trong bảng điều khiển Google Cloud, chuyển đến Trình đơn PublisherCode > API và Dịch vụ > Thông tin xác thực > Tạo thông tin xác thực > Khoá tài khoản dịch vụ.
- Trong phần Tài khoản dịch vụ, hãy chọn Tài khoản dịch vụ mới.
- Đặt tài khoản dịch vụ thành
service-account
. - Đặt Vai trò thành Dự án > Chủ sở hữu.
- Đặt loại khoá thành JSON.
- Chọn Tạo.
- Khoá tài khoản dịch vụ JSON riêng tư sẽ được tải xuống máy cục bộ của bạn.
Trong mã cập nhật đơn đặt hàng của bạn, hãy đổi khoá dịch vụ lấy mã thông báo mang bằng cách sử dụng thư viện ứng dụng API của Google và phạm vi "https://www.googleapis.com/auth/actions.order.developer". Bạn có thể tìm thấy các bước cài đặt và các ví dụ trên trang GitHub của thư viện ứng dụng API.
Tham chiếu order-update.js
trong các mẫu Node.js và Java của chúng tôi cho
một ví dụ về trao đổi khoá.
Gửi thông tin cập nhật về đơn đặt hàng
Sau khi bạn đổi khoá tài khoản dịch vụ của mình lấy mã thông báo của phương thức mang OAuth, hãy gửi thông tin cập nhật về đơn đặt hàng dưới dạng các yêu cầu PATCH được uỷ quyền đối với Orders API.
URL của API đơn đặt hàng:
PATCH https://actions.googleapis.com/v3/orders/${orderId}
Hãy cung cấp các tiêu đề sau trong yêu cầu của bạn:
"Authorization: Bearer token"
bằng mã thông báo phương thức truyền OAuth mà bạn đã đổi khoá tài khoản dịch vụ."Content-Type: application/json"
.
Yêu cầu PATCH phải lấy phần nội dung JSON có định dạng sau:
{ "orderUpdate": OrderUpdate }
OrderUpdate
đối tượng bao gồm các trường cấp cao nhất sau đây:
updateMask
– Các trường của đơn đặt hàng mà bạn đang cập nhật. Để cập nhật trạng thái đặt trước, đặt giá trị thànhreservation.status, reservation.userVisibleStatusLabel
.order
– Nội dung của bản cập nhật. Nếu bạn đang cập nhật nội dung của phần đặt trước, hãy đặt giá trị thành đối tượngOrder
đã cập nhật. Nếu bạn chỉ cập nhật trạng thái của đặt chỗ (ví dụ: từ"PENDING"
đến"FULFILLED"
), đối tượng này sẽ chứa các trường sau:merchantOrderId
– Mã nhận dạng mà bạn đặt trong đối tượngOrder
.lastUpdateTime
– Dấu thời gian của lần cập nhật này.purchase
– Đối tượng chứa:status
– Trạng thái của đơn đặt hàng dưới dạngReservationStatus
, chẳng hạn như "CONFIRMED
" hoặc "CANCELLED
".userVisibleStatusLabel
– Nhãn dành cho người dùng cung cấp thông tin chi tiết về trạng thái đơn đặt hàng, chẳng hạn như "Yêu cầu đặt chỗ của bạn đã được xác nhận".
userNotification
(không bắt buộc) – MộtuserNotification
có thể hiển thị trên thiết bị của người dùng khi bản cập nhật này được gửi. Ghi chú việc bao gồm đối tượng này không đảm bảo rằng thông báo sẽ xuất hiện thiết bị của người dùng.
Mã mẫu sau đây cho thấy ví dụ về OrderUpdate
cập nhật
trạng thái của đơn đặt hàng đặt trước tới FULFILLED
:
// 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 orderUpdateJson = new OrderUpdate({ updateMask: [ 'lastUpdateTime', 'contents.lineItems.reservation.status', 'contents.lineItems.reservation.userVisibleStatusLabel', ].join(','), order: { merchantOrderId: orderId, lastUpdateTime: new Date().toISOString(), contents: { lineItems: [ { reservation: { status: 'FULFILLED', userVisibleStatusLabel: 'Reservation fulfilled', }, } ] } }, reason: 'Reservation status was updated to fulfilled.', }); // 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: orderUpdateJson, }, 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; } }); });
// Create order update FieldMask fieldMask = FieldMask.newBuilder().addAllPaths(Arrays.asList( "lastUpdateTime", "contents.lineItems.reservation.status", "contents.lineItems.reservation.userVisibleStatusLabel")) .build(); OrderUpdateV3 orderUpdate = new OrderUpdateV3() .setOrder(new OrderV3() .setMerchantOrderId(orderId) .setLastUpdateTime(Instant.now().toString()) .setContents(new OrderContents() .setLineItems(Collections.singletonList(new LineItemV3() .setReservation(new ReservationItemExtension() .setStatus("FULFILLED") .setUserVisibleStatusLabel("Reservation fulfilled.")))))) .setUpdateMask(FieldMaskUtil.toString(fieldMask)) .setReason("Reservation status was updated to fulfilled."); // 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);
Đặt trạng thái đặt chỗ
ReservationStatus
của đơn đặt hàng mới cập nhật
phải mô tả trạng thái hiện tại của đơn đặt hàng. Trong order.ReservationStatus
của bản cập nhật
, hãy sử dụng một trong các giá trị sau:
PENDING
- Yêu cầu đặt trước đã được "tạo" theo Hành động của bạn, nhưng cần có xử lý bổ sung trên nền tảng của bạn.CONFIRMED
– Yêu cầu đặt chỗ sẽ được xác nhận trong phụ trợ lập lịch.CANCELLED
– Người dùng đã hủy yêu cầu đặt chỗ của họ.FULFILLED
– Dịch vụ đã thực hiện đặt trước của người dùng.CHANGE_REQUESTED
– Người dùng đã yêu cầu thay đổi thông tin đặt chỗ và thay đổi đó đang được xử lý.REJECTED
– Nếu bạn không thể xử lý hoặc không thể xử lý xác nhận đặt chỗ.
Gửi nội dung cập nhật đơn đặt hàng cho mỗi trạng thái có liên quan đến
. Ví dụ: Nếu yêu cầu đặt chỗ của bạn yêu cầu xử lý thủ công để
xác nhận yêu cầu đặt chỗ sau khi được yêu cầu, gửi thông tin cập nhật về đơn đặt hàng với giá PENDING
cho đến
đã xử lý thêm. Không phải lượt đặt trước nào cũng yêu cầu mọi giá trị trạng thái.
Khắc phục sự cố
Nếu bạn gặp bất kỳ vấn đề nào trong khi thử nghiệm, hãy đọc các bước khắc phục sự cố của chúng tôi cho các giao dịch.