Cập nhật đơn đặt hàng không đồng bộ

Sau khi khách hàng gửi đơn đặt món ăn, bạn có thể gửi thông báo cập nhật đơn đặt hàng đến dịch vụ Đặt hàng đầu cuối để thông báo cho chúng tôi về thay đổi.

Dưới đây là một số lý do phổ biến dẫn đến việc gửi thông tin cập nhật về đơn đặt hàng:

  • Thời gian thực hiện ước tính cho đơn đặt hàng sẽ có sẵn hoặc thay đổi.
  • Trạng thái của đơn đặt hàng sẽ thay đổi.
  • Không thể thực hiện đơn đặt hàng nữa.
  • Giá của một món trong thực đơn có trong đơn đặt hàng đã thay đổi.
  • Khách hàng có một cách mới để quản lý đơn đặt hàng của mình, chẳng hạn như dịch vụ hỗ trợ khách hàng hoặc số điện thoại của nhà hàng.
  • Biên lai cho đơn đặt hàng sẽ có sẵn.

Các phần tiếp theo cung cấp thông tin chi tiết về cách giải quyết những trường hợp khác nhau này thông qua cập nhật đơn đặt hàng.

Trạng thái thứ tự chuyển đổi

Một đơn đặt hàng có thể có sáu trạng thái. Các trạng thái này và quá trình chuyển đổi có thể xảy ra được trình bày trong biểu đồ sau:

Sắp xếp thứ tự chuyển đổi trạng thái

Khi khách hàng gửi đơn đặt hàng lần đầu tiên, đơn đặt hàng sẽ bắt đầu với trạng thái CREATED, CONFIRMED hoặc REJECTED. Bạn có thể gửi tin nhắn cập nhật đơn đặt hàng tới cập nhật trạng thái của đơn đặt hàng, miễn là quá trình chuyển đổi trạng thái hợp lệ. CREATED Trạng thái được dùng khi nền tảng của đối tác không thể xác nhận hoặc từ chối đơn đặt hàng ngay lập tức. Một ví dụ về trường hợp sử dụng là khi khách hàng đặt hàng thông qua dịch vụ giao hàng trang web tổng hợp. Đơn vị tập hợp giao hàng sẽ nhận hàng giao từ Google, và trang web tổng hợp gửi thông tin đến nhà hàng. Sau khi nhà hàng đã nhận được và đã xác nhận tình trạng còn hàng của đơn đặt hàng, trạng thái hiện có thể là CONFIRMED, nếu không REJECTED

Một đơn đặt hàng trong trạng thái CONFIRMED tiếp theo sẽ chuyển sang trạng thái IN_PREPARATION. Tuỳ thuộc vào việc đơn đặt hàng là để đến lấy hàng hay giao hàng, tiếp theo, hãy sử dụng trạng thái READY_FOR_PICKUP hoặc IN_TRANSIT. Khi đồ ăn được giao hoặc đến lấy, đơn đặt hàng được đặt thành trạng thái FULFILLED.

Nếu cho phép khách hàng huỷ đơn đặt hàng, bạn có thể sử dụng trạng thái CANCELLED. Bạn có thể huỷ đơn đặt hàng khi ở trạng thái CREATED, CONFIRMED, IN_PREPARATION, READY_FOR_PICKUP hoặc IN_TRANSIT. Dịch vụ đặt hàng trọn gói sẽ tiến hành hoàn tiền tuỳ theo chính sách huỷ và trạng thái thanh toán tại thời điểm huỷ.

Dịch vụ Đặt hàng hai đầu của bạn không cần phải hỗ trợ tất cả các tiểu bang hiện có và hiệu ứng chuyển cảnh. Tuy nhiên, trạng thái cuối cùng của đơn đặt hàng phảiFULFILLED, REJECTED hoặc CANCELLED.

Cung cấp thời gian thực hiện đơn hàng ước tính

Bạn có thể cung cấp cho người dùng khoảng thời gian ước tính về thời điểm đơn đặt hàng của họ sẵn sàng để đến lấy hàng (hoặc được giao). Dùng trường estimatedFulfillmentTimeIso8601FoodOrderUpdateExtension để cung cấp khoảng thời gian ước tính khi một đơn đặt hàng của khách hàng sẵn sàng để đến lấy hàng hoặc được giao.

Gửi estimatedFulfillmentTimeIso8601 vào những thời điểm sau:

  • Khi có thông tin về thời gian dự kiến, tốt nhất là theo thứ tự CREATED hoặc Trạng thái CONFIRMED.
  • Khi thời gian dự kiến thay đổi, chẳng hạn như cập nhật thời gian dự kiến để chính xác hơn khi đơn đặt hàng là IN_TRANSIT.

Để quản lý kỳ vọng của người dùng một cách hiệu quả, hãy thận trọng khi ước tính và cung cấp phạm vi ngày và giờ thay vì ngày và giờ cố định. Bạn nên tính đến các biến động như tình trạng lưu lượng truy cập bất cứ khi nào có thể. Cho Ví dụ: bạn có thể gửi thời gian ước tính là 12:45 chiều (giới hạn dưới) đến 1:15 chiều (giới hạn trên) ràng buộc) đối với đơn đặt hàng có thời gian giao hàng dự kiến là 1 giờ chiều.

Cung cấp các thao tác quản lý đơn đặt hàng

Khi gửi thông tin cập nhật về đơn đặt hàng, bạn có thể cung cấp tài nguyên giúp khách hàng chúng quản lý đơn đặt hàng dưới dạng OrderManagementAction. Sau một khách hàng đặt món, họ có thể cần liên hệ với bạn hoặc nhà hàng thực hiện đơn đặt hàng để theo dõi tiến trình, thay đổi hoặc huỷ đơn đặt hàng.

