1. บทนำ
อัปเดตล่าสุด: 30-10-2020
การสร้างรถเข็นช็อปปิ้งใน Business Messages
นี่เป็นโค้ดแล็บที่ 2 ในชุดที่มุ่งสร้างเส้นทางของผู้ใช้สำหรับ "ซื้อออนไลน์และรับสินค้าที่ร้าน" ในเส้นทางอีคอมเมิร์ซหลายเส้นทาง รถเข็นช็อปปิ้งเป็นกุญแจสําคัญในการเปลี่ยนผู้ใช้ให้กลายเป็นลูกค้าที่ชําระเงิน นอกจากนี้ รถเข็นช็อปปิ้งยังเป็นวิธีทำความเข้าใจลูกค้าได้ดียิ่งขึ้นและวิธีเสนอคำแนะนำเกี่ยวกับสินค้าอื่นๆ ที่ลูกค้าอาจสนใจ ในโค้ดแล็บนี้ เราจะมุ่งเน้นที่การสร้างประสบการณ์การใช้รถเข็นช็อปปิ้งและทำให้แอปพลิเคชันใช้งานได้ใน Google App Engine
รถเข็นช็อปปิ้งที่ดีควรเป็นอย่างไร
รถเข็นช็อปปิ้งเป็นกุญแจสำคัญสู่ประสบการณ์การช็อปปิ้งออนไลน์ที่ประสบความสำเร็จ ผลลัพธ์ที่ได้คือ Business Messages ไม่เพียงช่วยอำนวยความสะดวกในการถามและตอบเกี่ยวกับผลิตภัณฑ์กับลูกค้าเป้าหมายเท่านั้น แต่ยังช่วยอำนวยความสะดวกในการช็อปปิ้งทั้งกระบวนการจนเสร็จสมบูรณ์ภายในการสนทนา
นอกจากรถเข็นช็อปปิ้งที่ดีแล้ว ประสบการณ์การช็อปปิ้งที่ดียังช่วยให้ผู้ใช้เลือกดูสินค้าตามหมวดหมู่และช่วยให้ธุรกิจแนะนำผลิตภัณฑ์อื่นๆ ที่ผู้ซื้ออาจสนใจได้ หลังจากเพิ่มสินค้าอื่นๆ ลงในรถเข็นช็อปปิ้งแล้ว ผู้ใช้จะตรวจสอบรถเข็นทั้งหมด รวมถึงนำสินค้าออกหรือเพิ่มสินค้าอื่นๆ ก่อนชำระเงินได้
สิ่งที่คุณจะสร้าง
ในส่วนนี้ของชุดโค้ดแล็บ คุณจะต้องขยายความสามารถของตัวแทนดิจิทัลที่คุณสร้างในส่วนที่ 1 สำหรับบริษัทสมมติชื่อ Bonjour Meal เพื่อให้ผู้ใช้เรียกดูแคตตาล็อกสินค้าและเพิ่มสินค้าลงในรถเข็นช็อปปิ้งได้
ใน Codelab นี้ แอปของคุณจะทำสิ่งต่อไปนี้
- แสดงแคตตาล็อกคําถามภายใน Business Messages
- แนะนำไอเทมที่ผู้ใช้อาจสนใจ
- ตรวจสอบเนื้อหาในรถเข็นช็อปปิ้งและสร้างสรุปราคารวม
สิ่งที่คุณจะได้เรียนรู้
- วิธีทำให้เว็บแอปพลิเคชันใช้งานได้บน App Engine ใน Google Cloud Platform
- วิธีใช้กลไกพื้นที่เก็บข้อมูลถาวรเพื่อบันทึกสถานะของรถเข็นช็อปปิ้ง
Codelab นี้มุ่งเน้นที่การขยายตัวแทนดิจิทัลจากส่วนที่ 1 ของชุด Codelab นี้
สิ่งที่ต้องมี
- โปรเจ็กต์ GCP ที่ลงทะเบียนและได้รับอนุมัติให้ใช้กับ Business Messages
- ดูวิธีการได้ที่เว็บไซต์ของนักพัฒนาซอฟต์แวร์
- ไฟล์ข้อมูลเข้าสู่ระบบ JSON ของบัญชีบริการที่สร้างขึ้นสำหรับโปรเจ็กต์ GCP
- อุปกรณ์ Android 5 ขึ้นไปหรืออุปกรณ์ iOS ที่มีแอป Google Maps
- มีประสบการณ์ด้านการเขียนโปรแกรมเว็บแอปพลิเคชัน
- การเชื่อมต่ออินเทอร์เน็ต
2. การเริ่มตั้งค่า
Codelab นี้จะถือว่าคุณได้สร้างตัวแทนคนแรกและทําส่วนที่ 1 ของ Codelab เสร็จแล้ว ดังนั้น เราจะไม่อธิบายข้อมูลเบื้องต้นเกี่ยวกับการเปิดใช้ Business Messages และ Business Communications API, การสร้างคีย์บัญชีบริการ, การติดตั้งใช้งานแอปพลิเคชัน หรือการตั้งค่า Webhook ใน Business Communications Console อย่างไรก็ตาม เราจะโคลนแอปพลิเคชันตัวอย่างเพื่อให้แน่ใจว่าแอปพลิเคชันของคุณสอดคล้องกับสิ่งที่เรากำลังสร้าง และเราจะเปิดใช้ API สำหรับ Datastore ใน Google Cloud Platform เพื่อให้เก็บข้อมูลที่เกี่ยวข้องกับรถเข็นช็อปปิ้งได้
การโคลนแอปพลิเคชันจาก GitHub
ในเทอร์มินัล ให้โคลน Django Echo Bot Sample ไปยังไดเรกทอรีที่ทำงานของโปรเจ็กต์ด้วยคำสั่งต่อไปนี้
$ git clone https://github.com/google-business-communications/bm-bonjour-meal-django-starter-code
คัดลอกไฟล์ข้อมูลเข้าสู่ระบบ JSON ที่สร้างขึ้นสําหรับบัญชีบริการไปยังโฟลเดอร์ทรัพยากรของตัวอย่าง แล้วเปลี่ยนชื่อข้อมูลเข้าสู่ระบบเป็น "bm-agent-service-account-credentials.json"
bm-bonjour-meal-django-starter-code/bonjourmeal-codelab/step-2/resources/bm-agent-service-account-credentials.json
เปิดใช้ Google Datastore API
ในส่วนที่ 1 ของโค้ดแล็บนี้ คุณได้เปิดใช้ Business Messages API, Business Communications API และ Cloud Build API
สําหรับโค้ดแล็บนี้ เนื่องจากเราจะทํางานกับ Google Datastore เราจึงต้องเปิดใช้ API นี้ด้วย
- เปิด Google Datastore API ใน Google Cloud Console
- ตรวจสอบว่าคุณกำลังใช้โปรเจ็กต์ GCP ที่ถูกต้อง
- คลิกเปิดใช้
ทำให้แอปพลิเคชันตัวอย่างใช้งานได้
ในเทอร์มินัล ให้ไปที่ไดเรกทอรี step-2 ของตัวอย่าง
เรียกใช้คําสั่งต่อไปนี้ในเทอร์มินัลเพื่อทําให้การนําตัวอย่างไปใช้งาน
$ gcloud config set project PROJECT_ID*
$ gcloud app deploy
- PROJECT_ID คือรหัสโปรเจ็กต์ของโปรเจ็กต์ที่คุณใช้ลงทะเบียนกับ API
จด URL ของแอปพลิเคชันที่ติดตั้งใช้งานไว้ในเอาต์พุตของคําสั่งสุดท้าย
Deployed service [default] to [https://PROJECT_ID.appspot.com]
โค้ดที่คุณเพิ่งทำให้ใช้งานได้มีเว็บแอปพลิเคชันที่มีเว็บฮุคเพื่อรับข้อความจาก Business Messages ไฟล์นี้มีทุกอย่างที่เราทําจากส่วนที่ 1 ของโค้ดแล็บ โปรดกําหนดค่า Webhook หากยังไม่ได้ทํา
แอปพลิเคชันจะตอบคำถามง่ายๆ เช่น ผู้ใช้ถามเกี่ยวกับเวลาทําการของ Bonjour Meal คุณควรทดสอบในอุปกรณ์เคลื่อนที่ผ่าน URL ทดสอบที่ดึงมาจากข้อมูลตัวแทนภายในคอนโซลการสื่อสารทางธุรกิจ URL ทดสอบจะเปิดประสบการณ์การใช้งาน Business Messages บนอุปกรณ์เคลื่อนที่ และคุณสามารถเริ่มโต้ตอบกับตัวแทนได้
3. แคตตาล็อกผลิตภัณฑ์
ระบบสินค้าคงคลัง
ในกรณีส่วนใหญ่ คุณสามารถผสานรวมกับพื้นที่โฆษณาของแบรนด์ได้โดยตรงผ่าน API ภายใน ในกรณีอื่นๆ คุณอาจทำการสกัดข้อมูลหน้าเว็บหรือสร้างระบบติดตามพื้นที่โฆษณาของคุณเอง เราไม่ได้มุ่งเน้นที่การสร้างระบบสินค้าคงคลัง แต่จะใช้ไฟล์คงที่แบบง่ายที่มีรูปภาพและข้อมูลผลิตภัณฑ์สำหรับตัวแทนของเรา ในส่วนนี้ เราจะดึงข้อมูลจากไฟล์แบบคงที่นี้ แสดงข้อมูลนั้นในการสนทนา และอนุญาตให้ผู้ใช้เรียกดูรายการที่พร้อมเพิ่มลงในรถเข็นช็อปปิ้ง
ไฟล์สินค้าคงคลังแบบคงที่มีลักษณะดังนี้
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
}
]
}
มาเริ่มใช้แอปพลิเคชัน Python เพื่ออ่านไฟล์นี้กัน
การอ่านจากพื้นที่โฆษณาของเรา
พื้นที่โฆษณาคือไฟล์แบบคงที่ชื่อ "inventory.json" ซึ่งอยู่ในไดเรกทอรี ./resources เราต้องเพิ่มตรรกะ Python บางอย่างลงใน views.py เพื่ออ่านเนื้อหาของไฟล์ JSON แล้วแสดงในการสนทนา มาสร้างฟังก์ชันที่อ่านข้อมูลจากไฟล์ JSON และแสดงรายการผลิตภัณฑ์ที่พร้อมจำหน่ายกัน
คุณสามารถวางคําจํากัดความฟังก์ชันนี้ไว้ที่ใดก็ได้ใน views.py
bonjourmeal-codelab/step-2/bopis/views.py
...
def get_inventory_data():
f = open(INVENTORY_FILE)
inventory = json.load(f)
return inventory
...
ซึ่งน่าจะให้ข้อมูลที่เราจําเป็นต่อการอ่านข้อมูลจากคลังสินค้า ตอนนี้เราต้องการวิธีแสดงข้อมูลผลิตภัณฑ์นี้ในการสนทนา
แสดงแคตตาล็อกผลิตภัณฑ์
เพื่อความสะดวกในโค้ดแล็บนี้ เรามีแคตตาล็อกผลิตภัณฑ์ทั่วไปเพื่อแสดงสินค้าคงคลังทั้งหมดในการสนทนาผ่าน Business Messages ผ่านภาพสไลด์ของการ์ดริชมีเดียใบเดียว
หากต้องการดูแคตตาล็อกผลิตภัณฑ์ เราจะสร้างการตอบกลับที่แนะนำซึ่งมีข้อความ "แสดงเมนู" และ postbackData "show-product-catalog
" เมื่อผู้ใช้แตะการตอบกลับที่แนะนำและเว็บแอปพลิเคชันของคุณได้รับข้อมูลการรายงานผล Conversion เราจะส่งภาพสไลด์ของการ์ดริชมีเดีย มาเพิ่มค่าคงที่ใหม่สําหรับคําตอบที่แนะนํานี้ที่ด้านบนของ views.py
bonjourmeal-codelab/step-2/bopis/views.py
...
CMD_SHOW_PRODUCT_CATALOG = 'show-product-catalog'
...
จากตรงนี้ เราจะแยกวิเคราะห์ข้อความและส่งไปยังฟังก์ชันใหม่ที่ส่งภาพสไลด์ของการ์ดริชมีเดียที่มีแคตตาล็อกผลิตภัณฑ์ ก่อนอื่นให้ขยายฟังก์ชัน route_message
เพื่อเรียกใช้ฟังก์ชัน "send_product_catalog
" เมื่อมีการแตะการตอบที่แนะนำ จากนั้นเราจะกำหนดฟังก์ชัน
ในข้อมูลโค้ดต่อไปนี้ ให้เพิ่มเงื่อนไขเพิ่มเติมลงในคำสั่ง if ในฟังก์ชัน route_message
เพื่อตรวจสอบว่า normalized_message
เท่ากับค่าคงที่ 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)
...
และมาตรวจสอบว่าทำตามขั้นตอนให้เสร็จสมบูรณ์และกำหนด send_product_catalog
send_product_catalog
เรียก get_menu_carousel,
ซึ่งสร้างภาพสไลด์ของการ์ดริชมีเดียจากไฟล์พื้นที่โฆษณาที่เราอ่านก่อนหน้านี้
คุณสามารถวางคําจํากัดความของฟังก์ชันไว้ที่ใดก็ได้ใน views.py โปรดทราบว่าข้อมูลโค้ดต่อไปนี้ใช้ค่าคงที่ใหม่ 2 รายการที่ควรเพิ่มไว้ที่ด้านบนของไฟล์
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)
...
หากคุณตรวจสอบการสร้างรายการภาพสไลด์ เราจะสร้างอินสแตนซ์ของคลาส BusinessMessagesSuggestion
ด้วย คำแนะนำแต่ละรายการแสดงถึงการเลือกผลิตภัณฑ์ของผู้ใช้ในภาพสไลด์ เมื่อผู้ใช้แตะการตอบกลับที่แนะนำ Business Messages จะส่ง postbackData ที่มี JSON ที่อธิบายสินค้าและการดําเนินการที่ผู้ใช้ต้องการทํา (เพิ่มหรือนําออกจากรถเข็น) ไปยัง Webhook ในส่วนถัดไป เราจะแยกวิเคราะห์ข้อความที่มีลักษณะเช่นนี้เพื่อให้เพิ่มสินค้าลงในรถเข็นได้
เมื่อทําการเปลี่ยนแปลงเหล่านี้แล้ว เรามาติดตั้งใช้งานเว็บแอปพลิเคชันใน Google App Engine และลองใช้ประสบการณ์การใช้งานกัน
$ gcloud app deploy
เมื่อโหลดแพลตฟอร์มการสนทนาในอุปกรณ์เคลื่อนที่แล้ว ให้ส่งข้อความ "show-product-catalog" แล้วคุณจะเห็นภาพสไลด์ของผลิตภัณฑ์ที่มีลักษณะเช่นนี้
หากแตะเพิ่มรายการ ไม่มีอะไรจะเกิดขึ้นจริง ยกเว้นตัวแทนจะส่งต่อข้อมูลการรายงานผล Conversion จากการตอบกลับที่แนะนำ ในส่วนถัดไป เราจะใช้ประโยชน์จากแคตตาล็อกผลิตภัณฑ์และนำไปสร้างรถเข็นช็อปปิ้งที่จะเพิ่มสินค้า
แคตตาล็อกผลิตภัณฑ์ที่คุณเพิ่งสร้างสามารถขยายได้หลายวิธี คุณอาจมีตัวเลือกเมนูเครื่องดื่มหรือตัวเลือกอาหารมังสวิรัติที่แตกต่างออกไป การใช้ภาพสไลด์หรือชิปคำแนะนำเป็นวิธีที่ยอดเยี่ยมในการช่วยให้ผู้ใช้เจาะลึกตัวเลือกเมนูเพื่อไปยังชุดผลิตภัณฑ์ที่กําลังมองหา เพื่อเป็นการขยายการทำงานจากโค้ดแล็บนี้ ให้ลองขยายระบบแคตตาล็อกผลิตภัณฑ์เพื่อให้ผู้ใช้ดูเครื่องดื่มแยกจากอาหารในเมนู หรือแม้แต่ระบุตัวเลือกอาหารมังสวิรัติได้
4. รถเข็นช็อปปิ้ง
ในส่วนนี้ของโค้ดแล็บ เราจะสร้างฟังก์ชันการทำงานของรถเข็นช็อปปิ้งต่อจากส่วนก่อนหน้า ซึ่งจะช่วยให้เราเรียกดูผลิตภัณฑ์ที่มีได้
ประสบการณ์การใช้งานรถเข็นช็อปปิ้งที่สำคัญอย่างหนึ่งคือช่วยให้ผู้ใช้เพิ่มสินค้าลงในรถเข็น นำสินค้าออกจากรถเข็น ติดตามจำนวนสินค้าแต่ละรายการในรถเข็น และตรวจสอบสินค้าในรถเข็นได้
การติดตามสถานะรถเข็นช็อปปิ้งหมายความว่าเราต้องเก็บข้อมูลไว้ในเว็บแอปพลิเคชัน เราจะใช้ Google Datastore ใน Google Cloud Platform เพื่อเก็บข้อมูลไว้อย่างถาวรเพื่อให้การทดสอบและการติดตั้งใช้งานง่ายขึ้น รหัสการสนทนาระหว่างผู้ใช้กับธุรกิจจะยังคงเดิม เราจึงใช้รหัสนี้เพื่อเชื่อมโยงผู้ใช้กับรายการในรถเข็นช็อปปิ้งได้
มาเริ่มกันด้วยการเชื่อมต่อกับ Google Datastore และเก็บรหัสการสนทนาไว้เมื่อเห็น
การเชื่อมต่อกับ Datastore
เราจะเชื่อมต่อกับ Google Datastore ทุกครั้งที่มีการโต้ตอบกับรถเข็นช็อปปิ้ง เช่น เมื่อผู้ใช้เพิ่มหรือลบสินค้า ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ไลบรารีไคลเอ็นต์นี้เพื่อโต้ตอบกับ Google Datastore ได้ที่เอกสารประกอบอย่างเป็นทางการ
ข้อมูลโค้ดต่อไปนี้จะกําหนดฟังก์ชันเพื่ออัปเดตรถเข็นช็อปปิ้ง ฟังก์ชันนี้ใช้อินพุต conversation_id
และ message
message
มี JSON ที่อธิบายการดำเนินการที่ผู้ใช้ต้องการ ซึ่งสร้างไว้ในภาพสไลด์ที่แสดงแคตตาล็อกผลิตภัณฑ์อยู่แล้ว ฟังก์ชันนี้จะสร้างไคลเอ็นต์ Google Datastore และดึงข้อมูลเอนทิตี ShoppingCart ทันที โดยที่รหัสคือรหัสการสนทนา
คัดลอกฟังก์ชันต่อไปนี้ลงในไฟล์ views.py เราจะขยายความในส่วนถัดไป
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)
มาขยายฟังก์ชันนี้เพื่อเพิ่มสินค้าลงในรถเข็นกัน
การเพิ่มสินค้าลงในรถเข็น
เมื่อผู้ใช้แตะการดําเนินการที่แนะนําเพิ่มสินค้าจากภาพสไลด์ผลิตภัณฑ์ ระบบจะใส่ JSON ที่อธิบายการดําเนินการที่ผู้ใช้ต้องการดำเนินการไว้ใน postbackData พจนานุกรม JSON มี 2 คีย์ ได้แก่ "action" และ "item_name" และระบบจะส่งพจนานุกรม JSON นี้ไปยัง Webhook ช่อง "item_name" คือตัวระบุที่ไม่ซ้ำกันซึ่งเชื่อมโยงกับสินค้าใน inventory.json
เมื่อเรามีคำสั่งรถเข็นและรายการรถเข็นที่แยกวิเคราะห์จากข้อความแล้ว เราจะเขียนคำสั่งเงื่อนไขเพื่อเพิ่มรายการได้ กรณีขอบเขตที่ควรพิจารณา ได้แก่ ในกรณีที่ Datastore ไม่เคยเห็นรหัสการสนทนา หรือรถเข็นช็อปปิ้งได้รับรายการนี้เป็นครั้งแรก ต่อไปนี้เป็นฟังก์ชันการทำงานเพิ่มเติมของ update_shopping_cart
ที่ระบุไว้ข้างต้น การเปลี่ยนแปลงนี้จะเพิ่มสินค้าลงในรถเข็นช็อปปิ้งซึ่ง Google Datastore เก็บไว้
ข้อมูลโค้ดต่อไปนี้เป็นส่วนขยายของฟังก์ชันก่อนหน้าที่เพิ่มลงใน views.py คุณเพิ่มความแตกต่างหรือคัดลอกข้อมูลโค้ดมาแทนที่ฟังก์ชัน 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)
เราจะขยายฟังก์ชันนี้ในภายหลังเพื่อรองรับกรณีที่ cart_cmd
มีสตริง "del-item" ที่กําหนดไว้ใน CMD_DEL_ITEM
การเชื่อมโยงข้อมูลเข้าด้วยกัน
ตรวจสอบว่าคุณได้เพิ่มการต่อท่อในฟังก์ชัน route_message
เพื่อให้ระบบเรียกใช้ฟังก์ชัน update_shopping_cart
เมื่อคุณได้รับข้อความให้เพิ่มสินค้าลงในรถเข็น นอกจากนี้ คุณยังต้องกำหนดค่าคงที่สำหรับการเพิ่มรายการโดยใช้รูปแบบที่เราใช้ในโค้ดแล็บ
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)
...
ขณะนี้เราเพิ่มสินค้าลงในรถเข็นช็อปปิ้งได้ หากทําให้การเปลี่ยนแปลงมีผลใน Google App Engine คุณควรจะเห็นการเปลี่ยนแปลงรถเข็นช็อปปิ้งแสดงในหน้าแดชบอร์ด Google Datastore ในคอนโซล GCP ดูภาพหน้าจอด้านล่างของคอนโซล Google Datastore จะมีเอนทิตีเดียวที่ตั้งชื่อตามรหัสการสนทนา ตามด้วยความสัมพันธ์บางอย่างกับสินค้าคงคลังและจำนวนสินค้าเหล่านั้นที่อยู่ในรถเข็นช็อปปิ้ง
ในส่วนถัดไป เราจะสร้างวิธีแสดงรายการในรถเข็นช็อปปิ้ง กลไกการตรวจสอบรถเข็นช็อปปิ้งควรแสดงรายการทั้งหมดในรถเข็น จำนวนของรายการเหล่านั้น และตัวเลือกในการนำสินค้าออกจากรถเข็น
การตรวจสอบสินค้าในรถเข็น
การระบุรายการในรถเข็นช็อปปิ้งเป็นวิธีเดียวที่เราเข้าใจสถานะของรถเข็นช็อปปิ้งและรู้ว่าจะนำรายการใดออกได้
ก่อนอื่นให้ส่งข้อความที่เป็นมิตร เช่น "นี่คือรถเข็นช็อปปิ้งของคุณ" ตามด้วยข้อความอื่นที่มีภาพสไลด์ของ Rich Card พร้อมคำตอบแนะนำที่เกี่ยวข้องสำหรับ "นำออก 1 รายการ" หรือ "เพิ่ม 1 รายการ" ภาพสไลด์ของการ์ดริชมีเดียควรแสดงจำนวนสินค้าที่บันทึกไว้ในรถเข็นด้วย
สิ่งที่ควรทราบก่อนที่จะเขียนฟังก์ชันจริงคือ หากมีสินค้าเพียงประเภทเดียวในรถเข็นช็อปปิ้ง เราจะแสดงผลเป็นภาพสไลด์ไม่ได้ ภาพสไลด์ของการ์ดริชมีเดียต้องมีการ์ดอย่างน้อย 2 ใบ ในทางกลับกัน หากไม่มีสินค้าในรถเข็น เราต้องการแสดงข้อความง่ายๆ ที่ระบุว่ารถเข็นว่างเปล่า
ด้วยเหตุนี้ เรามากำหนดฟังก์ชันชื่อ send_shopping_cart
กัน ฟังก์ชันนี้จะเชื่อมต่อกับ Google Datastore และขอเอนทิตี ShoppingCart ตามรหัสการสนทนา เมื่อได้ข้อมูลแล้ว เราจะเรียกใช้ฟังก์ชัน get_inventory_data
และใช้ภาพสไลด์ของการ์ดริชมีเดียเพื่อรายงานสถานะของรถเข็นช็อปปิ้ง นอกจากนี้ เราจะต้องขอรหัสของผลิตภัณฑ์ตามชื่อ และสามารถประกาศฟังก์ชันเพื่อค้นหาใน Google Datastore เพื่อระบุค่าดังกล่าว ขณะสร้างภาพสไลด์ เราสามารถเชื่อมโยงการตอบกลับที่แนะนำเพื่อลบรายการหรือเพิ่มรายการตามรหัสผลิตภัณฑ์ ข้อมูลโค้ดด้านล่างจะดําเนินการทั้งหมดเหล่านี้ คัดลอกโค้ดไปวางที่ใดก็ได้ใน 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)
...
ตรวจสอบว่าคุณได้กําหนด CMD_SHOW_CART
ที่ด้านบนของ views.py แล้ว และเรียกใช้ send_shopping_cart
หากผู้ใช้ส่งข้อความที่มี "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)
...
จากตรรกะที่เราได้แนะนำไว้ในฟังก์ชัน send_shopping_cart
เมื่อคุณพิมพ์ "show-cart" เราจะได้ข้อความระบุว่าไม่มีสินค้าในรถเข็น การ์ดริชมีเดียที่แสดงสินค้า 1 รายการในรถเข็น หรือภาพสไลด์ของการ์ดที่แสดงสินค้าหลายรายการ นอกจากนี้ เรายังมีคำตอบแนะนำ 3 รายการ ได้แก่ "ดูราคารวม" "ล้างรถเข็น" และ "ดูเมนู"
ลองใช้การเปลี่ยนแปลงโค้ดข้างต้นเพื่อทดสอบว่ารถเข็นช็อปปิ้งติดตามสินค้าที่เพิ่มและคุณสามารถตรวจสอบรถเข็นจากแพลตฟอร์มการสนทนาได้ตามที่แสดงในภาพหน้าจอด้านบน คุณสามารถทําให้การเปลี่ยนแปลงใช้งานได้ด้วยคําสั่งนี้ที่เรียกใช้จากไดเรกทอรี step-2 ที่คุณเพิ่มการเปลี่ยนแปลง
$ gcloud app deploy
เราจะสร้างฟีเจอร์ "ดูราคารวม" ในส่วนถัดไปหลังจากสร้างฟังก์ชันการทำงานเพื่อนำสินค้าออกจากรถเข็นแล้ว ฟังก์ชัน get_cart_price
จะทํางานคล้ายกับฟีเจอร์ "ดูรถเข็นช็อปปิ้ง" ตรงที่จะตรวจสอบข้อมูลใน Datastore กับไฟล์ inventory.json เพื่อให้ได้ราคารวมของรถเข็นช็อปปิ้ง ซึ่งจะมีประโยชน์สำหรับส่วนถัดไปของโค้ดแล็บที่เราผสานรวมกับการชำระเงิน
การนำสินค้าออกจากรถเข็น
สุดท้าย เราจะทําให้ลักษณะการทํางานของรถเข็นช็อปปิ้งเสร็จสมบูรณ์ได้ด้วยการแสดงฟังก์ชันการนํารถเข็นออก แทนที่ฟังก์ชัน update_shopping_cart
ที่มีอยู่ด้วยข้อมูลโค้ดต่อไปนี้
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)
การส่งข้อความยืนยัน
เมื่อผู้ใช้เพิ่มสินค้าลงในรถเข็น คุณควรส่งข้อความยืนยันเพื่อรับทราบการดําเนินการของผู้ใช้และแจ้งว่าคุณได้ดําเนินการตามคําขอแล้ว วิธีนี้ไม่เพียงช่วยกำหนดความคาดหวัง แต่ยังช่วยให้การสนทนาดำเนินต่อไปด้วย
มาขยายฟังก์ชัน update_shopping_cart
เพื่อส่งข้อความไปยังรหัสการสนทนาที่ระบุว่ามีการเพิ่มหรือนำสินค้าออกแล้ว และแสดงคำแนะนำให้ตรวจสอบรถเข็นช็อปปิ้งหรือดูเมนูอีกครั้ง
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)
เท่านี้ก็เรียบร้อย ประสบการณ์การใช้งานรถเข็นช็อปปิ้งที่สมบูรณ์แบบซึ่งช่วยให้ผู้ใช้เพิ่มสินค้า นำสินค้าออก และตรวจสอบสินค้าในรถเข็นได้
เมื่อถึงขั้นตอนนี้ หากต้องการดูฟังก์ชันการทำงานของรถเข็นช็อปปิ้งในการสนทนาผ่าน Business Messages ให้ติดตั้งใช้งานแอปพลิเคชันเพื่อโต้ตอบกับตัวแทน ซึ่งทำได้โดยการเรียกใช้คำสั่งนี้ในไดเรกทอรี step-2
$ gcloud app deploy
5. การเตรียมพร้อมสําหรับการชําระเงิน
เราต้องการวิธีรับราคาของรถเข็นช็อปปิ้งเพื่อเตรียมพร้อมสำหรับการผสานรวมกับระบบประมวลผลการชำระเงินในภาคถัดไปของชุดบทแนะนำนี้ มาสร้างฟังก์ชันที่ดึงข้อมูลราคาให้เราโดยตรวจสอบข้อมูลรถเข็นช็อปปิ้งใน Google Datastore, ดึงข้อมูลราคาของแต่ละรายการจากสินค้าคงคลัง และคูณราคาด้วยจำนวนของแต่ละรายการในรถเข็น
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
...
และสุดท้าย เราจะใช้ฟังก์ชันดังกล่าวและส่งข้อความถึงผู้ใช้ได้
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)
...
มาสรุปทั้งหมดกันด้วยการอัปเดตฟังก์ชัน route_message
และค่าคงที่เพื่อเรียกใช้ตรรกะข้างต้น
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)
...
ภาพหน้าจอบางส่วนที่แสดงผลลัพธ์ของตรรกะข้างต้นมีดังนี้
เมื่อพร้อมที่จะผสานรวมกับผู้ประมวลผลการชำระเงินในส่วนถัดไปของโค้ดแล็บ เราจะเรียกใช้ฟังก์ชัน get_cart_price
เพื่อส่งข้อมูลไปยังผู้ประมวลผลการชำระเงินและเริ่มขั้นตอนการชําระเงิน
อีกครั้ง คุณสามารถลองใช้ฟังก์ชันการทำงานของรถเข็นช็อปปิ้งนี้ในการสนทนาผ่าน Business Messages ได้โดยการติดตั้งใช้งานแอปพลิเคชันและโต้ตอบกับตัวแทน
$ gcloud app deploy
6. ขอแสดงความยินดี
ยินดีด้วย คุณสร้างประสบการณ์การใช้รถเข็นช็อปปิ้งภายใน Business Messages เรียบร้อยแล้ว
สิ่งที่เราไม่ได้พูดถึงในโค้ดแล็บนี้คือฟีเจอร์สำหรับล้างรถเข็นช็อปปิ้งทั้งหมด หากต้องการ ให้ลองขยายระยะเวลาของใบสมัครเพื่อใช้ฟีเจอร์ "ล้างรถเข็น" โซลูชันจะอยู่ในขั้นตอนที่ 3 ของซอร์สโค้ดที่คุณโคลน
เราจะผสานรวมกับผู้ให้บริการประมวลผลการชำระเงินภายนอกในอนาคตเพื่อให้ผู้ใช้ทำธุรกรรมการชำระเงินกับแบรนด์ของคุณได้
รถเข็นช็อปปิ้งที่ดีควรเป็นอย่างไร
ประสบการณ์การใช้รถเข็นช็อปปิ้งที่ดีในการสนทนานั้นไม่ต่างจากแอปบนอุปกรณ์เคลื่อนที่หรือในร้านค้าจริง ความสามารถในการเพิ่มสินค้า นำสินค้าออก และคำนวณราคาของรถเข็นเป็นเพียงฟีเจอร์บางส่วนที่เราได้สำรวจในโค้ดแล็บนี้ สิ่งที่แตกต่างจากรถเข็นช็อปปิ้งในชีวิตจริงคือความสามารถในการดูราคาของสินค้าทั้งหมดในรถเข็นได้ทุกเมื่อขณะที่คุณเพิ่มหรือนำสินค้าออก ฟีเจอร์ที่มีคุณค่าสูงประเภทนี้จะทำให้ประสบการณ์คอมเมิร์ซแบบการสนทนาของคุณโดดเด่น
ขั้นตอนถัดไป
เมื่อพร้อมแล้ว ให้ดูหัวข้อต่อไปนี้เพื่อดูข้อมูลเกี่ยวกับการโต้ตอบที่ซับซ้อนมากขึ้นที่คุณทำได้ใน Business Messages
- Business Messages ทํางานอย่างไร
- แนวทางปฏิบัติแนะนำ
- หลักเกณฑ์เกี่ยวกับโลโก้
- ส่งต่อให้เจ้าหน้าที่บริการลูกค้า
เอกสารอ้างอิง
- SuggestedReply
- เอกสารอ้างอิงข้อความ Business Messages
- คําจํากัดความ JSON สําหรับ RichCard