Fitur pesan di muka v1

Anda dapat menambahkan dukungan dalam fulfillment Anda bagi pengguna untuk menjadwalkan pesanan makanan untuk diambil dan dikirim terlebih dahulu. Sebelum menerapkan dukungan ini dalam fulfillment, buat feed inventaris layanan yang menentukan jam buka bagi pengguna untuk melakukan pemesanan di awal, seperti yang dijelaskan dalam skema feed inventaris (AdvanceServiceDeliveryHoursSpecification).

Slot pemesanan di awal

Google mengusulkan slot pesanan di awal dengan penambahan 15 menit, hingga 7 hari ke depan, berdasarkan waktu pemenuhan untuk restoran atau layanan (seperti yang ditentukan dalam AdvanceServiceDeliveryHoursSpecification).

Untuk mengambil slot pesanan yang diusulkan di awal, gunakan nilai berikut dari kolom fulfillmentPreference objek FoodCartExtension saat checkout:

  • PickupInfo.pickupTimeIso8601
  • DeliveryInfo.deliveryTimeIso8601

Menerapkan pesanan di muka saat {i>checkout<i}

Tabel di bawah ini mencantumkan kemungkinan cara menerapkan respons fulfillment Anda pada waktu checkout ketika pengguna mencoba melakukan pemesanan.

Skenario Perilaku pemenuhan pesanan
Pemesanan di awal dapat dipenuhi untuk slot yang diminta. Terima keranjang P0M ("sesegera mungkin") atau keranjang FUTURE_SLOT dengan membuat ProposedOrder dengan slot yang sama. Untuk contoh respons checkout yang menerima slot, lihat cuplikan kode ini.
Pesanan di awal tidak dapat dipenuhi untuk slot yang diminta. Fulfillment Anda harus melakukan hal berikut:
  1. Tolak keranjang P0M atau FUTURE_SLOT yang diminta, dan tunjukkan alasan mengapa pesanan tidak dapat dipenuhi di objek FoodErrorExtension.
    • Jika pesanan tidak dapat dipenuhi karena kapasitas, tentukan FoodOrderError jenis error NO_CAPACITY.
    • Jika pesanan tidak dapat dipenuhi karena restoran tutup, tentukan FoodOrderError jenis error CLOSED.
    • Jika pesanan tidak dapat dipenuhi karena alasan lain, tentukan FoodOrderError jenis error UNAVAILABLE_SLOT.
  2. Jika memungkinkan, berikan nilai P0M atau FUTURE_SLOT alternatif di correctedProposedOrder. Nilai ini harus berupa semua slot fulfillment yang valid untuk 7 hari ke depan mulai dari waktu saat ini. Sertakan slot P0M jika berlaku.

Untuk contoh respons checkout yang mengusulkan slot alternatif, lihat cuplikan kode ini.

Slot alternatif untuk pemenuhan pesanan

Saat checkout, jika slot pesanan di muka yang diusulkan oleh Google tidak cocok, fulfillment Anda dapat menyarankan alternatif menggunakan objek CheckoutResponseMessage.

Untuk menentukan slot pesanan di awal alternatif, tanggapi permintaan checkout dengan FoodErrorExtension, lalu tetapkan nilai berikut:

  1. Dalam parameter foodOrderErrors, tentukan jenis error (seperti UNAVAILABLE_SLOT, NO_CAPACITY, atau CLOSED).
  2. Di parameter correctedProposedOrder, berikan nilai P0M atau FUTURE_SLOT alternatif melalui availableFulfillmentOptions.

Slot alternatif harus selama 7 hari ke depan sejak waktu penempatan pesanan, dan menyertakan semua slot tempat keranjang yang diminta pengguna dapat dipenuhi.

Misalnya, promo makan siang hanya tersedia dari Senin hingga Jumat dari pukul 11.00 hingga 13.00. Kemudian, pengguna mencoba menambahkan promo makan siang ke keranjang, tetapi slot yang mereka pilih tidak tersedia. Dalam hal ini, fulfillment Anda harus mempertahankan promo makan siang di keranjang, dan hanya mengembalikan slot pukul 11.00 hingga 13.00 selama 7 hari ke depan