OrderManagementAction cho phép khách hàng gửi email, gọi điện thoại hoặc liên kết đến URL ngay trên thiết bị của họ. Sử dụng cùng một thông tin trong OrderManagementAction như trong email xác nhận đơn đặt hàng mà bạn gửi đến người dùng.

Thao tác quản lý đơn đặt hàng bao gồm các loại sau:

  • CUSTOMER_SERVICE: Cung cấp cho khách hàng một thao tác để liên hệ với khách hàng . Bạn bắt buộc phải sử dụng loại thao tác quản lý này để cập nhật đơn đặt hàng.
  • EMAIL: Cung cấp cho khách hàng một thao tác để gửi email đến địa chỉ email.
  • CALL: Thực hiện thao tác cho khách hàng để gọi đến số điện thoại được cung cấp.
  • VIEW_DETAIL: Thực hiện một thao tác để khách hàng xem chi tiết về đơn đặt hàng.

Mỗi nội dung cập nhật đơn đặt hàng phải chứa ít nhất một thao tác quản lý đơn đặt hàng. Tuy nhiên, thì các thao tác quản lý đơn đặt hàng được cung cấp có thể thay đổi tuỳ theo trạng thái của đơn đặt hàng. Ví dụ: khi một đơn đặt hàng ở trạng thái CONFIRMED, CUSTOMER_SERVICE có thể trỏ đến số điện thoại dịch vụ khách hàng của bạn. Khi đơn đặt hàng đó có trạng thái cập nhật lên IN_TRANSIT, thao tác CUSTOMER_SERVICE có thể trỏ đến số điện thoại của nhà hàng để thực hiện đơn hàng.

Đang gửi thông tin cập nhật về đơn đặt hàng

Bạn sử dụng loại thông báo AsyncOrderUpdateRequestMessage để gửi đơn đặt hàng cập nhật lên dịch vụ Đặt hàng đầu đến cuối. Google sẽ phản hồi bằng một AsyncOrderUpdateResponseMessage. Ví dụ: nếu muốn thông báo cho rằng đơn đặt hàng của họ hợp lệ và được chấp nhận, bạn có thể gửi AsyncOrderUpdateRequestMessage để thay đổi trạng thái của đơn đặt hàng thành CONFIRMED với nhãn Accepted by restaurant.

Sơ đồ cập nhật đơn đặt hàng

Đặt thông báo cập nhật đơn đặt hàng

Khi gửi AsyncOrderUpdateRequestMessage đến Google, bạn phải cung cấp thông tin về trạng thái của đơn đặt hàng bằng cách sử dụng trường OrderUpdate.

Các ví dụ sau đây minh hoạ một AsyncOrderUpdateRequestMessage mẫu cho mỗi trạng thái đơn đặt hàng:

ĐÃ XÁC NHẬN

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng xác nhận đơn đặt hàng có biên nhận và thời gian giao hàng dự kiến bất cứ lúc nào.

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

BỊ TỪ CHỐI

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng đơn đặt hàng bị từ chối kèm lý do từ chối.

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

ĐÃ HỦY

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng đơn đặt hàng bị huỷ kèm lý do huỷ.

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

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng rằng thức ăn hiện đang được chuẩn bị.

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

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng đồ ăn đã sẵn sàng để đến lấy.

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

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng đơn đặt hàng đang được vận chuyển kèm theo thời gian giao hàng dự kiến.

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

BỔ SUNG

Ví dụ này cho thấy một yêu cầu cập nhật đơn đặt hàng mẫu để thông báo cho người dùng đến lấy hàng hoặc giao hàng:

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

Để biết thêm ví dụ về các yêu cầu cập nhật đơn đặt hàng trong các trường hợp sử dụng, hãy đọc bài viết Triển khai thông tin cập nhật đơn đặt hàng nâng cao.

Tạo mã thông báo uỷ quyền và gửi thông báo

Việc cập nhật đơn đặt hàng yêu cầu mã thông báo uỷ quyền để việc đặt hàng hoàn chỉnh có thể xác minh rằng tin nhắn đó đến từ dịch vụ web Đặt hàng hai đầu của bạn.

Để cập nhật đơn đặt hàng cho dự án của bạn, hãy làm theo các bước sau:

  1. Tạo mã thông báo uỷ quyền bằng cách làm theo các bước sau:
    1. Sử dụng Thư viện xác thực của Google để đọc thông tin xác thực từ dịch vụ của bạn tệp tài khoản.
    2. Yêu cầu mã thông báo bằng cách sử dụng phạm vi API sau: https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. Hãy sử dụng mã thông báo này để gửi yêu cầu POST qua HTTP đã xác thực tới điểm cuối sau: https://actions.googleapis.com/v2/conversations:send
  3. Đặt tiêu đề Content-Type thành application/json theo yêu cầu của bạn.

Các ví dụ sau đây minh hoạ cách triển khai việc cập nhật đơn đặt hàng:

Node.js

Mã này sử dụng thư viện xác thực của Google cho 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

Mã này sử dụng thư viện xác thực của Google cho 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

Mã này sử dụng thư viện xác thực của Google cho 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",);
}
    

Để cập nhật đơn đặt hàng thành công và không gặp lỗi, Google sẽ trả về phản hồi HTTP 200 có tải trọng trống. Nếu có vấn đề, chẳng hạn như bản cập nhật bị không đúng định dạng, Google sẽ trả về một lỗi.