1. Introduzione
Ultimo aggiornamento: 30/10/2020
Costruire un carrello degli acquisti su Business Messages
Questo è il secondo codelab di una serie finalizzata a creare un percorso utente relativo all'acquisto online e al ritiro in negozio. In molti percorsi di e-commerce, un carrello degli acquisti è fondamentale per la conversione degli utenti in clienti paganti. Il carrello degli acquisti è anche un modo per comprendere meglio i tuoi clienti e un modo per offrire suggerimenti su altri articoli che potrebbero essere di loro interesse. In questo codelab, ci concentreremo sulla creazione dell'esperienza con il carrello degli acquisti e sul deployment dell'applicazione in Google App Engine.
Cosa caratterizza un buon carrello degli acquisti?
I carrelli degli acquisti sono fondamentali per un'esperienza di acquisto online di successo. Come si è scoperto, Business Messages non solo è in grado di facilitare le domande e risposte su un prodotto con un potenziale cliente, ma può anche facilitare l'intera esperienza di acquisto fino al completamento di un pagamento durante la conversazione.
Oltre a un buon carrello degli acquisti, una buona esperienza di acquisto consente agli utenti di sfogliare gli articoli per categoria e consente all'attività di consigliare altri prodotti che potrebbero interessare all'acquirente. Dopo aver aggiunto altri articoli al carrello, l'utente può esaminare l'intero carrello ed essere in grado di rimuovere articoli o aggiungerne altri prima del pagamento.
Cosa creerai
In questa sezione della serie codelab, hai intenzione di ampliare l'agente digitale che hai creato nella parte 1 per l'azienda fittizia, Bonjour Meal, in modo che gli utenti possano sfogliare un catalogo di articoli e aggiungere articoli a un carrello degli acquisti.
In questo codelab, la tua app
- Mostrare un catalogo di domande in Business Messages
- Suggerisci articoli che potrebbero interessare agli utenti
- Esamina i contenuti del carrello degli acquisti e crea un riepilogo del prezzo totale
Cosa imparerai a fare
- Come eseguire il deployment di un'applicazione web su App Engine su Google Cloud Platform
- Come utilizzare un meccanismo di archiviazione permanente per salvare lo stato di un carrello degli acquisti
Questo codelab è incentrato sull'estensione dell'agente digitale della parte 1 di questa serie codelab.
Che cosa ti serve
- Un progetto Google Cloud che è stato registrato e approvato per l'utilizzo con Business Messages
- Visita il nostro sito per sviluppatori per istruzioni su come
- Un file di credenziali JSON dell'account di servizio generato per il tuo progetto Google Cloud
- Un dispositivo Android 5 o versioni successive OPPURE un dispositivo iOS con l'app Google Maps
- Esperienza con la programmazione di applicazioni web
- Una connessione a Internet.
2. Preparazione
Questo codelab presuppone che tu abbia creato il tuo primo agente e completato la parte 1 del codelab. Pertanto, non esamineremo le nozioni di base sull'abilitazione delle API Business Messages e Business Communications, sulla creazione di chiavi degli account di servizio, sul deployment di un'applicazione o sulla configurazione del webhook nella Business Communications Console. Detto questo, cloniamo un'applicazione di esempio per assicurarci che la tua applicazione sia coerente con ciò che stiamo sviluppando e abiliteremo l'API per Datastore su Google Cloud Platform in modo che sia in grado di memorizzare i dati relativi al carrello degli acquisti.
Clonazione dell'applicazione da GitHub
In un terminale, clona l'esempio di bot di Django Echo nella directory di lavoro del progetto con il seguente comando:
$ git clone https://github.com/google-business-communications/bm-bonjour-meal-django-starter-code
Copia il file delle credenziali JSON creato per l'account di servizio nella cartella delle risorse dell'esempio e rinomina le credenziali in "bm-agent-service-account-credentials.json".
bm-bonjour-meal-django-starter-code/bonjourmeal-codelab/step-2/resources/bm-agent-service-account-credentials.json
Abilita l'API Google Datastore
Nella parte 1 di questo codelab, hai abilitato l'API Business Messages, l'API Businesscommunication e l'API Cloud Build.
Per questo codelab, poiché lavoreremo con Google Datastore, dobbiamo abilitare anche questa API:
- Apri l'API Google Datastore nella console Google Cloud.
- Assicurati di lavorare con il progetto Google Cloud corretto.
- Fai clic su Abilita.
Deployment dell'applicazione di esempio
In un terminale, vai alla directory del passaggio 2 dell'esempio.
Esegui questi comandi in un terminale per eseguire il deployment dell'esempio:
$ gcloud config set project PROJECT_ID*
$ gcloud app deploy
- PROJECT_ID è l'ID del progetto utilizzato per la registrazione con le API.
Prendi nota dell'URL dell'applicazione di cui è stato eseguito il deployment nell'output dell'ultimo comando:
Deployed service [default] to [https://PROJECT_ID.appspot.com]
Il codice di cui hai appena eseguito il deployment contiene un'applicazione web con un webhook per ricevere messaggi da Business Messages. Contiene tutto ciò che abbiamo fatto nella parte 1 del codelab. Se non l'hai ancora fatto, configura il webhook.
L'applicazione risponderà ad alcune semplici richieste, ad esempio un utente che chiede informazioni sull'orario di apertura del pasto Bonjour. Devi verificarlo sul tuo dispositivo mobile tramite gli URL di test che puoi recuperare dalle informazioni sull'agente all'interno di Business Communications Console. Gli URL di test avvieranno l'esperienza Business Messages sul tuo dispositivo mobile e potrai iniziare a interagire con l'agente da lì.
3. Catalogo dei prodotti
Un sistema di inventario
Nella maggior parte dei casi, puoi effettuare l'integrazione diretta con l'inventario di un brand tramite un'API interna. In altri casi, potresti eseguire lo scraping di una pagina web o creare un tuo sistema di monitoraggio dell'inventario. Il nostro obiettivo non è creare un sistema di inventario; utilizzeremo un semplice file statico contenente immagini e informazioni sui prodotti per il nostro agente. In questa sezione, estrarremo le informazioni da questo file statico, le mostreremo nella conversazione e consentiremo all'utente di sfogliare gli articoli disponibili per l'aggiunta al carrello degli acquisti.
Il file di inventario statico ha il seguente aspetto:
bonjourmeal-codelab/step-2/resources/inventory.json
{
"food": [
{
"id":0,
"name": "Ham and cheese sandwich",
"price": "6.99",
"image_url": "https://storage.googleapis.com/bonjour-rail.appspot.com/ham-and-cheese.png",
"remaining": 8
},
{
"id":1,
"name": "Chicken veggie wrap",
"price": "9.99",
"image_url": "https://storage.googleapis.com/bonjour-rail.appspot.com/chicken-veggie-wrap.png",
"remaining": 2
},
{
"id":2,
"name": "Assorted cheese plate",
"price": "7.99",
"image_url": "https://storage.googleapis.com/bonjour-rail.appspot.com/assorted-cheese-plate.png",
"remaining": 6
},
{
"id":3,
"name": "Apple walnut salad",
"price": "12.99",
"image_url": "https://storage.googleapis.com/bonjour-rail.appspot.com/apple-walnut-salad.png",
"remaining": 1
}
]
}
Facciamo in modo che l'applicazione Python legga questo file.
Leggere dal nostro inventario
L'inventario è un file statico denominato "inventory.json" che si trova nella directory ./resources. Dobbiamo aggiungere una logica Python a views.py per leggere i contenuti del file JSON e poi visualizzarli nella conversazione. Creiamo una funzione che legge i dati dal file JSON e restituisca l'elenco dei prodotti disponibili.
Questa definizione di funzione può essere inserita ovunque in views.py.
bonjourmeal-codelab/step-2/bopis/views.py
...
def get_inventory_data():
f = open(INVENTORY_FILE)
inventory = json.load(f)
return inventory
...
Questo dovrebbe darci ciò di cui abbiamo bisogno per leggere i dati dall'inventario. Ora abbiamo bisogno di un modo per far emergere queste informazioni sul prodotto nella conversazione.
Visualizzazione del catalogo dei prodotti
Per semplicità, in questo codelab abbiamo a disposizione un catalogo generale dei prodotti per mostrare tutti gli elementi dell'inventario nella conversazione Business Messages tramite un unico carosello di schede interattive.
Per visualizzare il catalogo dei prodotti, creeremo una risposta suggerita con testo "Mostra menu" e postbackData "show-product-catalog
". Quando gli utenti toccano la risposta suggerita e la tua applicazione web riceve i dati dei postback, invieremo il carosello di schede interattive. Aggiungiamo una nuova costante per questa risposta suggerita nella parte superiore di views.py.
bonjourmeal-codelab/step-2/bopis/views.py
...
CMD_SHOW_PRODUCT_CATALOG = 'show-product-catalog'
...
Da qui analizziamo il messaggio e lo indirizziamo a una nuova funzione che invia un carosello di schede interattive contenente il catalogo dei prodotti. Prima estendi la funzione route_message
per chiamare una funzione "send_product_catalog
" quando viene toccato la risposta suggerita, quindi definiremo la funzione.
Nello snippet seguente, aggiungi una condizione aggiuntiva all'istruzione if nella funzione route_message
per verificare se normalized_message
è uguale alla costante definita in precedenza, CMD_SHOW_PRODUCT_CATALOG
.
bonjourmeal-codelab/step-2/bopis/views.py
...
def route_message(message, conversation_id):
'''
Routes the message received from the user to create a response.
Args:
message (str): The message text received from the user.
conversation_id (str): The unique id for this user and agent.
'''
normalized_message = message.lower()
if normalized_message == CMD_RICH_CARD:
send_rich_card(conversation_id)
elif normalized_message == CMD_CAROUSEL_CARD:
send_carousel(conversation_id)
elif normalized_message == CMD_SUGGESTIONS:
send_message_with_suggestions(conversation_id)
elif normalized_message == CMD_BUSINESS_HOURS_INQUIRY:
send_message_with_business_hours(conversation_id)
elif normalized_message == CMD_ONLINE_SHOPPING_INQUIRY:
send_online_shopping_info_message(conversation_id)
elif normalized_message == CMD_SHOW_PRODUCT_CATALOG:
send_product_catalog(conversation_id)
else:
echo_message(message, conversation_id)
...
Assicurati di completare il flusso e definire send_product_catalog
. send_product_catalog
chiama get_menu_carousel,
, che genera il carosello di schede interattive dal file dell'inventario letto in precedenza.
Le definizioni delle funzioni possono essere inserite ovunque in views.py. Tieni presente che lo snippet seguente utilizza due nuove costanti da aggiungere all'inizio del file.
bonjourmeal-codelab/step-2/bopis/views.py
...
CMD_ADD_ITEM = 'add-item'
CMD_SHOW_CART = 'show-cart'
...
def get_menu_carousel():
"""Creates a sample carousel rich card.
Returns:
A :obj: A BusinessMessagesCarouselCard object with three cards.
"""
inventory = get_inventory_data()
card_content = []
for item in inventory['food']:
card_content.append(BusinessMessagesCardContent(
title=item['name'],
description=item['price'],
suggestions=[
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='Add item',
postbackData='{'+f'"action":"{CMD_ADD_ITEM}","item_name":"{item["id"]}"'+'}'))
],
media=BusinessMessagesMedia(
height=BusinessMessagesMedia.HeightValueValuesEnum.MEDIUM,
contentInfo=BusinessMessagesContentInfo(
fileUrl=item['image_url'],
forceRefresh=False))))
return BusinessMessagesCarouselCard(
cardContents=card_content,
cardWidth=BusinessMessagesCarouselCard.CardWidthValueValuesEnum.MEDIUM)
def send_product_catalog(conversation_id):
"""Sends the product catalog to the conversation_id.
Args:
conversation_id (str): The unique id for this user and agent.
"""
rich_card = BusinessMessagesRichCard(carouselCard=get_menu_carousel())
fallback_text = ''
# Construct a fallback text for devices that do not support carousels
for card_content in rich_card.carouselCard.cardContents:
fallback_text += (card_content.title + '\n\n' + card_content.description
+ '\n\n' + card_content.media.contentInfo.fileUrl
+ '\n---------------------------------------------\n\n')
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
richCard=rich_card,
fallback=fallback_text,
suggestions=[
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='See my cart',
postbackData=CMD_SHOW_CART)
),
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='See the menu',
postbackData=CMD_SHOW_PRODUCT_CATALOG)
),
]
)
send_message(message_obj, conversation_id)
...
Se esamini la creazione degli elementi del carosello, creiamo anche un'istanza della classe BusinessMessagesSuggestion
. Ogni suggerimento rappresenta una selezione dell'utente per un prodotto nel carosello. Quando un utente tocca la risposta suggerita, Business Messages invia al tuo webhook il postbackData, contenente il codice JSON, che descrive l'articolo e l'azione che l'utente vuole eseguire (aggiungere o rimuovere dal carrello). Nella sezione seguente, analizzeremo i messaggi di questo tipo in modo da poter aggiungere effettivamente l'articolo al carrello.
Ora che abbiamo apportato queste modifiche, esegui il deployment dell'applicazione web in Google App Engine e proviamo l'esperienza.
$ gcloud app deploy
Una volta caricata la piattaforma conversazionale sul tuo dispositivo mobile, invia il messaggio "show-product-catalog" e dovresti visualizzare un carosello di prodotti simili a questo.
Se tocchi Aggiungi elemento, in realtà non accade nulla, tranne che l'agente esegue l'eco dei dati postback dalla risposta suggerita. Nella sezione successiva, utilizzeremo il catalogo dei prodotti e lo utilizzeremo per creare il carrello degli acquisti in cui aggiungere l'articolo.
Il catalogo dei prodotti che hai appena creato può essere esteso in diversi modi. Potresti avere diverse opzioni per il menù delle bevande o opzioni vegetariane. L'utilizzo di caroselli o chip di suggerimenti è un ottimo modo per consentire agli utenti di visualizzare in dettaglio le opzioni di menu per arrivare all'insieme di prodotti che stanno cercando. Come estensione di questo codelab, prova a estendere il sistema del catalogo dei prodotti in modo che un utente possa visualizzare le bevande separatamente dagli alimenti nel menu o persino specificare le opzioni vegetariane.
4. Il carrello degli acquisti
In questa sezione del codelab, creeremo la funzionalità del carrello degli acquisti a partire dalla sezione precedente, in modo da poter sfogliare i prodotti disponibili.
Tra le molte cose, la chiave dell'esperienza del carrello degli acquisti consente agli utenti di aggiungere e rimuovere articoli dal carrello, monitorare il numero di ogni articolo nel carrello ed esaminare gli articoli nel carrello.
Tenere traccia dello stato del carrello degli acquisti significa che dobbiamo conservare i dati nell'applicazione web. Per semplificare la sperimentazione e il deployment, utilizzeremo Google Datastore in Google Cloud Platform per rendere i dati persistenti. L'ID conversazione rimane costante tra un utente e l'attività, quindi possiamo utilizzarlo per associare gli utenti agli articoli del carrello degli acquisti.
Iniziamo connettendoci a Google Datastore e ripristinando l'ID conversazione quando lo vediamo.
Connessione a Datastore
Ci metteremo in contatto con Google Datastore ogni volta che viene eseguita un'interazione con il carrello, ad esempio, quando un utente aggiunge o elimina un articolo. Per ulteriori informazioni sull'utilizzo di questa libreria client per interagire con Google Datastore, consulta la documentazione ufficiale.
Lo snippet seguente definisce una funzione per aggiornare il carrello degli acquisti. La funzione accetta il seguente input: conversation_id
e message
. message
contiene JSON che descrive l'azione che l'utente vuole eseguire e che è già integrato nel carosello che mostra il catalogo dei prodotti. La funzione crea un client Google Datastore e recupera immediatamente un'entità ShoppingCart, dove la chiave è l'ID conversazione.
Copia la seguente funzione nel file views.py. Continueremo ad ampliare questa funzionalità nella prossima sezione.
bonjourmeal-codelab/step-2/bopis/views.py
from google.oauth2 import service_account
from google.cloud import datastore
def update_shopping_cart(conversation_id, message):
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_LOCATION)
client = datastore.Client(credentials=credentials)
key = client.key('ShoppingCart', conversation_id)
entity = datastore.Entity(key=key)
result = client.get(key)
# TODO: Add logic to add and remove items from cart
entity.update(result)
client.put(entity)
Estendiamo questa funzione per aggiungere un articolo al carrello.
Aggiungere articoli al carrello
Quando l'utente tocca un'azione suggerita Aggiungi elemento dal carosello di prodotti, il postbackData contiene JSON che descrive l'azione che l'utente vuole eseguire. Il dizionario JSON ha due chiavi, "action" e "item_name", mentre il dizionario JSON viene inviato al tuo webhook. Il campo "item_name" è l'identificatore univoco associato all'elemento nel file Inventory.json.
Dopo aver analizzato il comando del carrello e l'articolo del carrello dal messaggio, possiamo scrivere dichiarazioni condizionali per aggiungere l'articolo. Alcuni casi limite da considerare sono il caso in cui Datastore non abbia mai rilevato l'ID conversazione o se il carrello degli acquisti riceve questo articolo per la prima volta. Di seguito è riportata un'estensione della funzionalità update_shopping_cart
definita sopra. Questa modifica aggiunge al carrello degli acquisti un articolo che è memorizzato in modo permanente da Google Datastore.
Lo snippet riportato di seguito è un'estensione della funzione precedentemente aggiunta al tuo view.py. Puoi aggiungere la differenza oppure copiare lo snippet e sostituire la versione esistente della funzione update_shopping_cart
.
bonjourmeal-codelab/step-2bopis/views.py
def update_shopping_cart(conversation_id, message):
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_LOCATION)
inventory = get_inventory_data()
cart_request = json.loads(message)
cart_cmd = cart_request["action"]
cart_item = cart_request["item_name"]
item_name = inventory['food'][int(cart_item)]['name']
client = datastore.Client(credentials=credentials)
key = client.key('ShoppingCart', conversation_id)
entity = datastore.Entity(key=key)
result = client.get(key)
if result is None:
if cart_cmd == CMD_ADD_ITEM:
entity.update({
item_name: 1
})
else:
if cart_cmd == CMD_ADD_ITEM:
if result.get(item_name) is None:
result[item_name] = 1
else:
result[item_name] = result[item_name] + 1
entity.update(result)
client.put(entity)
Questa funzione verrà estesa in seguito per supportare lo scenario in cui cart_cmd
contiene la stringa "del-item" definita in CMD_DEL_ITEM
.
Integrazione
Assicurati di aggiungere gli impianti idraulici nella funzione route_message
in modo che se ricevi un messaggio che ti chiede di aggiungere al carrello un articolo che viene chiamata la funzione update_shopping_cart
. Dovrai inoltre definire una costante per l'aggiunta di elementi seguendo la convenzione che usiamo in tutto il codelab.
bonjourmeal-codelab/step-2bopis/views.py
...
CMD_DEL_ITEM = 'del-item'
...
def route_message(message, conversation_id):
'''
Routes the message received from the user to create a response.
Args:
message (str): The message text received from the user.
conversation_id (str): The unique id for this user and agent.
'''
normalized_message = message.lower()
if normalized_message == CMD_RICH_CARD:
send_rich_card(conversation_id)
elif normalized_message == CMD_CAROUSEL_CARD:
send_carousel(conversation_id)
elif normalized_message == CMD_SUGGESTIONS:
send_message_with_suggestions(conversation_id)
elif normalized_message == CMD_BUSINESS_HOURS_INQUIRY:
send_message_with_business_hours(conversation_id)
elif normalized_message == CMD_ONLINE_SHOPPING_INQUIRY:
send_online_shopping_info_message(conversation_id)
elif normalized_message == CMD_SHOW_PRODUCT_CATEGORY:
send_product_catalog(conversation_id)
elif CMD_ADD_ITEM in normalized_message or CMD_DEL_ITEM in normalized_message:
update_shopping_cart(conversation_id, message)
else:
echo_message(message, conversation_id)
...
Per il momento, è possibile aggiungere articoli al carrello degli acquisti. Se esegui il deployment delle modifiche in Google App Engine, dovresti riuscire a vedere le modifiche del carrello acquisti riflesse nella dashboard di Google Datastore nella console di Google Cloud. Guarda il seguente screenshot della console Google Datastore. c'è una singola entità che ha il nome dell'ID conversazione seguito da alcune relazioni con gli elementi dell'inventario e la quantità di questi articoli presenti nel carrello.
Nella sezione successiva, creeremo un modo per elencare gli articoli nel carrello degli acquisti. Il meccanismo di verifica del carrello degli acquisti dovrebbe mostrare tutti gli articoli presenti nel carrello, la quantità di questi articoli e un'opzione per rimuovere un articolo dal carrello.
Revisione degli articoli nel carrello
L'elenco degli articoli nel carrello è l'unico modo che ci permette di conoscere lo stato del carrello e di sapere quali articoli possiamo rimuovere.
Innanzitutto, invia un messaggio amichevole come "Ecco il tuo carrello degli acquisti:", seguito da un altro messaggio contenente un carosello di schede interattive con risposte suggerite associate per "Rimuovi uno" o "Aggiungi un". Il carosello delle schede interattive dovrebbe mostrare anche la quantità di articoli salvati nel carrello.
Prima di scrivere la nostra funzione, è importante essere consapevoli: se è presente un solo tipo di articolo nel carrello, non possiamo renderlo come un carosello. I caroselli di schede interattive devono contenere almeno due schede. Se, invece, non ci sono articoli nel carrello, vogliamo mostrare un semplice messaggio che indica che il carrello è vuoto.
Alla luce di questo, definiamo una funzione denominata send_shopping_cart
. Questa funzione si connette a Google Datastore e richiede un'entità ShoppingCart in base all'ID conversazione. Successivamente, chiameremo la funzione get_inventory_data
e utilizzeremo un carosello di schede interattive per segnalare lo stato del carrello degli acquisti. Avremo bisogno anche di ottenere l'ID di un prodotto per nome e di dichiarare una funzione per esaminare Google Datastore per determinare questo valore. Durante la produzione del carosello, possiamo associare le risposte suggerite per eliminare o aggiungere articoli in base all'ID prodotto. Lo snippet riportato di seguito esegue tutte queste operazioni. Copia il codice ovunque in views.py.
bonjourmeal-codelab/step-2/bopis/views.py
...
def get_id_by_product_name(product_name):
inventory = get_inventory_data()
for item in inventory['food']:
if item['name'] == product_name:
return int(item['id'])
return False
def send_shopping_cart(conversation_id):
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_LOCATION)
# Retrieve the inventory data
inventory = get_inventory_data()
# Pull the data from Google Datastore
client = datastore.Client(credentials=credentials)
key = client.key('ShoppingCart', conversation_id)
result = client.get(key)
shopping_cart_suggestions = [
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='See total price', postbackData='show-cart-price')),
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='Empty the cart', postbackData='empty-cart')),
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='See the menu', postbackData=CMD_SHOW_PRODUCT_CATALOG)),
]
if result is None or len(result.items()) == 0:
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
text='There are no items in your shopping cart.',
suggestions=shopping_cart_suggestions)
send_message(message_obj, conversation_id)
elif len(result.items()) == 1:
for product_name, quantity in result.items():
product_id = get_id_by_product_name(product_name)
fallback_text = ('You have one type of item in the shopping cart')
rich_card = BusinessMessagesRichCard(
standaloneCard=BusinessMessagesStandaloneCard(
cardContent=BusinessMessagesCardContent(
title=product_name,
description=f'{quantity} in cart.',
suggestions=[
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='Remove one',
postbackData='{'+f'"action":"{CMD_DEL_ITEM}","item_name":"{product_id}"'+'}'))
],
media=BusinessMessagesMedia(
height=BusinessMessagesMedia.HeightValueValuesEnum.MEDIUM,
contentInfo=BusinessMessagesContentInfo(
fileUrl=inventory['food'][product_id]
['image_url'],
forceRefresh=False)))))
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
richCard=rich_card,
suggestions=shopping_cart_suggestions,
fallback=fallback_text)
send_message(message_obj, conversation_id)
else:
cart_carousel_items = []
# Iterate through the cart and generate a carousel of items
for product_name, quantity in result.items():
product_id = get_id_by_product_name(product_name)
cart_carousel_items.append(
BusinessMessagesCardContent(
title=product_name,
description=f'{quantity} in cart.',
suggestions=[
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='Remove one',
postbackData='{'+f'"action":"{CMD_DEL_ITEM}","item_name":"{product_id}"'+'}'))
],
media=BusinessMessagesMedia(
height=BusinessMessagesMedia.HeightValueValuesEnum.MEDIUM,
contentInfo=BusinessMessagesContentInfo(
fileUrl=inventory['food'][product_id]
['image_url'],
forceRefresh=False))))
rich_card = BusinessMessagesRichCard(
carouselCard=BusinessMessagesCarouselCard(
cardContents=cart_carousel_items,
cardWidth=BusinessMessagesCarouselCard.CardWidthValueValuesEnum
.MEDIUM))
fallback_text = ''
# Construct a fallback text for devices that do not support carousels
for card_content in rich_card.carouselCard.cardContents:
fallback_text += (
card_content.title + '\n\n' + card_content.description + '\n\n' +
card_content.media.contentInfo.fileUrl +
'\n---------------------------------------------\n\n')
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
richCard=rich_card,
suggestions=shopping_cart_suggestions,
fallback=fallback_text,
)
send_message(message_obj, conversation_id)
...
Assicurati di aver già definito CMD_SHOW_CART
nella parte superiore di views.py e chiama send_shopping_cart
se l'utente invia un messaggio contenente "show-cart".
bonjourmeal-codelab/step-2/bopis/views.py
...
def route_message(message, conversation_id):
'''
Routes the message received from the user to create a response.
Args:
message (str): The message text received from the user.
conversation_id (str): The unique id for this user and agent.
'''
normalized_message = message.lower()
if normalized_message == CMD_RICH_CARD:
send_rich_card(conversation_id)
elif normalized_message == CMD_CAROUSEL_CARD:
send_carousel(conversation_id)
elif normalized_message == CMD_SUGGESTIONS:
send_message_with_suggestions(conversation_id)
elif normalized_message == CMD_BUSINESS_HOURS_INQUIRY:
send_message_with_business_hours(conversation_id)
elif normalized_message == CMD_ONLINE_SHOPPING_INQUIRY:
send_online_shopping_info_message(conversation_id)
elif normalized_message == CMD_SHOW_PRODUCT_CATEGORY:
send_product_catalog(conversation_id)
elif CMD_ADD_ITEM in normalized_message or CMD_DEL_ITEM in normalized_message:
update_shopping_cart(conversation_id, message)
elif normalized_message == CMD_SHOW_CART:
send_shopping_cart(conversation_id)
else:
echo_message(message, conversation_id)
...
In base alla logica introdotta nella funzione send_shopping_cart
, quando digiti "show-cart", viene visualizzato un messaggio che indica che il carrello non contiene articoli, una scheda informativa in cui viene mostrato l'unico articolo presente nel carrello oppure un carosello di schede con più articoli. Inoltre, abbiamo tre risposte suggerite: "Vedi il prezzo totale", "Svuota il carrello" e "Vedi il menu".
Prova a implementare le modifiche al codice riportate sopra per verificare che il carrello degli acquisti stia monitorando gli articoli che aggiungi e che tu possa esaminare il carrello dalla piattaforma delle conversazioni, come mostrato negli screenshot qui sopra. Puoi eseguire il deployment delle modifiche con questo comando eseguito dalla directory p step-2 in cui vuoi aggiungere le modifiche.
$ gcloud app deploy
Creeremo la funzione "Visualizza prezzo totale" nella sezione successiva, dopo aver sviluppato la funzionalità per rimuovere un articolo dal carrello. La funzione get_cart_price
avrà un comportamento simile a quello della funzionalità "Visualizza il carrello degli acquisti", nel senso che eseguirà un controllo incrociato dei dati in Datastore con il file Inventory.json per produrre un prezzo totale per il carrello degli acquisti. Questa soluzione sarà utile per la prossima parte del codelab in cui eseguiremo l'integrazione con i pagamenti.
Rimozione di articoli dal carrello
Infine, possiamo completare il comportamento del carrello degli acquisti introducendo la funzionalità per la rimozione del carrello. Sostituisci la funzione update_shopping_cart
esistente con il seguente snippet.
bonjourmeal-codelab/step-2/ bopis/views.py
def update_shopping_cart(conversation_id, message):
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_LOCATION)
inventory = get_inventory_data()
cart_request = json.loads(message)
cart_cmd = cart_request["action"]
cart_item = cart_request["item_name"]
item_name = inventory['food'][int(cart_item)]['name']
client = datastore.Client(credentials=credentials)
key = client.key('ShoppingCart', conversation_id)
entity = datastore.Entity(key=key)
result = client.get(key)
if result is None:
if cart_cmd == CMD_ADD_ITEM:
entity.update({
item_name: 1
})
elif cart_cmd == CMD_DEL_ITEM:
# The user is trying to delete an item from an empty cart. Pass and skip
pass
else:
if cart_cmd == CMD_ADD_ITEM:
if result.get(item_name) is None:
result[item_name] = 1
else:
result[item_name] = result[item_name] + 1
elif cart_cmd == CMD_DEL_ITEM:
if result.get(item_name) is None:
# The user is trying to remove an item that's no in the shopping cart. Pass and skip
pass
elif result[item_name] - 1 > 0:
result[item_name] = result[item_name] - 1
else:
del result[item_name]
entity.update(result)
client.put(entity)
Invio di un messaggio di conferma
Quando l'utente aggiunge un articolo al carrello, devi inviare un messaggio di conferma per confermare l'azione e l'elaborazione della richiesta. In questo modo, non solo crei aspettative, ma permette anche di mantenere viva la conversazione.
Estendiamo la funzione update_shopping_cart
in modo che invii un messaggio all'ID conversazione indicante che l'articolo è stato aggiunto o rimosso e che fornisca suggerimenti per controllare il carrello degli acquisti o visualizzare di nuovo il menu.
bonjourmeal-codelab/step-2/bopis/views.py
def update_shopping_cart(conversation_id, message):
# No changes to the function, except appending the following logic
...
if cart_cmd == CMD_ADD_ITEM:
message = 'Great! You\'ve added an item to the cart.'
else:
message = 'You\'ve removed an item from the cart.'
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
text=message,
suggestions=[
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='Review shopping cart',
postbackData=CMD_SHOW_CART)
),
BusinessMessagesSuggestion(
reply=BusinessMessagesSuggestedReply(
text='See menu again',
postbackData=CMD_SHOW_PRODUCT_CATALOG)
),
])
send_message(message_obj, conversation_id)
Questo dovrebbe bastare! Un'esperienza del carrello completa che consente a un utente di aggiungere e rimuovere articoli, nonché di recensire gli articoli nel carrello.
A questo punto, se vuoi vedere la funzionalità del carrello nella conversazione Business Messages, esegui il deployment dell'applicazione per interagire con il tuo agente. A tale scopo, esegui questo comando nella directory del passaggio 2.
$ gcloud app deploy
5. Preparazione per i pagamenti
In vista dell'integrazione con un elaboratore dei pagamenti nella prossima parte della serie, abbiamo bisogno di un modo per ottenere il prezzo del carrello degli acquisti. Creiamo una funzione che recupera il prezzo per noi eseguendo un controllo incrociato dei dati del carrello degli acquisti in Google Datastore, recuperando il prezzo di ogni articolo dall'inventario e moltiplicando il prezzo per la quantità di ogni articolo nel carrello.
bonjourmeal-codelab/step-2/bopis/views.py
...
def get_cart_price(conversation_id):
# Pull the data from Google Datastore
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_LOCATION)
client = datastore.Client(credentials=credentials)
key = client.key('ShoppingCart', conversation_id)
entity = datastore.Entity(key=key)
result = client.get(key)
# Retrieve the inventory data
inventory = get_inventory_data()
# Start off with a total of 0 before adding up the total
total_price = 0
if len(result.items()) != 0:
for product_name, quantity in result.items():
total_price = total_price + float(
inventory['food'][get_id_by_product_name(product_name)]['price']) * int(quantity)
return total_price
...
Infine, possiamo utilizzare questa funzione e inviare un messaggio all'utente.
bonjourmeal-codelab/step-2/bopis/views.py
...
def send_shopping_cart_total_price(conversation_id):
cart_price = get_cart_price(conversation_id)
message_obj = BusinessMessagesMessage(
messageId=str(uuid.uuid4().int),
representative=BOT_REPRESENTATIVE,
suggestions=[],
text=f'Your cart\'s total price is ${cart_price}.')
send_message(message_obj, conversation_id)
...
Per unire il tutto, aggiorniamo la funzione route_message
e la costante per attivare la logica riportata sopra.
bonjourmeal-codelab/step-2/bopis/views.py
...
CMD_GET_CART_PRICE = 'show-cart-price'
...
def route_message(message, conversation_id):
'''
Routes the message received from the user to create a response.
Args:
message (str): The message text received from the user.
conversation_id (str): The unique id for this user and agent.
'''
normalized_message = message.lower()
if normalized_message == CMD_RICH_CARD:
send_rich_card(conversation_id)
elif normalized_message == CMD_CAROUSEL_CARD:
send_carousel(conversation_id)
elif normalized_message == CMD_SUGGESTIONS:
send_message_with_suggestions(conversation_id)
elif normalized_message == CMD_BUSINESS_HOURS_INQUIRY:
send_message_with_business_hours(conversation_id)
elif normalized_message == CMD_ONLINE_SHOPPING_INQUIRY:
send_online_shopping_info_message(conversation_id)
elif normalized_message == CMD_SHOW_PRODUCT_CATEGORY:
send_product_catalog(conversation_id)
elif CMD_ADD_ITEM in normalized_message or CMD_DEL_ITEM in normalized_message:
update_shopping_cart(conversation_id, message)
elif normalized_message == CMD_SHOW_CART:
send_shopping_cart(conversation_id)
elif normalized_message == CMD_GET_CART_PRICE:
send_shopping_cart_total_price(conversation_id)
else:
echo_message(message, conversation_id)
...
Di seguito sono riportati alcuni screenshot che illustrano gli obiettivi della logica descritta sopra:
Quando saremo pronti per l'integrazione con l'elaboratore dei pagamenti nella prossima parte del codelab, chiameremo la funzione get_cart_price
per passare i dati all'elaboratore dei pagamenti e avviare il flusso di pagamento.
Anche in questo caso, puoi provare questa funzionalità del carrello nella conversazione Business Messages eseguendo il deployment dell'applicazione e interagendo con il tuo agente.
$ gcloud app deploy
6. Congratulazioni
Congratulazioni, hai creato un'esperienza con il carrello degli acquisti in Business Messages.
Un aspetto che non abbiamo esaminato in questo codelab è la funzionalità che consente di svuotare l'intero carrello degli acquisti. Se vuoi, prova a estendere l'applicazione per soddisfare la funzionalità "Svuota il carrello". La soluzione è disponibile al passaggio 3 del codice sorgente che hai clonato.
In una delle prossime sezioni, eseguiremo l'integrazione con un elaboratore dei pagamenti esterno per consentire ai tuoi utenti di completare una transazione di pagamento con il tuo brand.
Cosa caratterizza un buon carrello degli acquisti?
Una buona esperienza con il carrello degli acquisti in una conversazione non è diversa da un'app mobile o in un negozio fisico. La possibilità di aggiungere e rimuovere articoli e calcolare il prezzo del carrello sono solo alcune delle funzionalità che abbiamo esplorato in questo codelab. Una differenza rispetto a un carrello degli acquisti reale è la possibilità di vedere il prezzo di tutti gli articoli nel carrello in un determinato momento, man mano che li aggiungi o li rimuovi. Questo tipo di funzionalità di alto valore metterà in risalto la tua esperienza di commercio conversazionale.
Passaggi successivi
Quando è tutto pronto, consulta alcuni dei seguenti argomenti per scoprire di più sulle interazioni più complesse che puoi ottenere in Business Messages:
- Come funziona Business Messages?
- Best practice
- Linee guida relative ai loghi
- Trasferimento all'operatore
Documenti di riferimento
- SuggestedReply
- Documento di riferimento per Business Messages Message
- Definizione JSON per RichCard