Anda harus menghapus objek correctedProposedOrder.Cart.fulfillmentPreference dalam respons.

Jika tidak ada slot yang tersedia, atau jika restoran atau layanan tidak mendukung pesanan di awal, Anda tidak perlu memberikan correctedProposedOrder.

Lihat contoh di bawah untuk pesan JSON antara fulfillment Anda dan Google selama alur permintaan checkout dan respons untuk pesanan di awal, saat restoran atau layanan tersedia untuk menerima praorder.

Contoh: CheckoutRequest dengan slot pengiriman

Cuplikan di bawah ini menunjukkan contoh permintaan checkout dengan slot pengiriman pesanan di awal.

{
  "inputs": [
    {
      "intent": "actions.foodordering.intent.CHECKOUT",
      "arguments": [
        {
          "extension": {
            "@type": "type.googleapis.com/google.actions.v2.orders.Cart",
            "merchant": {
              "id": "https://www.exampleprovider.com/merchant/id1",
              "name": "Cucina Venti"
            },
            "lineItems": [
              {
                "name": "Sizzling Prawns Dinner",
                "type": "REGULAR",
                "id": "sample_item_offer_id_1",
                "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                "quantity": 1,
                "price": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "16",
                    "nanos": 750000000
                  }
                },
              }
            ],
            "extension": {
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
              "fulfillmentPreference": {
                "fulfillmentInfo": {
                  "delivery": {
                    // Deliver at 6:30PM.
                    "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                  }
                }
              },
              "location": {
                ...
              }
            }
          }
        }
      ]
    }
  ]
}

Contoh: CheckoutResponse menerima slot

Cuplikan di bawah menunjukkan contoh respons checkout saat fulfillment Anda menerima slot pesanan di awal yang diusulkan.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "checkoutResponse": {
              "proposedOrder": {
                "id": "sample_proposed_order_id_1",
                "cart": {
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Falafel Bite"
                  },
                  "lineItems": [
                    {
                      "name": "Sizzling Prawns Dinner",
                      "type": "REGULAR",
                      "id": "sample_item_offer_id_1",
                      "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "16",
                          "nanos": 750000000
                        }
                      },
                    }
                  ],
                  "extension": {
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "delivery": {
                          // Same as the time in the request.
                          "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                        }
                      }
                    },
                    "location": {
                      ...
                     }
                   }
                },
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    // Represents $16.75
                    "currencyCode": "USD",
                    "units": "16",
                    "nanos": 750000000
                  }
                },
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
                  // Send whole proposed order back.
                  "availableFulfillmentOptions": [
                    "fulfillmentInfo": {
                      "delivery": {
                        // Same as the time in the request.
                        "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                      }
                    }
                  ]
                }
              },
              "paymentOptions": {
                ...
              }
            }
          }
        }
      ]
    }
  }
}

Contoh: CheckoutResponse dengan slot alternatif

Cuplikan di bawah ini menunjukkan contoh respons checkout tempat fulfillment Anda mengusulkan slot pesanan di awal alternatif. Perhatikan bahwa objek correctedProposedOrder.Cart.fulfillmentPreference harus dihilangkan dalam respons Anda.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "error": {
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
              "foodOrderErrors": [
                {
                  "error": "UNAVAILABLE_SLOT", // Cart level error
                  "description": "The restaurant is closed."
                }
              ],
              "correctedProposedOrder": {
                // Send whole original cart back,
                // without the fulfillmentPreference.
                "cart": {
                  ...
                },
                "otherItems": {
                  ...
                },
                "totalPrice": {
                  ...
                },
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
                  "availableFulfillmentOptions": [
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T19:00:00-07:00"
                      }
                    },
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T19:30:00-07:00"
                      }
                    },
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T20:00:00-07:00"
                      }
                    }
                  ]
                }
              },
              "paymentOptions": {
                ...
              }
            }
          }
        }
      ]
    }
  }
}

