Fitur pesan di muka v1

Anda dapat menambahkan dukungan di pemenuhan pesanan agar pengguna dapat menjadwalkan pengambilan dan untuk mengirim pesanan makanan di muka. Sebelum menerapkan dukungan ini di fulfillment, buat feed inventaris layanan yang menentukan jam buka untuk pengguna untuk melakukan pemesanan di awal, seperti yang dijelaskan dalam skema feed inventaris (AdvanceServiceDeliveryHoursSpecification)

Slot pesanan di awal

Google mengusulkan slot pesanan di muka dengan kelipatan 15 menit, hingga 7 hari sebelumnya, berdasarkan waktu pemenuhan untuk restoran atau layanan (sebagaimana dijelaskan dalam AdvanceServiceDeliveryHoursSpecification).

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

  • PickupInfo.pickupTimeIso8601
  • DeliveryInfo.deliveryTimeIso8601

Menerapkan pesanan di muka saat checkout

Tabel di bawah ini mencantumkan kemungkinan cara mengimplementasikan fungsi fulfillment Anda respons pada waktu {i>checkout<i} ketika pengguna mencoba melakukan pemesanan.

Skenario Perilaku pemenuhan pesanan
Pesanan di awal dapat dipenuhi untuk slot yang diminta. Setujui P0M ("sesegera mungkin") atau FUTURE_SLOT keranjang dengan membuat ProposedOrder menggunakan 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 P0M atau FUTURE_SLOT yang diminta keranjang, dan menunjukkan alasan mengapa pesanan tidak dapat dipenuhi dalam Objek FoodErrorExtension.
    • Jika pesanan tidak dapat dipenuhi karena kapasitas, tentukan FoodOrderError dari jenis error NO_CAPACITY.
    • Jika pesanan tidak dapat dipenuhi karena restoran ditutup, tentukan FoodOrderError jenis error CLOSED.
    • Jika pesanan tidak dapat dipenuhi karena beberapa alasan lain, menentukan FoodOrderError jenis error UNAVAILABLE_SLOT.
  2. Jika memungkinkan, berikan P0M atau Nilai FUTURE_SLOT di correctedProposedOrder. Nilai ini harus berupa semua slot fulfillment yang valid untuk 7 slot berikutnya hari dimulai dari waktu saat ini. Sertakan slot P0M jika perlu.

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 Google tidak sesuai, fulfillment dapat menyarankan alternatif menggunakan CheckoutResponseMessage .

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

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

Slot alternatif harus untuk 7 hari ke depan sejak waktu pemesanan dan menyertakan semua slot di mana keranjang yang diminta pengguna terpenuhi.

Misalnya, promo makan siang hanya tersedia dari Senin hingga Jumat dari pukul 11.00 hingga 13.00. Pengguna kemudian mencoba menambahkan makan siang spesial ke keranjang mereka tetapi slot yang dipilih tidak tersedia. Dalam hal ini, fulfillment Anda harus simpan spesial makan siang di keranjang, dan kembalikan hanya slot pukul 11.00 - 13.00 selama 7 hari ke depan

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

Jika tidak ada slot yang tersedia, atau jika restoran atau layanan tidak mendukung pesanan di muka, maka Anda tidak perlu menyediakan correctedProposedOrder.

Lihat contoh di bawah untuk pesan JSON antara fulfillment Anda dan Google selama alur permintaan {i>checkout<i} dan respons untuk pesanan di muka, ketika restoran atau layanan tersedia untuk menerima praorder.

Contoh: CheckoutRequest dengan slot pengiriman

Cuplikan di bawah ini menampilkan contoh permintaan checkout dengan pesanan di muka slot pengiriman.

{
  "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 ini menunjukkan contoh respons checkout di mana fulfillment Anda menerima slot pesanan 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 di mana fulfillment Anda menawarkan slot pesanan awal alternatif. Perhatikan bahwa Objek correctedProposedOrder.Cart.fulfillmentPreference harus dihilangkan di 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 pada saat pengiriman

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 OrderState jika pesanan diterima oleh penyedia. Sertakan slot waktu yang dipilih dalam email konfirmasi Anda kepada pengguna.

Jika {i>fulfillment <i}Anda mengirimkan pesanan ke restoran nanti, kirimkan lakukan update menggunakan Tindakan Pembaruan Pesanan Asinkron.

Di objek OrderUpdate respons pesanan kirim pemenuhan Anda atau pembaruan urutan asinkron berikutnya, termasuk 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 muka.
  • Saat ada estimasi waktu pengiriman yang lebih akurat dari restoran atau layanan, tetapkan nilai ke estimasi waktu pengiriman atau pengambilan.

Contoh: SubmitOrderRequest dengan slot penayangan

Cuplikan di bawah ini menampilkan contoh permintaan pengiriman yang mengindikasikan 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 menyetujui pesanan

Cuplikan di bawah ini menunjukkan contoh respons kirim pesanan di mana pemenuhan pesanan mengonfirmasi bahwa telah menerima pesanan di muka dari 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 kirim pesanan di mana fulfillment menolak pesanan di muka pengguna karena slot yang 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 awal

Jenis AdvanceServiceDeliveryHoursSpecification dapat digunakan untuk menentukan waktu pengiriman atau pengambilan bagi pengguna untuk menjadwalkan pesanan mereka terlebih dahulu.

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

Contoh berikut menentukan jam layanan untuk menerima pesanan di muka, dengan interval servis 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 menetapkan bahwa layanan telah dibuka untuk pesanan di hari yang sama pada hari Natal tetapi ditutup untuk pesanan lanjutan yang dijadwalkan pada hari itu. 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 terjadwal untuk 27 Desember.
  • Pengguna tidak dapat melakukan pemesanan di awal pada tanggal 22 Desember untuk pengiriman terjadwal pada 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 menetapkan bahwa layanan akan ditutup untuk pesanan pada hari yang sama atau pesanan di muka yang dijadwalkan untuk hari Natal, tetapi terbuka pesanan di muka yang dijadwalkan untuk hari berikutnya. Contoh ini mendukung hal berikut skenario:

  • 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 terjadwal untuk 27 Desember.
  • Pengguna tidak dapat melakukan pemesanan di awal pada tanggal 22 Desember untuk pengiriman terjadwal pada 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 Layanan 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 Layanan berikut menerima pesanan setiap hari mulai 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 menampilkan 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 dalam waktu 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"
      }
    }
  ]
}
...