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

بعد أن يرسل العميل طلب الطعام، يمكنك إرسال رسالة تحديث الطلب إلى خدمة "الطلب من خلال 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. من المفترض أن يتم ردّ الأموال المدفوعة مقابل خدمة "الطلب من خلال Google" استنادًا إلى سياسة الإلغاء وحالة الدفعات في وقت الإلغاء.

لا تحتاج خدمة "الطلب من خلال Google" إلى التوافق مع جميع الولايات وعمليات النقل المتاحة. ومع ذلك، يجب أن تكون الحالة النهائية للطلب 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". يرسل 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"
            }
          }
        }
      ]
    }
  }
}
    

الاستعداد

يعرض هذا المثال نموذجًا لطلب تعديل الطلب يُعلِم المستخدم بأنه يتم تحضير الطعام في الوقت الحالي.

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

الاستعداد_للاستلام

يعرض هذا المثال نموذجًا لطلب تعديل الطلب يُعلِم المستخدم بأن الطعام جاهز للاستلام.

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

النقل

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

{
  "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" من التحقّق من أن الرسالة واردة من خدمة "الطلب من خلال Google" على الويب.

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

  1. أنشئ رمزًا مميزًا للتفويض باتّباع الخطوات التالية:
    1. يمكنك استخدام مكتبة مصادقة Google لقراءة بيانات الاعتماد من ملف حساب الخدمة.
    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 خطأً.