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

بعد أن يرسل العميل طلب الطعام، يمكنك إرسال رسالة تحديث الطلب إلى خدمة "الطلب الشامل" لإشعارنا بالتغيير.

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

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

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

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

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

عمليات الانتقال في حالة الطلب

عندما يرسِل العميل الطلب لأول مرة، يبدأ الطلب بالحالة 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.

لإدارة توقعات المستخدم بشكل فعال، كن متحفظًا في تقديراتك وقدم تاريخًا ونطاقًا زمنيًا بدلاً من تاريخ ووقت ثابتين. يجب عليك مراعاة الاختلافات مثل ظروف حركة المرور كلما أمكن ذلك. مثال

تقديم إجراءات إدارة الطلبات

عند إرسال تعديل على طلبك، يمكنك تقديم الموارد للعملاء الذين تساعدهم في إدارة طلباتهم على شكل 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"
            }
          }
        }
      ]
    }
  }
}
    

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

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

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

لتطبيق تعديلات على الطلبات لمشروعك، يُرجى اتّباع الخطوات التالية:

  1. إنشاء رمز مميّز للتفويض باتّباع الخطوات التالية:
    1. يمكنك استخدام Google Auth Library لقراءة بيانات الاعتماد من ملف حساب الخدمة.
    2. اطلب الرمز المميّز باستخدام نطاق واجهة برمجة التطبيقات التالي: 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 بحمولة فارغة. إذا كانت هناك مشكلة، مثل كون التحديث غير صحيح، يعرض Google خطأ.