Actualización del pedido asíncrono

Después de que un cliente envía un pedido de comida, puedes enviar un mensaje de actualización del pedido a el servicio de Pedidos de extremo a extremo para notificarnos sobre el cambio.

Estos son algunos de los motivos comunes por los que envías actualizaciones de pedidos:

  • El tiempo de entrega estimado del pedido pasa a estar disponible o cambia.
  • Cambia el estado de un pedido.
  • Ya no se puede completar el pedido.
  • Cambió el precio de un elemento del menú incluido en el pedido.
  • El cliente tiene una nueva forma de administrar su pedido, como una asistencia al cliente o el número de teléfono del restaurante.
  • El recibo del pedido estará disponible.

En las siguientes secciones, se explica cómo abordar estas diferentes situaciones con las actualizaciones de pedidos.

Estados del pedido en transición

Un pedido tiene seis estados posibles. Estos estados y sus posibles transiciones se describen en el siguiente diagrama:

Transiciones de estado del pedido

Cuando un cliente envía un pedido por primera vez, este comienza con el estado CREATED, CONFIRMED o REJECTED. Puedes enviar un mensaje de actualización del pedido a actualizar el estado de un pedido, siempre que la transición de estado sea válida. CREATED se usa cuando la plataforma del socio no puede confirmar o rechazar el pedido. de inmediato. Un ejemplo de caso de uso es cuando un cliente realiza un pedido a través de una entrega agregador. El agregador de entregas recibe la entrega de Google, y el y el agregador envía la información al restaurante. Una vez que el restaurante recibió y confirmaste la disponibilidad del pedido, el estado ahora puede ser CONFIRMED; de lo contrario, REJECTED

Un pedido en el estado CONFIRMED pasa a continuación al estado IN_PREPARATION. En función de si el pedido es para retiro o entrega, luego usa el estado READY_FOR_PICKUP o IN_TRANSIT. Cuando se entrega o se recoge la comida, el pedido se establece en el estado FULFILLED.

Si permites que los clientes cancelen pedidos, puedes usar el estado CANCELLED. Se puede cancelar un pedido en el estado CREATED, CONFIRMED, IN_PREPARATION, READY_FOR_PICKUP o IN_TRANSIT. El servicio de Pedidos de extremo a extremo debería emitir reembolsos según tu política de cancelación y el estado de los pagos en el momento de la cancelación.

El servicio de pedidos de extremo a extremo no tiene que ser compatible con todos los estados disponibles y transiciones. Sin embargo, el estado final del pedido debe ser FULFILLED. REJECTED o CANCELLED.

Proporcionar un tiempo de entrega estimado

Puedes proporcionar a los usuarios un intervalo de tiempo estimado en el que se completará el pedido listo para su retiro (o entregado). Usa el campo estimatedFulfillmentTimeIso8601 de FoodOrderUpdateExtension para proporcionar un intervalo de tiempo estimado para cuando un el pedido del cliente estará listo para su retiro o entregado.

Envía estimatedFulfillmentTimeIso8601 en los siguientes horarios:

  • Cuando el tiempo estimado esté disponible, idealmente en el pedido CREATED o CONFIRMED.
  • Cuando cambia la hora estimada, como actualizar la hora estimada será más preciso cuando el pedido sea IN_TRANSIT.

Para gestionar las expectativas de los usuarios de forma eficaz, sé conservador en tus estimaciones y proporcionan una fecha y un intervalo de tiempo en lugar de una fecha y hora fijas. Deberías tenga en cuenta variaciones, como las condiciones del tráfico, siempre que sea posible. Para ejemplo, puedes enviar una estimación de 12:45 p. m. (límite inferior) a 1:15 p. m. (límite superior) bound) para un pedido cuyo tiempo de entrega estimado es a la 1:00 p.m.

Proporcionar acciones de administración de pedidos

Al enviar la actualización de un pedido, puedes brindar a los clientes recursos que ayuden que administre su pedido en forma de un OrderManagementAction. Después de un un cliente hace un pedido, es posible que deba comunicarse contigo o con el restaurante completar el pedido para hacer un seguimiento del progreso, realizar cambios o cancelar el pedido.

