אחרי שלקוח שולח הזמנה של אוכל, אתם יכולים לשלוח הודעה על עדכון ההזמנה לשירות 'הזמנות מקצה לקצה' כדי להודיע לנו על השינוי.
אלה כמה מהסיבות הנפוצות לשליחת עדכוני הזמנה:
- מועד הטיפול המשוער בהזמנה זמין או משתנה.
- הסטטוס של ההזמנה משתנה.
- לא ניתן יותר למלא את ההזמנה.
- המחיר של פריט בתפריט שכלול בהזמנה השתנה.
- הלקוח יקבל דרך חדשה לנהל את ההזמנה, כמו מספר טלפון של תמיכת לקוחות או של המסעדה.
- הקבלה על ההזמנה תהיה זמינה.
בקטעים הבאים מוסבר איך לטפל בתרחישים השונים האלה באמצעות עדכוני הזמנות.
מעבר בין מצבי ההזמנות
להזמנה יש שישה מצבים אפשריים. המצבים האלה והמעברים האפשריים ביניהם מפורטים בתרשים הבא:
כשלקוח שולח הזמנה בפעם הראשונה, ההזמנה מתחילה במצב CREATED
, CONFIRMED
או REJECTED
. אתם יכולים לשלוח הודעה עם עדכון לגבי ההזמנה כדי לעדכן את הסטטוס שלה, כל עוד המעבר בין הסטטוסים תקין. המצב CREATED
משמש כשפלטפורמת השותף לא יכולה לאשר או לדחות את ההזמנה באופן מיידי. דוגמה לתרחישים לדוגמה היא כשלקוח מבצע הזמנה דרך שירות אגרגטור של משלוחים. שירות האגרגטור של המשלוחים מקבל את המשלוח מ-Google, ואז שולח את המידע למסעדה. אחרי שהמסעדה קיבלה את הזמנה ואישרה את הזמינות שלה, המצב יכול להיות עכשיו CONFIRMED
, אחרת REJECTED
.
הזמנה במצב CONFIRMED
עוברת למצב IN_PREPARATION
. בהתאם לאופן האספקה (איסוף עצמי או משלוח), משתמשים בסטטוס READY_FOR_PICKUP
או בסטטוס IN_TRANSIT
. כשהאוכל נמסר או נאסף, ההזמנה מוגדרת למצב FULFILLED
.
אם אתם מאפשרים ללקוחות לבטל הזמנות, אתם יכולים להשתמש במצב CANCELLED
. אפשר לבטל הזמנה בסטטוסים CREATED
, CONFIRMED
, IN_PREPARATION
, READY_FOR_PICKUP
או IN_TRANSIT
.
שירות ההזמנות מקצה לקצה אמור להנפיק החזרים כספיים בהתאם למדיניות הביטולים ולסטטוס התשלומים בזמן הביטול.
שירות ההזמנות מקצה לקצה לא חייב לתמוך בכל המצבים והמעברים הזמינים. עם זאת, המצב הסופי של ההזמנה חייב להיות FULFILLED
, REJECTED
או CANCELLED
.
מתן מועד טיפול משוער
אתם יכולים לספק למשתמשים טווח זמן משוער שבו ההזמנה שלהם תהיה מוכנה לאיסוף (או תימסר). משתמשים בשדה estimatedFulfillmentTimeIso8601
של FoodOrderUpdateExtension
כדי לציין טווח זמן משוער שבו ההזמנה של הלקוח תהיה מוכנה לאיסוף או תימסר.
שולחים את estimatedFulfillmentTimeIso8601
במועדים הבאים:
- כשהזמן המשוער יהיה זמין, רצוי במצב ההזמנה
CREATED
אוCONFIRMED
. - כשהזמן המשוער משתנה, למשל כשמעדכנים את הזמן המשוער כדי שיהיה מדויק יותר כשההזמנה בסטטוס
IN_TRANSIT
.
כדי לנהל את הציפיות של המשתמשים בצורה יעילה, כדאי להעריך בזהירות ולציין טווח תאריכים ושעות במקום תאריך ושעה קבועים. כשהדבר אפשרי, כדאי להביא בחשבון גורמים משתנים כמו תנאי התנועה. לדוגמה, אפשר לשלוח הערכה של 12:45 (גבול תחתון) עד 13:15 (גבול עליון) להזמנה שבה זמן האספקה המשוער הוא 13:00.
מתן פעולות לניהול הזמנות
כששולחים עדכון לגבי הזמנה, אפשר לספק ללקוחות משאבים שיעזרו להם לנהל את ההזמנה שלהם באמצעות OrderManagementAction
. אחרי שלקוחות מבצעים הזמנה, יכול להיות שהם יצטרכו ליצור איתכם או עם המסעדה שמבצעת את ההזמנה קשר כדי לעקוב אחרי ההתקדמות, לבצע שינויים או לבטל את ההזמנה.
OrderManagementAction
מאפשר ללקוחות לשלוח אימייל, להתקשר או לקשר לכתובת URL ישירות מהמכשיר שלהם. צריך להשתמש באותם פרטים ב-OrderManagementAction
כמו בהודעת האישור על ההזמנה באימייל ששולחים למשתמש.
פעולות ניהול ההזמנות כוללות את הסוגים הבאים:
CUSTOMER_SERVICE
: מספקים ללקוחות אפשרות לפנות לשירות הלקוחות. סוג הפעולה הזו נדרש לעדכוני הזמנות.EMAIL
: מאפשרים ללקוחות לשלוח אימייל לכתובת האימייל שצוינה.CALL
: מבקשים מהלקוחות להתקשר למספר הטלפון שצוין.VIEW_DETAIL
: מבקשים מהלקוחות לבצע פעולה כדי להציג את פרטי ההזמנה שלהם.
כל עדכון של הזמנה חייב לכלול לפחות פעולה אחת לניהול ההזמנה. עם זאת, פעולות ניהול ההזמנות שמוצגות עשויות להשתנות בהתאם למצב ההזמנה.
לדוגמה, כשהזמנה נמצאת בסטטוס CONFIRMED
, הפעולה CUSTOMER_SERVICE
יכולה להפנות למספר הטלפון של שירות הלקוחות. כשסטטוס ההזמנה מתעדכן ל-IN_TRANSIT
, הפעולה CUSTOMER_SERVICE
יכולה להפנות למספר הטלפון של המסעדה שמבצעת את ההזמנה.
שליחת עדכונים לגבי ההזמנה
משתמשים בסוג ההודעה AsyncOrderUpdateRequestMessage
כדי לשלוח עדכון של הזמנה לשירות Ordering End-to-End. Google תחזיר AsyncOrderUpdateResponseMessage
. לדוגמה, אם רוצים להודיע ללקוח שההזמנה שלו תקפה ונתקבלה, אפשר לשלוח AsyncOrderUpdateRequestMessage
כדי לשנות את סטטוס ההזמנה ל-CONFIRMED
עם התווית Accepted by restaurant
.
הגדרת ההודעה על עדכון ההזמנה
כששולחים AsyncOrderUpdateRequestMessage
אל Google, צריך לכלול מידע על סטטוס ההזמנה באמצעות השדה OrderUpdate
.
בדוגמאות הבאות מוצגת AsyncOrderUpdateRequestMessage
לדוגמה לכל מצב הזמנה:
אושר
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שבה המשתמש מקבל הודעה על אישור ההזמנה עם קבלה ומועד אספקה משוער.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CONFIRMED", "label": "Provider confirmed" }, "receipt": { "userVisibleOrderId": "userVisibleId1234" }, "updateTime": "2017-07-17T12:00:00Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601": "2017-07-17T13:00:00Z/2017-07-17T13:30:00Z" } } } }
נדחה
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שבה המשתמש מקבל הודעה על כך שההזמנה נדחתה עם הסיבה לדחייה.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "UNKNOWN", "reason": "Sorry, the restaurant cannot take your order right now." }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "foodOrderErrors": [ { "error": "NO_CAPACITY", "description": "Sorry, the restaurant cannot take your order right now." } ] } } } }
בוטלה
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שבה המשתמש מקבל הודעה על ביטול ההזמנה עם הסיבה לביטול.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CANCELLED", "label": "Order cancelled" }, "updateTime": "2017-05-10T02:30:00.000Z", "cancellationInfo": { "reason": "Customer requested" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ] } } }
IN_PREPARATION
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שבה המשתמש מודיע שהוא מכין את האוכל.
{ "isInSandbox":true, "customPushMessage":{ "orderUpdate":{ "actionOrderId":"sample_action_order_id", "orderState":{ "state":"IN_PREPARATION", "label":"Order is being prepared" }, "receipt": { "userVisibleOrderId": "userVisibleId1234" }, "updateTime":"2018-04-15T11:30:00Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension":{ "@type":"type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601":"PT20M" } } } }
READY_FOR_PICKUP
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שבה מודיע למשתמש שהאוכל מוכן לאיסוף.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "READY_FOR_PICKUP", "label": "Order is ready for pickup" }, "receipt": { "userVisibleOrderId": "userVisibleId1234" }, "updateTime": "2018-04-15T12:00:00Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601": "PT20M" } } } }
IN_TRANSIT
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שבה מודיע למשתמש שההזמנה בדרך ומצוין זמן אספקה משוער.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "IN_TRANSIT", "label": "Order is on the way" }, "inTransitInfo": { "updatedTime": "2017-07-17T12:00:00Z" }, "updateTime": "2017-07-17T12:00:00Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601": "PT20M" } } } }
FULFILLED
בדוגמה הזו מוצגת בקשה לדוגמה לעדכון הזמנה, שמעדכנת את המשתמש שההזמנה נאספה או נמסרה:
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "FULFILLED", "label": "Order delivered" }, "updateTime": "2017-05-10T02:30:00.000Z", "fulfillmentInfo": { "deliveryTime": "2017-05-10T02:30:00.000Z" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ] } } }
דוגמאות נוספות לבקשות לעדכון הזמנות בתרחישי שימוש שונים מפורטות במאמר הטמעת עדכוני הזמנות מתקדמים.
יצירת אסימון הרשאה ושליחת ההודעה
כדי לעדכן הזמנות, נדרש אסימון הרשאה כדי ששירות Ordering End-to-End יוכל לאמת שההודעה מגיעה משירות האינטרנט של Ordering End-to-End.
כדי להטמיע עדכוני הזמנות בפרויקט:
- כדי ליצור אסימון הרשאה:
- משתמשים ב-Google Auth Library כדי לקרוא את פרטי הכניסה מקובץ חשבון השירות.
- מבקשים אסימון באמצעות היקף ה-API הבא:
https://www.googleapis.com/auth/actions.fulfillment.conversation
- משתמשים באסימון הזה כדי לשלוח בקשת HTTP POST מאומתת לנקודת הקצה הבאה:
https://actions.googleapis.com/v2/conversations:send
- מגדירים את הכותרת
Content-Type
ל-application/json
כחלק מהבקשה.
בדוגמאות הבאות מוסבר איך מטמיעים עדכוני הזמנות:
Node.js
הקוד הזה משתמש ב-Google Auth Library ל-Node.js.
const {auth} = require('google-auth-library') const request = require('request'); // The service account client secret file downloaded from the Google Cloud Console const serviceAccountJson = require('./service-account.json') // order-update.json is a file that contains the payload const jsonBody = require('./order-update.json') /** * Get the authorization token using a service account. */ async function getAuthToken() { let client = auth.fromJSON(serviceAccountJson) client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation'] const tokens = await client.authorize() return tokens.access_token; } /** * Send an order update request */ async function sendOrderUpdate() { const token = await getAuthToken() request.post({ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, url: 'https://actions.googleapis.com/v2/conversations:send', body: jsonBody, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) }
Python
הקוד הזה משתמש בספריית Google Auth ל-Python.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json # service-account.json is the service account client secret file downloaded from the # Google Cloud Console credentials = service_account.Credentials.from_service_account_file( 'service-account.json') scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/actions.fulfillment.conversation']) authed_session = AuthorizedSession(scoped_credentials) # order-update.json is a file that contains the payload json_payload=json.load(open('order-update.json')) response = authed_session.post( 'https://actions.googleapis.com/v2/conversations:send', json=json_payload)
Java
הקוד הזה משתמש ב-Google Auth Library ל-Java.
/** * Get the authorization token using a service account. */ private static String getAuthToken() { InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json"); ServiceAccountCredentials.Builder credentialsSimpleBuilder = ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder(); credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/actions.fulfillment.conversation")); AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken(); return accessToken.getTokenValue(); } /** * Send an order update request */ public void sendOrderUpdate() { String authToken = getAuthToken(); // Execute POST request executePostRequest("https://actions.googleapis.com/v2/conversations:send", authToken, "update_order_example.json",); }
אם עדכוני ההזמנות בוצעו ללא שגיאות, Google מחזירה תגובה מסוג HTTP 200 עם עומס נתונים ריק. אם הייתה בעיה, למשל העדכון היה בפורמט שגוי, Google תחזיר שגיאה.