אחרי שלקוח שולח הזמנת אוכל, תוכלו לשלוח הודעה על עדכון ההזמנה לשירות מקצה לקצה כדי להודיע לנו על השינוי.
הנה כמה סיבות נפוצות לשליחת עדכונים של הזמנות:
- זמן האספקה המשוער של ההזמנה יהפוך לזמין או ישתנה.
- המצב של הזמנה משתנה.
- לא ניתן יותר למלא את ההזמנה.
- המחיר של פריט בתפריט שנכלל בהזמנה השתנה.
- ללקוח יש דרך חדשה לנהל את ההזמנה, כמו תמיכת לקוחות או מספר טלפון של מסעדה.
- הקבלה על ההזמנה הופכת לזמינה.
בקטעים הבאים מוסבר איך לטפל בתרחישים השונים בעזרת עדכוני הזמנות.
מצבים של הזמנת העברה
להזמנה יש שישה מצבים אפשריים. המצבים האלה והמעברים האפשריים שלהם מפורטים בתרשים הבא:
כשלקוח שולח הזמנה בפעם הראשונה, ההזמנה מתחילה במצב 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
. 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" } } } }
מוכנה
בדוגמה הבאה מוצגת בקשה לעדכון הזמנה, שמיידעת את המשתמש שההזמנה נאספת או נמסרה:
{ "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" } } } ] } } }
לקבלת דוגמאות נוספות של בקשות לעדכון הזמנות בתרחישים שונים לדוגמה, תוכלו לקרוא את המאמר הטמעת עדכונים להזמנות מראש.
יצירת אסימון הרשאה ושליחת ההודעה
עדכוני הזמנות מחייבים אסימון הרשאה, כדי שהשירות מקצה לקצה של הזמנות יוכל לאמת שההודעה היא משירות האינטרנט מקצה לקצה של ההזמנה.
כך מטמיעים עדכוני הזמנות בפרויקט:
- כדי ליצור אסימון הרשאה:
- משתמשים בספריית האימות של Google כדי לקרוא את פרטי הכניסה מקובץ חשבון השירות.
- בקשה לאסימון באמצעות היקף ה-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 עבור 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 עבור 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 עם מטען ייעודי (payload) ריק. אם יש בעיה, למשל שגיאה בפורמט העדכון, Google מחזירה שגיאה.