Menerapkan pesanan di muka saat mengirimkan pesanan

Saat pengiriman pesanan, jika ada masalah dengan slot pesanan di awal, SubmitOrderResponseMessage harus menyertakan alasan (seperti UNAVAILABLE_SLOT atau UNKNOWN) dalam objek RejectionInfo.

Perbarui status pesanan dari CREATED menjadi CONFIRMED di objek OrderState saat pesanan diterima oleh penyedia. Sertakan slot waktu yang dipilih dalam email konfirmasi Anda kepada pengguna.

Jika fulfillment Anda mengirimkan pesanan ke restoran nanti, kirim info terbaru ke Google menggunakan Tindakan Pembaruan Pesanan Asinkron.

Dalam objek OrderUpdate pengiriman respons pesanan fulfillment Anda atau pembaruan pesanan asinkron berikutnya, sertakan estimatedFulfillmentTimeIso8601 dengan nilai yang ditetapkan sebagai berikut:

  • Jika status pesanan adalah CREATED atau CONFIRMED, tetapkan nilai ke waktu pengiriman atau pengambilan yang dijadwalkan pengguna untuk pesanan di awal.
  • Jika ada perkiraan waktu pengiriman yang lebih akurat dari restoran atau layanan, tetapkan nilai ke perkiraan waktu pengiriman atau pengambilan.

Contoh: SubmitOrderRequest dengan slot pengiriman

Cuplikan di bawah menunjukkan contoh permintaan kirim pesanan yang menunjukkan slot pesanan awal yang dipilih pengguna.

{
  "inputs": [
    {
      "intent": "actions.intent.TRANSACTION_DECISION",
      "arguments": [
        {
          "transactionDecisionValue": {
            "order": {
              "finalOrder": {
                "cart": {
                  "notes": "Guest prefers their food to be hot when it is delivered.",
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Cucina Venti"
                  },
                  "lineItems": [
                    {
                      "name": "Sizzling Prawns Dinner",
                      "type": "REGULAR",
                      "id": "sample_item_offer_id_1",
                      "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "16",
                          "nanos": 750000000
                        }
                      }
                    }
                  ],
                  "extension": {
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "delivery": {
                          "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                        }
                      }
                    }
                    "contact": {
                      ...
                    }
                  }
                },
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "16",
                    "nanos": 750000000
                  }
                },
                "id": "sample_final_order_id",
                "extension": {
                  // Send whole proposed order back.
                  "availableFulfillmentOptions": [
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                      }
                   ]
                }
              },
              "googleOrderId": "sample_google_order_id",
              "orderDate": "2017-07-17T12:00:00Z",
              "paymentInfo": {
                ...
              }
            }
          }
        }
      ]
    }
  ]
}

Contoh: SubmitOrderResponse menerima pesanan

Cuplikan di bawah ini menunjukkan contoh respons pengiriman pesanan saat fulfillment Anda mengonfirmasi bahwa pesanan di awal telah diterima oleh pengguna.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "sample_action_order_id",
              "orderState": {
                "state": "CREATED",
                "label": "Order placed"
              },
              "receipt": {
                "userVisibleOrderId": "userVisibleId1234"
              },
              "updateTime": "2017-07-17T12:00:00Z",
              "orderManagementActions": [
                ...
              ],
              "infoExtension": {
                 "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
                 // Same as the user selected time.
                 "estimatedFulfillmentTimeIso8601": "2017-12-14T18:30:00-07:00"
              }
            }
          }
        }
      ]
    }
  }
}

Contoh: SubmitOrderResponse menolak pesanan karena slot tidak tersedia

