تعديل الطلب غير المتزامن

بعد أن يرسل العميل طلب طعام، يمكنك إرسال رسالة تعديل طلب إلى خدمة Ordering End-to-End لإعلامنا بالتغيير.

في ما يلي بعض الأسباب الشائعة لإرسال تعديلات على الطلبات:

  • يصبح الوقت المقدّر لاستيفاء الطلب متاحًا أو يتغيّر.
  • تغيُّر حالة طلب
  • لم يعُد بالإمكان تنفيذ الطلب.
  • تغيّر سعر أحد عناصر القائمة المضمّنة في الطلب.
  • يتوفّر للعميل طريقة جديدة لإدارة طلبه، مثل رقم هاتف فريق دعم العملاء أو رقم هاتف المطعم.
  • يصبح إيصال الطلب متاحًا.

تقدّم الأقسام التالية تفاصيل حول كيفية معالجة هذه السيناريوهات المختلفة باستخدام تعديلات الطلبات.

حالات الطلب أثناء النقل

يتضمّن الطلب ست حالات محتملة. تم توضيح هذه الحالات والحالات الانتقالية المحتملة في الرسم البياني التالي:

حالات انتقال حالة الطلب

عندما يرسل العميل طلبًا لأول مرة، تبدأ حالة الطلب بأحد القيم التالية: 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 مساءً (الحد الأدنى) إلى الساعة 1:15 مساءً (الحد الأقصى) لطلب يكون وقت التسليم المقدَّر له هو الساعة 1: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"
      }
    }
  }
}
  

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"
            }
          }
        }
      ]
    }
  }
}
    

لمزيد من الأمثلة على طلبات تعديل الطلبات في حالات استخدام مختلفة، يُرجى الاطّلاع على مقالة تنفيذ التعديلات المتقدّمة للطلبات.

إنشاء رمز مميّز للتفويض وإرسال الرسالة

تتطلّب تعديلات الطلبات الحصول على رمز مميّز لإذن الوصول كي تتمكّن خدمة "عملية الطلب الشاملة" من التحقّق من أنّ الرسالة واردة من خدمة الويب "عملية الطلب الشاملة".

لتنفيذ تعديلات الطلبات لمشروعك، اتّبِع الخطوات التالية:

  1. أنشئ رمز مميّزًا للتفويض باتّباع الخطوات التالية:
    1. استخدِم مكتبة Google Auth لقراءة بيانات الاعتماد من ملف حساب الخدمة.
    2. اطلب الرمز المميّز باستخدام نطاق واجهة برمجة التطبيقات التالي: https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. استخدِم هذا الرمز المميّز لإرسال طلب POST مصادق عليه عبر بروتوكول HTTP إلى نقطة النهاية التالية: 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 مع بيانات أساسية فارغة. إذا حدثت مشكلة، مثل عدم صحة التنسيق في التحديث، ستعرض Google رسالة خطأ.