Reputation: 357
I want to build an order system WhatsApp bot when the user sends a message to the bot and gets a list of items to order then each question the user answers he gets a new answer to the prev question he has answered. I read the documentation of cloud api and configured a webhook to get any message from the user.
const token = process.env.WHATSAPP_TOKEN;
// Imports dependencies and set up http server
const request = require("request"),
express = require("express"),
body_parser = require("body-parser"),
axios = require("axios").default,
app = express().use(body_parser.json()); // creates express http server
// Sets server port and logs message on success
app.listen(process.env.PORT || 1337, () => console.log("webhook is listening"));
// Accepts POST requests at /webhook endpoint
app.post("/webhook", (req, res) => {
// Parse the request body from the POST
let body = req.body;
// Check the Incoming webhook message
console.log(JSON.stringify(req.body, null, 2));
// info on WhatsApp text message payload: https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples#text-messages
if (req.body.object) {
if (
req.body.entry &&
req.body.entry[0].changes &&
req.body.entry[0].changes[0] &&
req.body.entry[0].changes[0].value.messages &&
req.body.entry[0].changes[0].value.messages[0]
) {
const entry = req.body.entry[0]
const change = entry.changes[0]
const { messages } = change.value
// console.log('change value is',change.value)
let phone_number_id =
req.body.entry[0].changes[0].value.metadata.phone_number_id;
let from = req.body.entry[0].changes[0].value.messages[0].from; // extract the phone number from the webhook payload
let msg_body = req.body.entry[0].changes[0].value.messages[0].text.body; // extract the message text from the webhook payload
// console.log({msg_body,from,phone_number_id,entry,field,messages})
axios({
method: "POST", // Required, HTTP method, a string, e.g. POST, GET
url:
"https://graph.facebook.com/v12.0/" +
phone_number_id +
"/messages?access_token=" +
token,
data: {
messaging_product: "whatsapp",
to: from,
text: { body: "Ack: " + msg_body },
},
headers: { "Content-Type": "application/json" },
});
}
res.sendStatus(200);
} else {
// Return a '404 Not Found' if event is not from a WhatsApp API
res.sendStatus(404);
}
});
// Accepts GET requests at the /webhook endpoint. You need this URL to setup webhook initially.
// info on verification request payload: https://developers.facebook.com/docs/graph-api/webhooks/getting-started#verification-requests
app.get("/webhook", (req, res) => {
/**
* UPDATE YOUR VERIFY TOKEN
*This will be the Verify Token value when you set up webhook
**/
const verify_token = process.env.VERIFY_TOKEN;
// Parse params from the webhook verification request
let mode = req.query["hub.mode"];
let token = req.query["hub.verify_token"];
let challenge = req.query["hub.challenge"];
// Check if a token and mode were sent
if (mode && token) {
// Check the mode and token sent are correct
if (mode === "subscribe" && token === verify_token) {
// Respond with 200 OK and challenge token from the request
console.log("WEBHOOK_VERIFIED");
res.status(200).send(challenge);
} else {
// Responds with '403 Forbidden' if verify tokens do not match
res.sendStatus(403);
}
}
});
I got the payload from the user but it's only the message, how do I know what the question the bot sent before and related it to the current answer from the user? as you can see in the post webhook I got the message from the user but now to sure how to know what the question asked by the bot was before. example of payload
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "102487739205598",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "1yyyyyyy",
"phone_number_id": "1xxxxxxxx"
},
"contacts": [
{
"profile": {
"name": "James"
},
"wa_id": "+1xxxxxxxxxxxxx"
}
],
"messages": [
{
"from": "+1xxxxxxxxxxxxx",
"id": "wamid.HBgMOTcyNTI2MzY2NjU1FQIAEhggQzVEMjY1QkNCMURGOEE2RkRFNzhGOTcyN0U3NDhBNzUA",
"timestamp": "1657899618",
"text": {
"body": "Hello, I want to order"
},
"type": "text"
}
]
},
"field": "messages"
}
]
}
]
}
I want to build a full flow but I think I miss here something.
Upvotes: 1
Views: 2619
Reputation: 101
First of all, you don't have to know the utterance the bot sent to the user to relate and process the response from the user.
What you can do is you can create an intent array globally and store the intents based on users' utterances.
For example: You are working on a ticket booking conversation flow. And you want to get the number of tickets from the customer. But without the customer asking to book a ticket you cannot ask the customer for the number of tickets. And if the customer is entering a number value for the number of tickets you should know that the customer is tried to book the ticket and the bot asked for number of tickets.
For this scenario
First when the user asks "book ticket", store the intent to a global array
let intentArray = [];
intentArray.push("ticketBooking");
so if the latest intent is "ticketBooking", then you can ask the user for the number of tickets.
Then when the user enters the number of tickets as a number value you can check your intent array whether the last intent was "ticketBooking" consider the current utterance as the number of ticket values and process the request as per your business logic.
Positive usecase 1:
users' utterances: ["Hi","book tickets","3","Yes"]
bot responses to the above utterances: ["hello there how can I help you?","How many tickets would you like to book?","Got it. You have booked 3 tickets. Can I confirm?"]
In this case the intentArray would be ["welcomeIntent","bookTickets","None","None"]
so when the user enter number of tickets after bookTickets,
if(intentArray[intentArray.length - 1] =="bookTickets" ){
numberOfTickets = //currentUtterance of the user
}else{
reply with "Sorry I didn't understand that"
}
then the user can type "Yes" at any time but we should make sure to process the "Yes" only for the confirmation message. So as per our intent array, we consider "Yes" if it comes second after the bookTickets intent.
That is:
if(intentArray[intentArray.length - 3] == "bookTickets" && currentUtterance == "Yes"){
//respond with "Thank you. your booking is confirmed"
}else{
//respond with "Sorry I didn't understand that"
}
I hope this will give you an idea to resolve your issue.
Upvotes: 0
Reputation: 36104
how do I know what the question the bot sent before and related it to the current answer from the user? as you can see in the post webhook I got the message from the user but now to sure how to know what the question asked by the bot was before.
You can store that message content, and message-id for reference to keep track of who replied to this message.
A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status. For more details see cloud-api send message api.
// send message api's response { "messaging_product": "whatsapp", "contacts": [{ "input": "PHONE_NUMBER", "wa_id": "WHATSAPP_ID", }] "messages": [{ "id": "wamid.ID", }] }
Accessible properties in the webhook payload:
Present in all payloads
object.entry[0].id
object.entry[0].changes[0].value.metadata.phone_number_id
object.entry[0].changes[0].value.metadata.display_phone_number
Present only when the User sends a message to a Business phone number
Access User's Contact Details
object.entry[0].changes[0].value.contacts[0].profile.name
object.entry[0].changes[0].value.contacts[0].profile.wa_id
Message
object.entry[0].changes[0].value.messages[0].id
object.entry[0].changes[0].value.messages[0]
Present only when a Business phone number sends a message to a User
object.entry[0].changes[0].value.statuses[0].id
object.entry[0].changes[0].value.statuses[0]
For more details about webhook see,
I want to build an order system WhatsApp bot when the user sends a message to the bot and gets a list of items to order then each question the user answers he gets a new answer to the prev question he has answered
You need to use an interactive message type, there are 4 types,
Let's understand list
and button
interactive types, read more about both the types of object here,
id
of the option in the sectionid
of the buttonYou will receive that id
in webhook payload whenever user selects any option or click any reply button, and also it will return a message-id that user clicked/replied,
as per both the fields selection id
and message-id
you have to reply a new message to the user.
For more details see the referene webhook payloads list type and button type.
For product
and product_list
types need to setup products store in your business account see how, and see the api documentation.
Upvotes: 1