Cuplikan di bawah ini menunjukkan contoh respons pesanan yang dikirim dengan fulfillment Anda menolak pesanan di awal pengguna karena slot tidak tersedia.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "sample_action_order_id",
              "orderState": {
                "state": "REJECTED",
                "label": "Unavailable slot"
              },
              "rejectionInfo": {
                // Note that this UNAVAILABLE_SLOT is different from the enum
                // with the same name proposed for FoodOrderError.
                "state": "UNAVAILABLE_SLOT",
                "label": "Unavailable slot"
              },
              "updateTime": "2017-07-17T12:00:00Z",
              "orderManagementActions": [
                ...
              ]
            }
          }
        }
      ]
    }
  }
}

Contoh pesanan di muka

Jenis AdvanceServiceDeliveryHoursSpecification dapat digunakan untuk menentukan jam pengiriman atau pengambilan bagi pengguna untuk menjadwalkan pesanan mereka di awal.

Catatan: Ada dua periode waktu terpisah yang harus Anda tentukan untuk fulfillment layanan: periode pengurutan yang menentukan kapan pengguna dapat melakukan pesanan, dan jendela fulfillment yang menentukan kapan pesanan dipenuhi. Objek OpeningHoursSpecification menentukan kapan pengguna dapat melakukan pemesanan. Waktu fulfillment turunannya (ServiceDeliveryHoursSpecification atau AdvanceServiceDeliveryHoursSpecification) menentukan kapan pesanan dapat dipenuhi.

Contoh berikut menentukan jam layanan untuk menerima pesanan di awal, dengan interval layanan 15 menit.

{
  "hoursAvailable": [
    {
      "@type": "OpeningHoursSpecification",
      "opens": "T00:00:00", // Ordering available 24 hours
      "closes": "T23:59:59",
      "deliveryHours": [
        {
          "@type": "ServiceDeliveryHoursSpecification",
          "opens": "T09:00:00", // ASAP orders b/w 9am and 8:59:59pm
          "closes": "T21:00:00",
          "deliveryLeadTime": {
            "value": "60",
            "unitCode": "MIN"
          }
        },
        {
          "@type": "AdvanceServiceDeliveryHoursSpecification",
          "opens": "T10:00:00",  // Delivery between 10AM and 7:59:59PM
          "closes": "T20:00:00",
          "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart (ISO8601)
          "advanceBookingRequirement": {
            "minValue": 60,   // The slot should be at least 60 mins away
            "maxValue": 8640, // but not more than 6 days away
            "unitCode": "MIN"
          }
        }
      ]
    }
  ]
}

Contoh berikut menunjukkan cara menentukan bahwa layanan buka untuk pesanan di hari yang sama pada hari Natal, tetapi ditutup untuk pesanan lanjutan yang dijadwalkan pada hari tersebut. Contoh ini mendukung skenario berikut:

  • Pengguna dapat melakukan pemesanan pada tanggal 25 Desember untuk pengiriman di hari yang sama.
  • Pengguna dapat melakukan pemesanan di awal pada tanggal 25 Desember untuk pengiriman yang dijadwalkan pada tanggal 27 Desember.
  • Pengguna tidak dapat melakukan pemesanan di awal pada tanggal 22 Desember untuk pengiriman yang dijadwalkan pada tanggal 25 Desember.
{
  "specialOpeningHoursSpecification": {
    "@type": "AdvanceServiceDeliveryHoursSpecification",
    "validFrom": "2018-12-25T00:00:00-07:00",
    "validThrough": "2018-12-26T00:00:00-07:00",
    "opens": "T00:00:00", // No advance ordering
    "closes": "T00:00:00"
  }
}