Un OrderManagementAction permite a los clientes enviar un correo electrónico, llamar o vincular a un URL directamente desde su dispositivo. Usa la misma información en OrderManagementAction como en la confirmación del pedido por correo electrónico que envía a usuario.

Las acciones de administración de pedidos incluyen los siguientes tipos:

  • CUSTOMER_SERVICE: Proporciona a los clientes una acción para comunicarse con ellos servicio. Este tipo de acción de administración es obligatorio para las actualizaciones de pedidos.
  • EMAIL: Brinda a los clientes una acción para enviar un correo electrónico a la dirección de correo electrónico.
  • CALL: Brinda a los clientes una acción para llamar al número de teléfono proporcionado.
  • VIEW_DETAIL: Brinda a los clientes una acción para ver los detalles de su en el orden personalizado.

Cada actualización de pedido debe contener al menos una acción de administración de pedidos. Sin embargo, las acciones de administración de pedidos proporcionadas pueden variar según el estado del pedido. Por ejemplo, cuando un pedido se encuentra en el estado CONFIRMED, el elemento CUSTOMER_SERVICE acción puede dirigir a tu número de teléfono de atención al cliente. Cuando ese estado de pedido se actualiza a IN_TRANSIT, la acción CUSTOMER_SERVICE puede apuntar a la número de teléfono del restaurante de entrega.

Enviando actualizaciones de pedidos

Usas el tipo de mensaje AsyncOrderUpdateRequestMessage para enviar un pedido. en el servicio de Pedidos de extremo a extremo. Google responde con un AsyncOrderUpdateResponseMessage Por ejemplo, si quieres informar cliente de que su pedido era válido y se aceptó, podría enviar un AsyncOrderUpdateRequestMessage para cambiar el estado del pedido a CONFIRMED con la etiqueta Accepted by restaurant.

Diagrama de actualización del pedido

Configura el mensaje de actualización del pedido

Cuando envías un AsyncOrderUpdateRequestMessage a Google, debes incluir lo siguiente: información sobre el estado del pedido con el campo OrderUpdate.

En los siguientes ejemplos, se muestra un AsyncOrderUpdateRequestMessage de muestra para cada estado de pedido:

CONFIRMED

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario que el pedido se confirme con un recibo y una entrega estimada tiempo.

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

RECHAZADA

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario que el pedido se rechazó con un motivo del rechazo.

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

CANCELADO

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario que el pedido se canceló con un motivo de cancelación.

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

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario de que se está preparando la comida en ese momento.

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

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario de que la comida está lista para retirarla.

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

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario que el pedido esté en tránsito con un tiempo de entrega estimado.

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

COMPLETADO

En este ejemplo, se muestra una solicitud de actualización del pedido de muestra que notifica al usuario de que el pedido se recoja o se entrega:

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

Para ver más ejemplos de solicitudes de actualización de pedidos en diferentes casos de uso, lee Implementa actualizaciones avanzadas de pedidos.

Genera un token de autorización y envía el mensaje

Las actualizaciones de pedidos requieren un token de autorización para que puede verificar que el mensaje provenga de tu servicio web de pedidos de extremo a extremo.

Para implementar actualizaciones de pedidos en tu proyecto, sigue estos pasos:

  1. Genera un token de autorización mediante los siguientes pasos:
    1. Usa la biblioteca de Google Auth para leer las credenciales de tu servicio archivo de cuenta.
    2. Solicita un token con el siguiente alcance de API: https://www.googleapis.com/auth/actions.fulfillment.conversation
  2. Usa este token para enviar una solicitud HTTP POST autenticada al siguiente extremo: https://actions.googleapis.com/v2/conversations:send
  3. Configura el encabezado Content-Type como application/json como parte de tu solicitud.

En los siguientes ejemplos, se muestra cómo implementar actualizaciones de pedidos:

Node.js

Este código usa la biblioteca auth de Google para 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

Este código usa la biblioteca auth de Google para 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

Este código usa la biblioteca auth de Google para 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",);
}
    

Para que los pedidos se actualicen correctamente sin errores, Google muestra una respuesta HTTP 200. con una carga útil vacía. Si hubo un problema, como que la actualización con el formato incorrecto, Google mostrará un error.