עדכון של הזמנה אסינכרונית

אחרי שלקוח שולח הזמנת אוכל, אתם יכולים לשלוח לשירות 'הזמנה עם Google' הודעה עם עדכון על השינוי כדי להודיע לנו על השינוי.

הנה כמה סיבות נפוצות לשליחת עדכוני הזמנות:

  • זמן האספקה המשוער של ההזמנה הופך לזמין או משתנה.
  • סטטוס ההזמנה משתנה.
  • כבר לא ניתן למלא את ההזמנה.
  • המחיר של פריט בתפריט שצוין בהזמנה השתנה.
  • ללקוח יש דרך חדשה לנהל את ההזמנה, למשל תמיכת לקוחות או מספר טלפון של מסעדה.
  • הקבלה על ההזמנה תהיה זמינה.

בקטעים הבאים מתוארים אופן הטיפול בתרחישים השונים האלה באמצעות עדכוני הזמנות.

מעבר בין מדינות בהזמנה

להזמנה יש שישה מצבים אפשריים. הסטטוסים הבאים והמעברים האפשריים שלהם מתוארים בתרשים הבא:

העברות במצב הזמנה

כשלקוח שולח הזמנה בפעם הראשונה, היא מתחילה במצב 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. השירות של Order with Google צריך להנפיק החזרים כספיים בהתאם למדיניות הביטולים ולמצב התשלומים בזמן הביטול.

בשירות Order with Google, אין צורך לתמוך בכל המדינות והמעברים הזמינים. עם זאת, המצב הסופי של ההזמנה חייב להיות 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 כדי לשלוח עדכון הזמנה לשירות Order with Google. 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"
            }
          }
        }
      ]
    }
  }
}
    

דוגמאות נוספות לבקשות לעדכון הזמנות בתרחישים שונים לדוגמה זמינות במאמר הטמעת עדכונים מתקדמים של הזמנות.

יצירת אסימון הרשאה ושליחת ההודעה

לעדכוני הזמנות נדרש אסימון הרשאה, כדי ששירות Order with Google יוכל לאמת שההודעה נשלחה משירות האינטרנט של Order with Google.

כדי להטמיע עדכוני הזמנות בפרויקט, פועלים לפי השלבים הבאים:

  1. כדי ליצור אסימון הרשאה, צריך לפעול לפי ההוראות האלה:
    1. משתמשים בספריית האימות של Google כדי לקרוא את פרטי הכניסה מקובץ חשבון השירות.
    2. בקשת אסימון באמצעות היקף ה-API הבא: https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. צריך להשתמש באסימון הזה כדי לשלוח בקשת HTTP POST מאומתת לנקודת הקצה הבאה: https://actions.googleapis.com/v2/conversations:send
  3. יש להגדיר את הכותרת 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 עבור 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 החזירה שגיאה.