Contoh berikut menunjukkan cara menentukan bahwa layanan ditutup untuk pesanan di hari yang sama atau pesanan di muka yang dijadwalkan untuk hari Natal, tetapi terbuka untuk pesanan lanjutan yang dijadwalkan di hari berikutnya. Contoh ini mendukung skenario berikut:

  • Pengguna tidak dapat melakukan pemesanan pada tanggal 25 Desember untuk pengiriman di hari yang sama.
  • Pengguna dapat melakukan pemesanan di awal pada tanggal 25 Desember untuk pengiriman yang dijadwalkan pada tanggal 27 Desember.
  • Pengguna tidak dapat melakukan pemesanan di awal pada tanggal 22 Desember untuk pengiriman yang dijadwalkan pada tanggal 25 Desember.
{
  "specialOpeningHoursSpecification": [
    {
      "@type": "ServiceDeliveryHoursSpecification",
      "validFrom": "2018-12-25T00:00:00-07:00",
      "validThrough": "2018-12-26T00:00:00-07:00",
      "opens": "T00:00:00", // No ASAP ordering on Christmas
      "closes": "T00:00:00"
    },
    {
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "validFrom": "2018-12-25T00:00:00-07:00",
      "validThrough": "2018-12-26T00:00:00-07:00",
      "opens": "T00:00:00", // Orders cannot be scheduled for Christmas
      "closes": "T00:00:00"
    }
  ]
}

Contoh Service berikut menerima pesanan 24/7 dan dikirim dari 10.00-14.59.59 pada hari kerja:

...
{
  "@type": "OpeningHoursSpecification",
  "opens": "T00:00:00",
  "closes": "T23:59:59",
  "deliveryHours": {
    "@type": "AdvanceServiceDeliveryHoursSpecification",
    "opens": "T10:00:00", // Delivery starts at 10:00AM
    "closes": "T15:00:00", // Delivery ends at 3:00PM. Delivery from 10AM-2:59:59PM.
    "dayOfWeek": [
      "Monday",
      "Tuesday",
      "Wednesday",
      "Thursday",
      "Friday"
    ],
    "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart
    "advanceBookingRequirement": {
      "minValue": 60,   // The slot should be at least 60 mins away
      "maxValue": 8640, // but not more than 6 days away
      "unitCode": "MIN"
    }
  }
}
...

Contoh Service berikut menerima pesanan setiap hari dari pukul 08.00-16.59.59, dan pelanggan dapat memilih pengiriman dalam waktu satu jam, atau memilih salah satu slot:

...
{
  "@type": "OpeningHoursSpecification",
  "opens": "T08:00:00",  // Ordering opens at 8:00AM
  "closes": "T17:00:00",  // Ordering closes at 5:00PM, last order at 4:59:59PM
  "deliveryHours": [
    {
      "@type": "ServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "deliveryLeadTime": {
        "@type": "QuantitativeValue",
        "value": "60", // If no exact deliveryLeadTime, put a maximum time
        "unitCode": "MIN"
      }
    },
    {
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart
      "advanceBookingRequirement": {
        "minValue": 90,   // The slot should be at least 90 mins away
        "maxValue": 8640, // but not more than 6 days away
        "unitCode": "MIN"
      }
    }
  ]
}
...

Contoh berikut menunjukkan kasus saat toko buka pukul 08.00-16.59.59 pada hari kerja, tetapi pukul 08.00-18.59 pada akhir pekan. Pesanan tidak diterima 24/7.

...
{
  // On weekdays, ordering open from 8AM-4:59:59PM.
  "@type": "OpeningHoursSpecification",
  "opens": "T08:00:00",
  "closes": "T17:00:00",
  "dayOfWeek": [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday"
  ],
  "deliveryHours": [
    {
      // Fulfillment between 8AM-4:59:59PM on weekdays.
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "dayOfWeek": [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    },
    {
      // Fulfillment between 8AM-6:59:59PM on weekends (even for orders placed on a
      // weekday).
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T19:00:00",
      "dayOfWeek": [
        "Saturday",
        "Sunday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    }
  ]
},
{
  // On weekends, one can place orders upto 6:59:59PM.
  "@type": "OpeningHoursSpecification",
  "opens": "T08:00:00",
  "closes": "T19:00:00",
  "dayOfWeek": [
    "Saturday",
    "Sunday"
  ],
  "deliveryHours": [
    {
      // But fulfillment on weekdays is only till 4:59:59PM.
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "dayOfWeek": [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    },
    {
      // Fulfillment on weekends is till 6:59:59PM.
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T19:00:00",
      "dayOfWeek": [
        "Saturday",
        "Sunday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    }
  ]
}
...