1658842095
Vào tháng 5 năm 2022, Meta (công ty trước đây được gọi là Facebook, sở hữu WhatsApp) thông báo rằng họ sẽ mở rộng API kinh doanh WhatsApp cho công chúng. Bài viết này dự định chào mừng bạn đến với thế giới cơ hội của Meta, nơi chatbot WhatsApp có thể giúp bạn tạo khách hàng tiềm năng, nhận đơn đặt hàng, lên lịch cuộc hẹn, chạy khảo sát, lấy ý kiến phản hồi của khách hàng, cung cấp hỗ trợ khách hàng có thể mở rộng, gửi hóa đơn và biên nhận, v.v.
Hướng dẫn này sẽ đi sâu vào các phần kỹ thuật của việc xây dựng một chatbot WhatsApp từ đầu.
Đến cuối hướng dẫn này, bạn sẽ tạo được chatbot WhatsApp của riêng mình.
Hướng dẫn của chúng tôi tập trung vào một cửa hàng thương mại điện tử đơn giản dành cho mẹ và người mua bán các mặt hàng gia dụng và thời trang nhanh. Doanh nghiệp sẽ có một chatbot WhatsApp, nơi khách hàng có thể duyệt và mua từ cửa hàng thương mại điện tử.
Mọi cửa hàng thương mại điện tử đều cần sản phẩm (giá cả, tên, mô tả, v.v.) và đối với hướng dẫn này, chúng tôi sẽ sử dụng các sản phẩm giả từ FakeStoreAPI .
Trước khi chúng tôi tiếp tục, bài viết này giả định rằng:
Bước đầu tiên để sử dụng bất kỳ API nào của Meta là tạo một ứng dụng trên Meta dashboard, điều này hoàn toàn miễn phí.
Trên màn hình này, chọn WhatsApp và nhấp vào nút Thiết lập của nó .
Sau đó, bạn sẽ được dẫn đến một màn hình mới, như hình dưới đây.
Trên màn hình này, hãy lưu ý:
1184643492312754
EAAQ1bU6LdrIBA
…+1 555 025 3483
113362588047543
102432872486730
Xin lưu ý rằng mã thông báo truy cập tạm thời sẽ hết hạn sau 24 giờ, tại thời điểm đó chúng tôi cần phải gia hạn mã này. Khi chuyển ứng dụng của mình sang chế độ trực tiếp, bạn có thể đăng ký mã thông báo truy cập vĩnh viễn mà chúng tôi không cần thực hiện vì ứng dụng của chúng tôi đang ở chế độ phát triển.
ID số điện thoại và ID tài khoản doanh nghiệp WhatsApp được gắn với số điện thoại thử nghiệm.
Tiếp theo, hãy thêm một số điện thoại để sử dụng để nhận tin nhắn.
Trong chế độ phát triển, Meta giới hạn chúng tôi ở năm số người nhận vì lý do để ngăn chặn thư rác / lạm dụng. Ở chế độ trực tiếp / sản xuất, số đại diện cho số điện thoại của khách hàng của chúng tôi.
Nhấp vào Chọn số điện thoại người nhận và thêm số WhatsApp của riêng bạn, như được hiển thị trong ảnh chụp màn hình bên dưới:
Sau khi thêm số người nhận, bạn sẽ thấy một màn hình giống như bên dưới. Nếu đây là lần đầu tiên bạn thêm số điện thoại của mình vào các nền tảng Meta - chẳng hạn như Trang Facebook, bộ Meta Business hoặc bảng điều khiển dành cho nhà phát triển Meta - bạn sẽ nhận được thông báo OTP từ Facebook Business nhắc bạn xác minh rằng bạn thực sự sở hữu số người nhận .
Hãy kiểm tra xem mọi thứ cho đến bước này có hoạt động tốt không. Chúng tôi sẽ thực hiện việc này bằng cách nhấp vào nút Gửi tin nhắn .
Nếu mọi thứ đều ổn, bạn sẽ thấy một tin nhắn trong hộp thư đến WhatsApp từ số kiểm tra của mình.
Cho đến thời điểm này, chúng tôi đang làm tốt! Hãy tạm dừng và mở trình chỉnh sửa mã của bạn. Đừng đóng tab trình duyệt của bạn vì chúng tôi sẽ quay lại trang tổng quan Nhà phát triển Meta sau vài phút.
Bây giờ thiết lập của chúng ta có thể gửi tin nhắn thành công, hãy thiết lập cách nhận tin nhắn. Đã đến lúc chúng ta phải làm bẩn tay và đắm mình trong việc viết mã. Tất cả mã chúng tôi sẽ viết cho hướng dẫn này đều nằm trong kho lưu trữ GitHub này .
Tạo một thư mục mới để chứa dự án của chúng tôi. Mở thư mục này trong một thiết bị đầu cuối và chạy tập lệnh dưới đây:
npm init ---yes
Tiếp theo, chúng tôi cài đặt một số gói:
npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev
Dưới đây là giải thích ngắn gọn về từng loại:
express
này rất quan trọng để thiết lập máy chủ của chúng tôi. Máy chủ sẽ chứa một tuyến đường sẽ hoạt động như một webhook của chúng tôipdfkit
này sẽ được sử dụng để tạo hóa đơn cho khách hàng của chúng tôi khi họ thanh toánrequest
này sẽ giúp chúng tôi chạy các yêu cầu tìm nạp tới FakeStoreAPIwhatsappcloudapi_wrapper
nhận tin nhắn WhatsAppTiếp theo, chúng ta sẽ tạo ba tệp:
./app.js
./.env.js
./routes/index.js
Trong ./.env.js
tệp của chúng tôi, hãy nhập mã dưới đây:
const production = {
...process.env,
NODE_ENV: process.env.NODE_ENV || 'production',
};
const development = {
...process.env,
NODE_ENV: process.env.NODE_ENV || 'development',
PORT: '9000',
Meta_WA_accessToken:'EAAKGUD3eZA28BADAJOmO6L19TmZAIEUpdFGHEGHX5sQ3kk4LDQLlnyh607rKSr0x2SAOPJS0kXOUZAhRDIPPGs4vcXQCo2DnfSJMnnIzFW7vaw8EuL7A0HjGZBwE8VwjRnBNam0ARLmfyOCEh1',
Meta_WA_SenderPhoneNumberId: '113362588047543',
Meta_WA_wabaId: '102432872486730',
Meta_WA_VerifyToken: 'YouCanSetYourOwnToken',
};
const fallback = {
...process.env,
NODE_ENV: undefined,
};
module.exports = (environment) => {
console.log(`Execution environment selected is: "${environment}"`);
if (environment === 'production') {
return production;
} else if (environment === 'development') {
return development;
} else {
return fallback;
}
};
Trong cùng một ./.env.js
tệp:
Meta_WA_accessToken
bằng mã thông báo truy cập tạm thời cho ứng dụng Meta của bạnMeta_WA_SenderPhoneNumberId
bằng ID số điện thoại của bạnMeta_WA_wabaId
bằng ID tài khoản doanh nghiệp WhatsApp của bạnMeta_WA_VerifyToken
. Nó có thể là một chuỗi hoặc một số; bạn sẽ thấy cách chúng tôi sử dụng nó trong bước webhooksĐoạn mã trên trước tiên nhập các biến môi trường hiện tại và hủy chúng, sau đó thêm các biến môi trường mới và xuất kết hợp của cả hai dưới dạng một đối tượng.
Trong tệp ./app.js
tệp, hãy chèn mã dưới đây:
process.env = require('./.env.js')(process.env.NODE_ENV || 'development');
const port = process.env.PORT || 9000;
const express = require('express');
let indexRoutes = require('./routes/index.js');
const main = async () => {
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use('/', indexRoutes);
app.use('*', (req, res) => res.status(404).send('404 Not Found'));
app.listen(port, () =>
console.log(`App now running and listening on port ${port}`)
);
};
main();
Dòng đầu tiên của khối mã ở trên chỉ cần nhập ./.env.js
tệp và gán tệp cho nó process.env
, đây là một đối tượng có thể truy cập toàn cầu trong Node.js.
Trong tệp ./routes/index.js
, hãy chèn mã dưới đây:
'use strict';
const router = require('express').Router();
router.get('/meta_wa_callbackurl', (req, res) => {
try {
console.log('GET: Someone is pinging me!');
let mode = req.query['hub.mode'];
let token = req.query['hub.verify_token'];
let challenge = req.query['hub.challenge'];
if (
mode &&
token &&
mode === 'subscribe' &&
process.env.Meta_WA_VerifyToken === token
) {
return res.status(200).send(challenge);
} else {
return res.sendStatus(403);
}
} catch (error) {
console.error({error})
return res.sendStatus(500);
}
});
router.post('/meta_wa_callbackurl', async (req, res) => {
try {
console.log('POST: Someone is pinging me!');
return res.sendStatus(200);
} catch (error) {
console.error({error})
return res.sendStatus(500);
}
});
module.exports = router;
Tiếp theo, mở thiết bị đầu cuối và chạy:
nodemon app.js
Máy chủ Express sẽ chạy trên cổng 9000.
Tiếp theo, mở một thiết bị đầu cuối khác, riêng biệt và chạy:
ngrok http 9000
Lệnh này hiển thị ứng dụng Express của chúng tôi với internet rộng lớn hơn. Mục tiêu ở đây là thiết lập một webhook mà WhatsApp Cloud có thể ping.
Lưu ý URL mà ngrok chỉ định cho máy chủ Express của bạn. Trong ví dụ của tôi, ngrok đã cấp cho tôi URL này https://7b9b-102-219-204-54.ngrok.io
:. Giữ cho cả máy chủ Express và thiết bị đầu cuối ngrok chạy.
Tiếp theo, hãy tiếp tục công việc của chúng ta trong bảng điều khiển Meta Developer. Cuộn đến phần có tiêu đề Định cấu hình Webhooks để nhận tin nhắn và nhấp vào Định cấu hình Webhooks . Liên kết sẽ hiển thị một trang giống như ảnh chụp màn hình bên dưới:
Nhấp vào nút Chỉnh sửa và một cửa sổ bật lên sẽ hiển thị.
Trong trường URL gọi lại , hãy dán URL mà ngrok đã cấp cho bạn và nối nó với tuyến gọi lại, như trong lệnh ./routes/index.js
. URL đầy đủ của tôi, trong trường hợp này, là https://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl
.
Trong trường Xác minh mã thông báo , hãy nhập giá trị của Meta_WA_VerifyToken khi nó xuất hiện trong ./.env.js
tệp của bạn.
Sau đó nhấp vào Xác minh và lưu .
Nếu bạn đã định cấu hình điều này tốt, bạn sẽ thấy một console.log
thông báo trong thiết bị đầu cuối của máy chủ Express cho biết:
GET: Ai đó đang ping tôi!
Bây giờ, hãy làm cho máy chủ Express của chúng tôi nhận tin nhắn đăng ký từ Meta.
Trên cùng một màn hình bảng điều khiển Meta Developers, nhấp vào Quản lý và một cửa sổ bật lên sẽ xuất hiện.
Chọn Tin nhắn và nhấp vào Kiểm tra , trên cùng một hàng.
Bạn sẽ thấy một console.log
thông báo trong thiết bị đầu cuối của máy chủ Express có nội dung:
BÀI ĐĂNG: Ai đó đang ping tôi!
Nếu bạn thấy thông báo này, hãy quay lại cùng một cửa sổ bật lên và nhấp vào Đăng ký trong cùng một hàng thông báo. Sau đó, nhấp vào Xong .
Đầu tiên, chúng tôi sẽ thiết lập logic của mình để tìm nạp dữ liệu từ FakeStoreAPI, tạo hóa đơn PDF và tạo địa điểm nhận đơn đặt hàng giả. Chúng tôi sẽ gói logic này thành một lớp JavaScript, sau đó chúng tôi sẽ nhập vào logic của ứng dụng.
Tạo một tệp và đặt tên cho nó ./utils/ecommerce_store.js
. Trong tệp này, hãy dán mã sau:
'use strict';
const request = require('request');
const PDFDocument = require('pdfkit');
const fs = require('fs');
module.exports = class EcommerceStore {
constructor() {}
async _fetchAssistant(endpoint) {
return new Promise((resolve, reject) => {
request.get(
`https://fakestoreapi.com${endpoint ? endpoint : '/'}`,
(error, res, body) => {
try {
if (error) {
reject(error);
} else {
resolve({
status: 'success',
data: JSON.parse(body),
});
}
} catch (error) {
reject(error);
}
}
);
});
}
async getProductById(productId) {
return await this._fetchAssistant(`/products/${productId}`);
}
async getAllCategories() {
return await this._fetchAssistant('/products/categories?limit=100');
}
async getProductsInCategory(categoryId) {
return await this._fetchAssistant(
`/products/category/${categoryId}?limit=10`
);
}
generatePDFInvoice({ order_details, file_path }) {
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream(file_path));
doc.fontSize(25);
doc.text(order_details, 100, 100);
doc.end();
return;
}
generateRandomGeoLocation() {
let storeLocations = [
{
latitude: 44.985613,
longitude: 20.1568773,
address: 'New Castle',
},
{
latitude: 36.929749,
longitude: 98.480195,
address: 'Glacier Hill',
},
{
latitude: 28.91667,
longitude: 30.85,
address: 'Buena Vista',
},
];
return storeLocations[
Math.floor(Math.random() * storeLocations.length)
];
}
};
Trong đoạn mã trên, chúng ta đã tạo một lớp được gọi là EcommerceStore
.
Phương thức đầu tiên _fetchAssistant
, nhận một điểm cuối mà nó sử dụng để ping fakestoreapi.com .
Các phương thức sau hoạt động như trình tạo truy vấn cho phương thức đầu tiên:
getProductById
nhận ID sản phẩm và sau đó nhận dữ liệu liên quan đến sản phẩm cụ thể đógetAllCategories
tìm nạp tất cả các danh mục có trong fakestoreapi.comgetProductsInCategory
nhận một danh mục sản phẩm và sau đó tiến hành tìm nạp tất cả các sản phẩm trong danh mục cụ thể đóCác trình xây dựng truy vấn này sẽ gọi phương thức đầu tiên.
Tiếp tục, phương thức generatePDFInvoice
nhận một đoạn văn bản và một đường dẫn tệp. Sau đó, nó tạo một tài liệu PDF, viết văn bản trên đó và sau đó lưu trữ tài liệu trong đường dẫn tệp được cung cấp.
Phương thức này generateRandomGeoLocation
chỉ trả về một vị trí địa lý ngẫu nhiên. Phương pháp này sẽ hữu ích khi chúng tôi gửi địa điểm nhận đơn hàng của shop cho khách hàng muốn lấy hàng của họ.
Để xử lý hành trình của khách hàng, chúng tôi cần giữ một phiên bao gồm hồ sơ khách hàng và giỏ hàng của họ. Do đó, mỗi khách hàng sẽ có phiên duy nhất của riêng họ.
Trong quá trình sản xuất, chúng tôi có thể sử dụng cơ sở dữ liệu như MySQL, MongoDB hoặc một thứ gì đó khác có khả năng phục hồi, nhưng để giữ cho hướng dẫn của chúng tôi gọn gàng và ngắn gọn, chúng tôi sẽ sử dụng cấu trúc dữ liệu của ES2015Map
. Với Map
, chúng tôi có thể lưu trữ và truy xuất dữ liệu cụ thể, có thể lặp lại, chẳng hạn như dữ liệu khách hàng duy nhất.
Trong ./routes/index.js
tệp của bạn, hãy thêm đoạn mã sau ngay bên trên router.get('/meta_wa_callbackurl', (req, res)
.
const EcommerceStore = require('./../utils/ecommerce_store.js');
let Store = new EcommerceStore();
const CustomerSession = new Map();
router.get('/meta_wa_callbackurl', (req, res) => {//this line already exists. Add the above lines
Dòng đầu tiên nhập EcommerceStore
lớp, trong khi dòng thứ hai khởi tạo nó. Dòng thứ ba tạo phiên của khách hàng mà chúng tôi sẽ sử dụng để lưu trữ hành trình của khách hàng.
Nhớ whatsappcloudapi_wrapper
gói mà chúng tôi đã cài đặt trước đó? Đã đến lúc nhập và khởi tạo nó.
Trong ./routes/index.js
tệp, hãy thêm các dòng mã sau vào bên dưới khai báo bộ định tuyến Express:
const router = require('express').Router(); // This line already exists. Below it add the following lines:
const WhatsappCloudAPI = require('whatsappcloudapi_wrapper');
const Whatsapp = new WhatsappCloudAPI({
accessToken: process.env.Meta_WA_accessToken,
senderPhoneNumberId: process.env.Meta_WA_SenderPhoneNumberId,
WABA_ID: process.env.Meta_WA_wabaId,
});
Các giá trị sau là các biến môi trường mà chúng tôi đã xác định trong ./.env.js
tệp của mình:
process.env.Meta_WA_accessToken
process.env.Meta_WA_SenderPhoneNumberId
process.env.Meta_WA_wabaId
Chúng tôi khởi tạo lớp WhatsAppCloudAPI với ba giá trị ở trên và đặt tên cho phiên bản của chúng tôi Whatsapp
.
Tiếp theo, hãy phân tích cú pháp tất cả dữ liệu được đưa vào /meta_wa_callbackurl
webhook POST. Bằng cách phân tích cú pháp nội dung của các yêu cầu, chúng tôi sẽ có thể trích xuất tin nhắn và các chi tiết khác, như tên của người gửi, số điện thoại của người gửi, v.v.
Xin lưu ý : Tất cả các chỉnh sửa mã mà chúng tôi thực hiện từ thời điểm này sẽ hoàn toàn được thực hiện trong
./routes/index.js
tệp.
Thêm các dòng mã sau vào bên dưới dấu ngoặc mở của try{
câu lệnh:
try { // This line already exists. Add the below lines
let data = Whatsapp.parseMessage(req.body);
if (data?.isMessage) {
let incomingMessage = data.message;
let recipientPhone = incomingMessage.from.phone; // extract the phone number of sender
let recipientName = incomingMessage.from.name;
let typeOfMsg = incomingMessage.type; // extract the type of message (some are text, others are images, others are responses to buttons etc...)
let message_id = incomingMessage.message_id; // extract the message id
}
Bây giờ, khi khách hàng gửi tin nhắn cho chúng tôi, webhook của chúng tôi sẽ nhận được tin nhắn đó. Tin nhắn được chứa trong phần nội dung yêu cầu của webhook. Để trích xuất thông tin hữu ích ra khỏi phần nội dung của yêu cầu, chúng tôi cần chuyển phần nội dung đó vào parseMessage
phương thức của phiên bản WhatsApp.
Sau đó, sử dụng một if
câu lệnh, chúng tôi kiểm tra xem kết quả của phương pháp có chứa một tin nhắn WhatsApp hợp lệ hay không.
Bên trong if
câu lệnh, chúng tôi xác định incomingMessage
, có chứa thông báo. Chúng tôi cũng xác định các biến khác:
recipientPhone
là số của khách hàng đã gửi tin nhắn cho chúng tôi. Chúng tôi sẽ gửi cho họ một tin nhắn trả lời, do đó có tiền tố "người nhận"recipientName
là tên của khách hàng đã gửi tin nhắn cho chúng tôi. Đây là tên họ đã đặt cho mình trong hồ sơ WhatsApp của họtypeOfMsg
là loại tin nhắn mà một khách hàng đã gửi cho chúng tôi. Như chúng ta sẽ thấy ở phần sau, một số tin nhắn là văn bản đơn giản, trong khi những tin nhắn khác là trả lời cho các nút (đừng lo lắng, điều này sẽ sớm có ý nghĩa!)message_id
là một chuỗi ký tự xác định duy nhất một tin nhắn mà chúng tôi đã nhận được. Điều này hữu ích khi chúng tôi muốn thực hiện các tác vụ cụ thể cho thư đó, chẳng hạn như đánh dấu thư là đã đọcCho đến thời điểm này, tất cả đều có vẻ ổn, nhưng chúng tôi sẽ xác nhận ngay sau đây.
Vì hướng dẫn của chúng tôi sẽ không đi sâu vào bất kỳ hình thức xử lý AI hoặc ngôn ngữ tự nhiên (NLP) nào, chúng tôi sẽ xác định luồng trò chuyện của mình bằng if…else
logic đơn giản.
Logic hội thoại bắt đầu khi khách hàng gửi tin nhắn văn bản. Chúng tôi sẽ không xem xét bản thân thông báo, vì vậy chúng tôi sẽ không biết họ định làm gì, nhưng chúng tôi có thể cho khách hàng biết bot của chúng tôi có thể làm gì.
Hãy cung cấp cho khách hàng một ngữ cảnh đơn giản để họ có thể trả lời với một mục đích cụ thể.
Chúng tôi sẽ cung cấp cho khách hàng hai nút:
Để thực hiện việc này, hãy chèn đoạn mã sau vào bên dưới message_id
:
if (typeOfMsg === 'text_message') {
await Whatsapp.sendSimpleButtons({
message: `Hey ${recipientName}, \nYou are speaking to a chatbot.\nWhat do you want to do next?`,
recipientPhone: recipientPhone,
listOfButtons: [
{
title: 'View some products',
id: 'see_categories',
},
{
title: 'Speak to a human',
id: 'speak_to_human',
},
],
});
}
Tuyên bố trên if
chỉ cho phép chúng tôi xử lý tin nhắn văn bản.
Phương sendSimpleButtons
pháp này cho phép chúng tôi gửi các nút tới khách hàng. Ghi chú về các thuộc tính title
và id
. Đó là những gì khách title
hàng sẽ thấy và id
là những gì chúng tôi sẽ sử dụng để biết khách hàng đã nhấp vào nút nào.
Hãy kiểm tra xem chúng tôi đã làm điều này đúng. Mở ứng dụng WhatsApp của bạn và gửi tin nhắn văn bản đến tài khoản doanh nghiệp WhatsApp.
Nếu bạn nhận được phản hồi như ảnh chụp màn hình ở trên, xin chúc mừng! Bạn vừa gửi tin nhắn đầu tiên của mình qua API đám mây WhatsApp.
Vì khách hàng có thể nhấp vào một trong hai nút, chúng ta hãy quan tâm đến nút Nói với một người .
Bên ngoài if
câu lệnh text_message
logic, hãy chèn đoạn mã sau:
if (typeOfMsg === 'simple_button_message') {
let button_id = incomingMessage.button_reply.id;
if (button_id === 'speak_to_human') {
await Whatsapp.sendText({
recipientPhone: recipientPhone,
message: `Arguably, chatbots are faster than humans.\nCall my human with the below details:`,
});
await Whatsapp.sendContact({
recipientPhone: recipientPhone,
contact_profile: {
addresses: [
{
city: 'Nairobi',
country: 'Kenya',
},
],
name: {
first_name: 'Daggie',
last_name: 'Blanqx',
},
org: {
company: 'Mom-N-Pop Shop',
},
phones: [
{
phone: '+1 (555) 025-3483',
},
{
phone: '+254712345678',
},
],
},
});
}
};
Đoạn mã trên thực hiện hai hành động:
sendText
phương pháp nàysendContact
phương thức nàyMã này cũng phát hiện ý định của người dùng bằng cách sử dụng ID của nút mà người dùng đã nhấp vào (trong trường hợp của chúng tôi, ID là incomingMessage.button_reply.id
), và sau đó nó phản hồi với hai tùy chọn hành động.
Bây giờ, quay lại WhatsApp và nhấp vào Nói chuyện với con người . Nếu bạn làm đúng, bạn sẽ thấy một câu trả lời như sau:
Khi bạn nhấp vào thẻ liên hệ bạn nhận được, bạn sẽ thấy như sau:
Tiếp theo, chúng ta hãy làm việc trên nút Xem một số sản phẩm .
Bên trong simple_button_message if
câu lệnh, nhưng ngay bên dưới và bên ngoài speak_to_human if
câu lệnh, hãy thêm đoạn mã sau:
if (button_id === 'see_categories') {
let categories = await Store.getAllCategories();
await Whatsapp.sendSimpleButtons({
message: `We have several categories.\nChoose one of them.`,
recipientPhone: recipientPhone,
listOfButtons: categories.data
.map((category) => ({
title: category,
id: `category_${category}`,
}))
.slice(0, 3)
});
}
Đây là những gì đoạn mã trên thực hiện:
if
dùng đã nhấp vào nút Xem một số sản phẩmFakeStoreAPI
phương getAllCategories
thứcslice(0,3)
- vì WhatsApp chỉ cho phép chúng tôi gửi ba nút đơn giảntitle
và một ID duy nhất được bắt đầu bằngcategory_
sendSimpleButtons
phương pháp, chúng tôi gửi các nút này cho khách hàngQuay lại ứng dụng WhatsApp của bạn một lần nữa và nhấp vào Xem các sản phẩm khác . Nếu bạn đã làm đúng các bước trên, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình bên dưới:
Bây giờ, chúng ta hãy tạo logic để có được sản phẩm trong danh mục mà khách hàng đã chọn.
Vẫn bên trong simple_button_message if
câu lệnh, nhưng bên dưới và bên ngoài see_categories if
câu lệnh, hãy thêm mã sau:
if (button_id.startsWith('category_')) {
let selectedCategory = button_id.split('category_')[1];
let listOfProducts = await Store.getProductsInCategory(selectedCategory);
let listOfSections = [
{
title: ` Top 3: ${selectedCategory}`.substring(0,24),
rows: listOfProducts.data
.map((product) => {
let id = `product_${product.id}`.substring(0,256);
let title = product.title.substring(0,21);
let description = `${product.price}\n${product.description}`.substring(0,68);
return {
id,
title: `${title}...`,
description: `$${description}...`
};
}).slice(0, 10)
},
];
await Whatsapp.sendRadioButtons({
recipientPhone: recipientPhone,
headerText: `#BlackFriday Offers: ${selectedCategory}`,
bodyText: `Our Santa has lined up some great products for you based on your previous shopping history.\n\nPlease select one of the products below:`,
footerText: 'Powered by: BMI LLC',
listOfSections,
});
}
if
Tuyên bố trên xác nhận rằng nút mà khách hàng nhấp vào thực sự là nút có chứa một danh mục .
Điều đầu tiên chúng tôi làm ở đây là trích xuất danh mục cụ thể từ ID của nút. Sau đó, chúng tôi truy vấn FakeStoreAPI của chúng tôi để tìm các sản phẩm thuộc danh mục cụ thể đó.
Sau khi truy vấn, chúng tôi nhận được danh sách các sản phẩm bên trong một mảng , listOfProducts.data
. Bây giờ chúng tôi lặp lại mảng này và đối với mỗi sản phẩm trong đó, chúng tôi trích xuất giá, tiêu đề, mô tả và ID của nó.
Chúng tôi thêm product_
vào id
, điều này sẽ giúp chúng tôi chọn lựa của khách hàng trong bước tiếp theo. Đảm bảo bạn cắt bớt độ dài của ID, tiêu đề và mô tả theo các hạn chế về nút radio (hoặc danh sách) của WhatsApp Cloud API .
Sau đó, chúng tôi trả về ba giá trị: ID, tiêu đề và mô tả. Vì WhatsApp chỉ cho phép chúng tôi tối đa 10 hàng, chúng tôi sẽ giới hạn số lượng sản phẩm là 10 bằng cách sử dụng phương pháp mảng .slice(0,10)
.
Sau đó, chúng tôi gọi sendRadioButtons
phương thức để gửi sản phẩm cho khách hàng. Ghi lại các thuộc tính , và . headerTextbodyTextfooterTextlistOfSections
Quay lại ứng dụng WhatsApp và nhấp vào bất kỳ danh mục sản phẩm nào. Nếu bạn đã làm theo đúng hướng dẫn, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình bên dưới:
Khi bạn nhấp vào Chọn một sản phẩm , bạn sẽ thấy màn hình sau:
Tại thời điểm này, khách hàng có thể chọn một sản phẩm mà họ cảm thấy thú vị, nhưng liệu chúng ta có thể biết họ đã chọn những gì? Vẫn chưa, vì vậy hãy để chúng tôi làm việc trên phần này.
Bên ngoài simple_button_message if
câu lệnh, hãy để chúng tôi thêm một if
câu lệnh khác:
if (typeOfMsg === 'radio_button_message') {
let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
}
Bên trong if
câu lệnh trên và ngay bên dưới câu lệnh selectionId
, hãy thêm đoạn mã sau:
if (selectionId.startsWith('product_')) {
let product_id = selectionId.split('_')[1];
let product = await Store.getProductById(product_id);
const { price, title, description, category, image: imageUrl, rating } = product.data;
let emojiRating = (rvalue) => {
rvalue = Math.floor(rvalue || 0); // generate as many star emojis as whole number ratings
let output = [];
for (var i = 0; i < rvalue; i++) output.push('');
return output.length ? output.join('') : 'N/A';
};
let text = `_Title_: *${title.trim()}*\n\n\n`;
text += `_Description_: ${description.trim()}\n\n\n`;
text += `_Price_: $${price}\n`;
text += `_Category_: ${category}\n`;
text += `${rating?.count || 0} shoppers liked this product.\n`;
text += `_Rated_: ${emojiRating(rating?.rate)}\n`;
await Whatsapp.sendImage({
recipientPhone,
url: imageUrl,
caption: text,
});
await Whatsapp.sendSimpleButtons({
message: `Here is the product, what do you want to do next?`,
recipientPhone: recipientPhone,
listOfButtons: [
{
title: 'Add to cart',
id: `add_to_cart_${product_id}`,
},
{
title: 'Speak to a human',
id: 'speak_to_human',
},
{
title: 'See more products',
id: 'see_categories',
},
],
});
}
Đoạn mã trên thực hiện những việc sau:
emojiRating
chức năng. Nếu xếp hạng là 3,8, nó sẽ hiển thị biểu tượng cảm xúc ba saosendImage
phương thứcSau đó, chúng tôi gửi cho khách hàng danh sách ba nút bằng cách sử dụng sendSimpleButtons
. Một cung cấp cho khách hàng cơ hội để thêm sản phẩm vào giỏ hàng của họ. Hãy lưu ý đến ID của nút có tiền tố add_to_cart_
.
Bây giờ, quay lại ứng dụng WhatsApp của bạn và chọn một sản phẩm. Nếu bạn đã làm theo đúng hướng dẫn, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình sau:
Để theo dõi các sản phẩm mà khách hàng thêm vào giỏ hàng của họ, chúng tôi cần có một nơi để lưu trữ các mặt hàng trong giỏ hàng. Đây là nơi CustomerSession
phát huy tác dụng. Hãy thêm một số logic vào nó.
Bên ngoài radio_button_message if
câu lệnh và ngay bên dưới phần message_id
khai báo, hãy thêm đoạn mã sau:
let message_id = incomingMessage.message_id; // This line already exists. Add the below lines...
// Start of cart logic
if (!CustomerSession.get(recipientPhone)) {
CustomerSession.set(recipientPhone, {
cart: [],
});
}
let addToCart = async ({ product_id, recipientPhone }) => {
let product = await Store.getProductById(product_id);
if (product.status === 'success') {
CustomerSession.get(recipientPhone).cart.push(product.data);
}
};
let listOfItemsInCart = ({ recipientPhone }) => {
let total = 0;
let products = CustomerSession.get(recipientPhone).cart;
total = products.reduce(
(acc, product) => acc + product.price,
total
);
let count = products.length;
return { total, products, count };
};
let clearCart = ({ recipientPhone }) => {
CustomerSession.get(recipientPhone).cart = [];
};
// End of cart logic
if (typeOfMsg === 'text_message') { ... // This line already exists. Add the above lines...
Đoạn mã trên kiểm tra xem phiên của khách hàng đã được tạo hay chưa. Nếu nó chưa được tạo, nó sẽ tạo một phiên mới được nhận dạng duy nhất bởi số điện thoại của khách hàng. Sau đó, chúng tôi khởi tạo một thuộc tính được gọi cart
, bắt đầu dưới dạng một mảng trống.
Hàm addToCart
nhận a product_id
và số lượng khách hàng cụ thể. Sau đó, nó ping FakeStoreAPI để biết dữ liệu của sản phẩm cụ thể và đẩy sản phẩm vào cart
mảng.
Sau đó, listOfItemsInCart
hàm này lấy số điện thoại của khách hàng và truy xuất số điện thoại được liên kết cart
, được sử dụng để tính số lượng sản phẩm trong giỏ hàng và tổng giá của chúng. Cuối cùng, nó trả về các mặt hàng trong giỏ hàng và tổng giá của chúng.
Chức clearCart
năng lấy số điện thoại của khách hàng và chuyển vào giỏ hàng của khách hàng đó.
Với logic giỏ hàng được thực hiện, hãy xây dựng nút Thêm vào giỏ hàng . Bên trong simple_button_message if
câu lệnh và bên dưới phần button_id
khai báo, hãy thêm đoạn mã sau:
if (button_id.startsWith('add_to_cart_')) {
let product_id = button_id.split('add_to_cart_')[1];
await addToCart({ recipientPhone, product_id });
let numberOfItemsInCart = listOfItemsInCart({ recipientPhone }).count;
await Whatsapp.sendSimpleButtons({
message: `Your cart has been updated.\nNumber of items in cart: ${numberOfItemsInCart}.\n\nWhat do you want to do next?`,
recipientPhone: recipientPhone,
listOfButtons: [
{
title: 'Checkout ',
id: `checkout`,
},
{
title: 'See more products',
id: 'see_categories',
},
],
});
}
Đoạn mã trên trích xuất ID sản phẩm từ nút khách hàng nhấp vào, sau đó gọi addToCart
chức năng lưu sản phẩm vào giỏ hàng của phiên khách hàng. Sau đó, nó trích xuất số lượng mặt hàng trong giỏ hàng của phiên của khách hàng và cho khách hàng biết họ có bao nhiêu sản phẩm. Nó cũng gửi hai nút, một trong số đó cho phép người dùng kiểm tra.
Ghi lại ID nút và quay lại ứng dụng WhatsApp của bạn. Nhấp vào Thêm vào giỏ hàng . Nếu bạn làm theo đúng hướng dẫn, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình bên dưới:
Bây giờ khách hàng của chúng tôi có thể thêm các mặt hàng vào giỏ hàng, chúng tôi có thể viết logic để thanh toán.
Bên trong simple_button_message if
câu lệnh nhưng bên ngoài add_to_cart_ if
câu lệnh, hãy thêm đoạn mã sau:
if (button_id === 'checkout') {
let finalBill = listOfItemsInCart({ recipientPhone });
let invoiceText = `List of items in your cart:\n`;
finalBill.products.forEach((item, index) => {
let serial = index + 1;
invoiceText += `\n#${serial}: ${item.title} @ $${item.price}`;
});
invoiceText += `\n\nTotal: $${finalBill.total}`;
Store.generatePDFInvoice({
order_details: invoiceText,
file_path: `./invoice_${recipientName}.pdf`,
});
await Whatsapp.sendText({
message: invoiceText,
recipientPhone: recipientPhone,
});
await Whatsapp.sendSimpleButtons({
recipientPhone: recipientPhone,
message: `Thank you for shopping with us, ${recipientName}.\n\nYour order has been received & will be processed shortly.`,
message_id,
listOfButtons: [
{
title: 'See more products',
id: 'see_categories',
},
{
title: 'Print my invoice',
id: 'print_invoice',
},
],
});
clearCart({ recipientPhone });
}
Đoạn mã trên thực hiện những việc sau:
finalBill
invoiceText
, biến này sẽ chứa văn bản mà chúng tôi sẽ gửi cho khách hàng cũng như văn bản sẽ được soạn thảo thành phiên bản PDF của hóa đơnforEach
lặp chỉ đơn giản là nối title
và price
của từng sản phẩm với hóa đơngeneratePDFInvoice
thức (giống phương thức mà chúng tôi đã xác định trong EcommerceStore
lớp của mình) lấy chi tiết của đơn đặt hàng, soạn thảo tài liệu PDF và lưu nó vào đường dẫn tệp trong thư mục / thư mục cục bộ mà chúng tôi đã cung cấpsendText
thức gửi một tin nhắn văn bản đơn giản chứa thông tin chi tiết về đơn đặt hàng cho khách hàngsendSimpleButtons
gửi một số nút cho khách hàng. Hãy lưu ý đến nút In hóa đơn của tôi và ID của nóclearCart
phương pháp làm trống giỏ hàngBây giờ, hãy quay lại ứng dụng WhatsApp của bạn và nhấp vào Thanh toán . Nếu bạn làm theo đúng hướng dẫn, bạn sẽ thấy một câu trả lời giống như ảnh chụp màn hình sau:
Tại thời điểm này, khách hàng sẽ nhận được hóa đơn PDF có thể in được. Vì lý do này, hãy để chúng tôi làm việc trên một số logic liên quan đến nút In hóa đơn của tôi .
Bên trong simple_button_message if
câu lệnh nhưng bên ngoài checkout if
câu lệnh, hãy thêm đoạn mã sau:
if (button_id === 'print_invoice') {
// Send the PDF invoice
await Whatsapp.sendDocument({
recipientPhone: recipientPhone,
caption:`Mom-N-Pop Shop invoice #${recipientName}`
file_path: `./invoice_${recipientName}.pdf`,
});
// Send the location of our pickup station to the customer, so they can come and pick up their order
let warehouse = Store.generateRandomGeoLocation();
await Whatsapp.sendText({
recipientPhone: recipientPhone,
message: `Your order has been fulfilled. Come and pick it up, as you pay, here:`,
});
await Whatsapp.sendLocation({
recipientPhone,
latitude: warehouse.latitude,
longitude: warehouse.longitude,
address: warehouse.address,
name: 'Mom-N-Pop Shop',
});
}
Đoạn mã trên lấy tài liệu PDF được tạo ở bước trước từ hệ thống tệp cục bộ và gửi cho khách hàng bằng sendDocument
phương pháp này.
Khi một khách hàng đặt mua một sản phẩm trực tuyến, họ cũng cần biết họ sẽ nhận được sản phẩm vật chất như thế nào. Vì lý do này, chúng tôi đã tạo một số tọa độ ngẫu nhiên bằng cách sử dụng generateRandomGeoLocation
phương thức của EcommerceStore
lớp và gửi các tọa độ này cho khách hàng bằng sendLocation
phương pháp này để cho họ biết nơi họ có thể lấy sản phẩm của mình.
Bây giờ, hãy mở ứng dụng WhatsApp của bạn và nhấp vào In hóa đơn của tôi .
Nếu bạn đã làm theo đúng hướng dẫn ở trên, bạn sẽ thấy câu trả lời giống với ảnh chụp màn hình bên dưới:
Cuối cùng, bạn có thể nhận thấy rằng các dấu kiểm bên dưới thư có màu xám thay vì màu xanh lam. Điều này cho thấy rằng các tin nhắn chúng tôi đã gửi không trả lại các xác nhận đã đọc mặc dù thực tế là bot của chúng tôi đang đọc chúng.
Những con bọ màu xám có thể gây khó chịu cho khách hàng và vì lý do này, chúng tôi cần làm việc để hiển thị những con bọ màu xanh lam.
Bên ngoài simple_button_message if
câu lệnh và trước dấu ngoặc nhọn đóng của data?.isMessage if
câu lệnh, hãy thêm đoạn mã sau:
await Whatsapp.markMessageAsRead({ message_id });
Một dòng chữ đơn giản này đánh dấu một tin nhắn được đọc ngay sau khi chúng tôi trả lời nó.
Bây giờ, hãy mở ứng dụng WhatsApp của bạn và gửi một tin nhắn văn bản ngẫu nhiên. Bạn có thấy những gì tôi đang thấy không?
Nếu các cuộc trò chuyện trước đó của bạn đã được cập nhật bằng dấu tích màu xanh, thì xin chúc mừng! Bạn đã xem đến phần cuối của hướng dẫn này và học được một số điều trong suốt quá trình.
Với tổng số 2 tỷ người dùng hoạt động hàng tháng, việc bỏ qua WhatsApp như một chiến lược thương mại điện tử là một cách chắc chắn để tụt hậu so với đối thủ cạnh tranh của doanh nghiệp bạn và vì hầu hết khách hàng của bạn đã sử dụng WhatsApp trong các hoạt động hàng ngày của họ, tại sao không nên ' doanh nghiệp của bạn có gặp họ ở đó không?
Tôi hy vọng hướng dẫn này sẽ hữu ích trong việc làm sáng tỏ API đám mây WhatsApp và tôi hy vọng bạn đã có một chút thú vị trong suốt quá trình này. Hãy cho tôi biết những chủ đề khác mà bạn có thể thấy thú vị và đừng quên chia sẻ bài viết này với giới công nghệ của bạn.
Nguồn: https://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/
#whatsapp #ecommerce #cloud #api #nodejs
1658842095
Vào tháng 5 năm 2022, Meta (công ty trước đây được gọi là Facebook, sở hữu WhatsApp) thông báo rằng họ sẽ mở rộng API kinh doanh WhatsApp cho công chúng. Bài viết này dự định chào mừng bạn đến với thế giới cơ hội của Meta, nơi chatbot WhatsApp có thể giúp bạn tạo khách hàng tiềm năng, nhận đơn đặt hàng, lên lịch cuộc hẹn, chạy khảo sát, lấy ý kiến phản hồi của khách hàng, cung cấp hỗ trợ khách hàng có thể mở rộng, gửi hóa đơn và biên nhận, v.v.
Hướng dẫn này sẽ đi sâu vào các phần kỹ thuật của việc xây dựng một chatbot WhatsApp từ đầu.
Đến cuối hướng dẫn này, bạn sẽ tạo được chatbot WhatsApp của riêng mình.
Hướng dẫn của chúng tôi tập trung vào một cửa hàng thương mại điện tử đơn giản dành cho mẹ và người mua bán các mặt hàng gia dụng và thời trang nhanh. Doanh nghiệp sẽ có một chatbot WhatsApp, nơi khách hàng có thể duyệt và mua từ cửa hàng thương mại điện tử.
Mọi cửa hàng thương mại điện tử đều cần sản phẩm (giá cả, tên, mô tả, v.v.) và đối với hướng dẫn này, chúng tôi sẽ sử dụng các sản phẩm giả từ FakeStoreAPI .
Trước khi chúng tôi tiếp tục, bài viết này giả định rằng:
Bước đầu tiên để sử dụng bất kỳ API nào của Meta là tạo một ứng dụng trên Meta dashboard, điều này hoàn toàn miễn phí.
Trên màn hình này, chọn WhatsApp và nhấp vào nút Thiết lập của nó .
Sau đó, bạn sẽ được dẫn đến một màn hình mới, như hình dưới đây.
Trên màn hình này, hãy lưu ý:
1184643492312754
EAAQ1bU6LdrIBA
…+1 555 025 3483
113362588047543
102432872486730
Xin lưu ý rằng mã thông báo truy cập tạm thời sẽ hết hạn sau 24 giờ, tại thời điểm đó chúng tôi cần phải gia hạn mã này. Khi chuyển ứng dụng của mình sang chế độ trực tiếp, bạn có thể đăng ký mã thông báo truy cập vĩnh viễn mà chúng tôi không cần thực hiện vì ứng dụng của chúng tôi đang ở chế độ phát triển.
ID số điện thoại và ID tài khoản doanh nghiệp WhatsApp được gắn với số điện thoại thử nghiệm.
Tiếp theo, hãy thêm một số điện thoại để sử dụng để nhận tin nhắn.
Trong chế độ phát triển, Meta giới hạn chúng tôi ở năm số người nhận vì lý do để ngăn chặn thư rác / lạm dụng. Ở chế độ trực tiếp / sản xuất, số đại diện cho số điện thoại của khách hàng của chúng tôi.
Nhấp vào Chọn số điện thoại người nhận và thêm số WhatsApp của riêng bạn, như được hiển thị trong ảnh chụp màn hình bên dưới:
Sau khi thêm số người nhận, bạn sẽ thấy một màn hình giống như bên dưới. Nếu đây là lần đầu tiên bạn thêm số điện thoại của mình vào các nền tảng Meta - chẳng hạn như Trang Facebook, bộ Meta Business hoặc bảng điều khiển dành cho nhà phát triển Meta - bạn sẽ nhận được thông báo OTP từ Facebook Business nhắc bạn xác minh rằng bạn thực sự sở hữu số người nhận .
Hãy kiểm tra xem mọi thứ cho đến bước này có hoạt động tốt không. Chúng tôi sẽ thực hiện việc này bằng cách nhấp vào nút Gửi tin nhắn .
Nếu mọi thứ đều ổn, bạn sẽ thấy một tin nhắn trong hộp thư đến WhatsApp từ số kiểm tra của mình.
Cho đến thời điểm này, chúng tôi đang làm tốt! Hãy tạm dừng và mở trình chỉnh sửa mã của bạn. Đừng đóng tab trình duyệt của bạn vì chúng tôi sẽ quay lại trang tổng quan Nhà phát triển Meta sau vài phút.
Bây giờ thiết lập của chúng ta có thể gửi tin nhắn thành công, hãy thiết lập cách nhận tin nhắn. Đã đến lúc chúng ta phải làm bẩn tay và đắm mình trong việc viết mã. Tất cả mã chúng tôi sẽ viết cho hướng dẫn này đều nằm trong kho lưu trữ GitHub này .
Tạo một thư mục mới để chứa dự án của chúng tôi. Mở thư mục này trong một thiết bị đầu cuối và chạy tập lệnh dưới đây:
npm init ---yes
Tiếp theo, chúng tôi cài đặt một số gói:
npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev
Dưới đây là giải thích ngắn gọn về từng loại:
express
này rất quan trọng để thiết lập máy chủ của chúng tôi. Máy chủ sẽ chứa một tuyến đường sẽ hoạt động như một webhook của chúng tôipdfkit
này sẽ được sử dụng để tạo hóa đơn cho khách hàng của chúng tôi khi họ thanh toánrequest
này sẽ giúp chúng tôi chạy các yêu cầu tìm nạp tới FakeStoreAPIwhatsappcloudapi_wrapper
nhận tin nhắn WhatsAppTiếp theo, chúng ta sẽ tạo ba tệp:
./app.js
./.env.js
./routes/index.js
Trong ./.env.js
tệp của chúng tôi, hãy nhập mã dưới đây:
const production = {
...process.env,
NODE_ENV: process.env.NODE_ENV || 'production',
};
const development = {
...process.env,
NODE_ENV: process.env.NODE_ENV || 'development',
PORT: '9000',
Meta_WA_accessToken:'EAAKGUD3eZA28BADAJOmO6L19TmZAIEUpdFGHEGHX5sQ3kk4LDQLlnyh607rKSr0x2SAOPJS0kXOUZAhRDIPPGs4vcXQCo2DnfSJMnnIzFW7vaw8EuL7A0HjGZBwE8VwjRnBNam0ARLmfyOCEh1',
Meta_WA_SenderPhoneNumberId: '113362588047543',
Meta_WA_wabaId: '102432872486730',
Meta_WA_VerifyToken: 'YouCanSetYourOwnToken',
};
const fallback = {
...process.env,
NODE_ENV: undefined,
};
module.exports = (environment) => {
console.log(`Execution environment selected is: "${environment}"`);
if (environment === 'production') {
return production;
} else if (environment === 'development') {
return development;
} else {
return fallback;
}
};
Trong cùng một ./.env.js
tệp:
Meta_WA_accessToken
bằng mã thông báo truy cập tạm thời cho ứng dụng Meta của bạnMeta_WA_SenderPhoneNumberId
bằng ID số điện thoại của bạnMeta_WA_wabaId
bằng ID tài khoản doanh nghiệp WhatsApp của bạnMeta_WA_VerifyToken
. Nó có thể là một chuỗi hoặc một số; bạn sẽ thấy cách chúng tôi sử dụng nó trong bước webhooksĐoạn mã trên trước tiên nhập các biến môi trường hiện tại và hủy chúng, sau đó thêm các biến môi trường mới và xuất kết hợp của cả hai dưới dạng một đối tượng.
Trong tệp ./app.js
tệp, hãy chèn mã dưới đây:
process.env = require('./.env.js')(process.env.NODE_ENV || 'development');
const port = process.env.PORT || 9000;
const express = require('express');
let indexRoutes = require('./routes/index.js');
const main = async () => {
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use('/', indexRoutes);
app.use('*', (req, res) => res.status(404).send('404 Not Found'));
app.listen(port, () =>
console.log(`App now running and listening on port ${port}`)
);
};
main();
Dòng đầu tiên của khối mã ở trên chỉ cần nhập ./.env.js
tệp và gán tệp cho nó process.env
, đây là một đối tượng có thể truy cập toàn cầu trong Node.js.
Trong tệp ./routes/index.js
, hãy chèn mã dưới đây:
'use strict';
const router = require('express').Router();
router.get('/meta_wa_callbackurl', (req, res) => {
try {
console.log('GET: Someone is pinging me!');
let mode = req.query['hub.mode'];
let token = req.query['hub.verify_token'];
let challenge = req.query['hub.challenge'];
if (
mode &&
token &&
mode === 'subscribe' &&
process.env.Meta_WA_VerifyToken === token
) {
return res.status(200).send(challenge);
} else {
return res.sendStatus(403);
}
} catch (error) {
console.error({error})
return res.sendStatus(500);
}
});
router.post('/meta_wa_callbackurl', async (req, res) => {
try {
console.log('POST: Someone is pinging me!');
return res.sendStatus(200);
} catch (error) {
console.error({error})
return res.sendStatus(500);
}
});
module.exports = router;
Tiếp theo, mở thiết bị đầu cuối và chạy:
nodemon app.js
Máy chủ Express sẽ chạy trên cổng 9000.
Tiếp theo, mở một thiết bị đầu cuối khác, riêng biệt và chạy:
ngrok http 9000
Lệnh này hiển thị ứng dụng Express của chúng tôi với internet rộng lớn hơn. Mục tiêu ở đây là thiết lập một webhook mà WhatsApp Cloud có thể ping.
Lưu ý URL mà ngrok chỉ định cho máy chủ Express của bạn. Trong ví dụ của tôi, ngrok đã cấp cho tôi URL này https://7b9b-102-219-204-54.ngrok.io
:. Giữ cho cả máy chủ Express và thiết bị đầu cuối ngrok chạy.
Tiếp theo, hãy tiếp tục công việc của chúng ta trong bảng điều khiển Meta Developer. Cuộn đến phần có tiêu đề Định cấu hình Webhooks để nhận tin nhắn và nhấp vào Định cấu hình Webhooks . Liên kết sẽ hiển thị một trang giống như ảnh chụp màn hình bên dưới:
Nhấp vào nút Chỉnh sửa và một cửa sổ bật lên sẽ hiển thị.
Trong trường URL gọi lại , hãy dán URL mà ngrok đã cấp cho bạn và nối nó với tuyến gọi lại, như trong lệnh ./routes/index.js
. URL đầy đủ của tôi, trong trường hợp này, là https://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl
.
Trong trường Xác minh mã thông báo , hãy nhập giá trị của Meta_WA_VerifyToken khi nó xuất hiện trong ./.env.js
tệp của bạn.
Sau đó nhấp vào Xác minh và lưu .
Nếu bạn đã định cấu hình điều này tốt, bạn sẽ thấy một console.log
thông báo trong thiết bị đầu cuối của máy chủ Express cho biết:
GET: Ai đó đang ping tôi!
Bây giờ, hãy làm cho máy chủ Express của chúng tôi nhận tin nhắn đăng ký từ Meta.
Trên cùng một màn hình bảng điều khiển Meta Developers, nhấp vào Quản lý và một cửa sổ bật lên sẽ xuất hiện.
Chọn Tin nhắn và nhấp vào Kiểm tra , trên cùng một hàng.
Bạn sẽ thấy một console.log
thông báo trong thiết bị đầu cuối của máy chủ Express có nội dung:
BÀI ĐĂNG: Ai đó đang ping tôi!
Nếu bạn thấy thông báo này, hãy quay lại cùng một cửa sổ bật lên và nhấp vào Đăng ký trong cùng một hàng thông báo. Sau đó, nhấp vào Xong .
Đầu tiên, chúng tôi sẽ thiết lập logic của mình để tìm nạp dữ liệu từ FakeStoreAPI, tạo hóa đơn PDF và tạo địa điểm nhận đơn đặt hàng giả. Chúng tôi sẽ gói logic này thành một lớp JavaScript, sau đó chúng tôi sẽ nhập vào logic của ứng dụng.
Tạo một tệp và đặt tên cho nó ./utils/ecommerce_store.js
. Trong tệp này, hãy dán mã sau:
'use strict';
const request = require('request');
const PDFDocument = require('pdfkit');
const fs = require('fs');
module.exports = class EcommerceStore {
constructor() {}
async _fetchAssistant(endpoint) {
return new Promise((resolve, reject) => {
request.get(
`https://fakestoreapi.com${endpoint ? endpoint : '/'}`,
(error, res, body) => {
try {
if (error) {
reject(error);
} else {
resolve({
status: 'success',
data: JSON.parse(body),
});
}
} catch (error) {
reject(error);
}
}
);
});
}
async getProductById(productId) {
return await this._fetchAssistant(`/products/${productId}`);
}
async getAllCategories() {
return await this._fetchAssistant('/products/categories?limit=100');
}
async getProductsInCategory(categoryId) {
return await this._fetchAssistant(
`/products/category/${categoryId}?limit=10`
);
}
generatePDFInvoice({ order_details, file_path }) {
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream(file_path));
doc.fontSize(25);
doc.text(order_details, 100, 100);
doc.end();
return;
}
generateRandomGeoLocation() {
let storeLocations = [
{
latitude: 44.985613,
longitude: 20.1568773,
address: 'New Castle',
},
{
latitude: 36.929749,
longitude: 98.480195,
address: 'Glacier Hill',
},
{
latitude: 28.91667,
longitude: 30.85,
address: 'Buena Vista',
},
];
return storeLocations[
Math.floor(Math.random() * storeLocations.length)
];
}
};
Trong đoạn mã trên, chúng ta đã tạo một lớp được gọi là EcommerceStore
.
Phương thức đầu tiên _fetchAssistant
, nhận một điểm cuối mà nó sử dụng để ping fakestoreapi.com .
Các phương thức sau hoạt động như trình tạo truy vấn cho phương thức đầu tiên:
getProductById
nhận ID sản phẩm và sau đó nhận dữ liệu liên quan đến sản phẩm cụ thể đógetAllCategories
tìm nạp tất cả các danh mục có trong fakestoreapi.comgetProductsInCategory
nhận một danh mục sản phẩm và sau đó tiến hành tìm nạp tất cả các sản phẩm trong danh mục cụ thể đóCác trình xây dựng truy vấn này sẽ gọi phương thức đầu tiên.
Tiếp tục, phương thức generatePDFInvoice
nhận một đoạn văn bản và một đường dẫn tệp. Sau đó, nó tạo một tài liệu PDF, viết văn bản trên đó và sau đó lưu trữ tài liệu trong đường dẫn tệp được cung cấp.
Phương thức này generateRandomGeoLocation
chỉ trả về một vị trí địa lý ngẫu nhiên. Phương pháp này sẽ hữu ích khi chúng tôi gửi địa điểm nhận đơn hàng của shop cho khách hàng muốn lấy hàng của họ.
Để xử lý hành trình của khách hàng, chúng tôi cần giữ một phiên bao gồm hồ sơ khách hàng và giỏ hàng của họ. Do đó, mỗi khách hàng sẽ có phiên duy nhất của riêng họ.
Trong quá trình sản xuất, chúng tôi có thể sử dụng cơ sở dữ liệu như MySQL, MongoDB hoặc một thứ gì đó khác có khả năng phục hồi, nhưng để giữ cho hướng dẫn của chúng tôi gọn gàng và ngắn gọn, chúng tôi sẽ sử dụng cấu trúc dữ liệu của ES2015Map
. Với Map
, chúng tôi có thể lưu trữ và truy xuất dữ liệu cụ thể, có thể lặp lại, chẳng hạn như dữ liệu khách hàng duy nhất.
Trong ./routes/index.js
tệp của bạn, hãy thêm đoạn mã sau ngay bên trên router.get('/meta_wa_callbackurl', (req, res)
.
const EcommerceStore = require('./../utils/ecommerce_store.js');
let Store = new EcommerceStore();
const CustomerSession = new Map();
router.get('/meta_wa_callbackurl', (req, res) => {//this line already exists. Add the above lines
Dòng đầu tiên nhập EcommerceStore
lớp, trong khi dòng thứ hai khởi tạo nó. Dòng thứ ba tạo phiên của khách hàng mà chúng tôi sẽ sử dụng để lưu trữ hành trình của khách hàng.
Nhớ whatsappcloudapi_wrapper
gói mà chúng tôi đã cài đặt trước đó? Đã đến lúc nhập và khởi tạo nó.
Trong ./routes/index.js
tệp, hãy thêm các dòng mã sau vào bên dưới khai báo bộ định tuyến Express:
const router = require('express').Router(); // This line already exists. Below it add the following lines:
const WhatsappCloudAPI = require('whatsappcloudapi_wrapper');
const Whatsapp = new WhatsappCloudAPI({
accessToken: process.env.Meta_WA_accessToken,
senderPhoneNumberId: process.env.Meta_WA_SenderPhoneNumberId,
WABA_ID: process.env.Meta_WA_wabaId,
});
Các giá trị sau là các biến môi trường mà chúng tôi đã xác định trong ./.env.js
tệp của mình:
process.env.Meta_WA_accessToken
process.env.Meta_WA_SenderPhoneNumberId
process.env.Meta_WA_wabaId
Chúng tôi khởi tạo lớp WhatsAppCloudAPI với ba giá trị ở trên và đặt tên cho phiên bản của chúng tôi Whatsapp
.
Tiếp theo, hãy phân tích cú pháp tất cả dữ liệu được đưa vào /meta_wa_callbackurl
webhook POST. Bằng cách phân tích cú pháp nội dung của các yêu cầu, chúng tôi sẽ có thể trích xuất tin nhắn và các chi tiết khác, như tên của người gửi, số điện thoại của người gửi, v.v.
Xin lưu ý : Tất cả các chỉnh sửa mã mà chúng tôi thực hiện từ thời điểm này sẽ hoàn toàn được thực hiện trong
./routes/index.js
tệp.
Thêm các dòng mã sau vào bên dưới dấu ngoặc mở của try{
câu lệnh:
try { // This line already exists. Add the below lines
let data = Whatsapp.parseMessage(req.body);
if (data?.isMessage) {
let incomingMessage = data.message;
let recipientPhone = incomingMessage.from.phone; // extract the phone number of sender
let recipientName = incomingMessage.from.name;
let typeOfMsg = incomingMessage.type; // extract the type of message (some are text, others are images, others are responses to buttons etc...)
let message_id = incomingMessage.message_id; // extract the message id
}
Bây giờ, khi khách hàng gửi tin nhắn cho chúng tôi, webhook của chúng tôi sẽ nhận được tin nhắn đó. Tin nhắn được chứa trong phần nội dung yêu cầu của webhook. Để trích xuất thông tin hữu ích ra khỏi phần nội dung của yêu cầu, chúng tôi cần chuyển phần nội dung đó vào parseMessage
phương thức của phiên bản WhatsApp.
Sau đó, sử dụng một if
câu lệnh, chúng tôi kiểm tra xem kết quả của phương pháp có chứa một tin nhắn WhatsApp hợp lệ hay không.
Bên trong if
câu lệnh, chúng tôi xác định incomingMessage
, có chứa thông báo. Chúng tôi cũng xác định các biến khác:
recipientPhone
là số của khách hàng đã gửi tin nhắn cho chúng tôi. Chúng tôi sẽ gửi cho họ một tin nhắn trả lời, do đó có tiền tố "người nhận"recipientName
là tên của khách hàng đã gửi tin nhắn cho chúng tôi. Đây là tên họ đã đặt cho mình trong hồ sơ WhatsApp của họtypeOfMsg
là loại tin nhắn mà một khách hàng đã gửi cho chúng tôi. Như chúng ta sẽ thấy ở phần sau, một số tin nhắn là văn bản đơn giản, trong khi những tin nhắn khác là trả lời cho các nút (đừng lo lắng, điều này sẽ sớm có ý nghĩa!)message_id
là một chuỗi ký tự xác định duy nhất một tin nhắn mà chúng tôi đã nhận được. Điều này hữu ích khi chúng tôi muốn thực hiện các tác vụ cụ thể cho thư đó, chẳng hạn như đánh dấu thư là đã đọcCho đến thời điểm này, tất cả đều có vẻ ổn, nhưng chúng tôi sẽ xác nhận ngay sau đây.
Vì hướng dẫn của chúng tôi sẽ không đi sâu vào bất kỳ hình thức xử lý AI hoặc ngôn ngữ tự nhiên (NLP) nào, chúng tôi sẽ xác định luồng trò chuyện của mình bằng if…else
logic đơn giản.
Logic hội thoại bắt đầu khi khách hàng gửi tin nhắn văn bản. Chúng tôi sẽ không xem xét bản thân thông báo, vì vậy chúng tôi sẽ không biết họ định làm gì, nhưng chúng tôi có thể cho khách hàng biết bot của chúng tôi có thể làm gì.
Hãy cung cấp cho khách hàng một ngữ cảnh đơn giản để họ có thể trả lời với một mục đích cụ thể.
Chúng tôi sẽ cung cấp cho khách hàng hai nút:
Để thực hiện việc này, hãy chèn đoạn mã sau vào bên dưới message_id
:
if (typeOfMsg === 'text_message') {
await Whatsapp.sendSimpleButtons({
message: `Hey ${recipientName}, \nYou are speaking to a chatbot.\nWhat do you want to do next?`,
recipientPhone: recipientPhone,
listOfButtons: [
{
title: 'View some products',
id: 'see_categories',
},
{
title: 'Speak to a human',
id: 'speak_to_human',
},
],
});
}
Tuyên bố trên if
chỉ cho phép chúng tôi xử lý tin nhắn văn bản.
Phương sendSimpleButtons
pháp này cho phép chúng tôi gửi các nút tới khách hàng. Ghi chú về các thuộc tính title
và id
. Đó là những gì khách title
hàng sẽ thấy và id
là những gì chúng tôi sẽ sử dụng để biết khách hàng đã nhấp vào nút nào.
Hãy kiểm tra xem chúng tôi đã làm điều này đúng. Mở ứng dụng WhatsApp của bạn và gửi tin nhắn văn bản đến tài khoản doanh nghiệp WhatsApp.
Nếu bạn nhận được phản hồi như ảnh chụp màn hình ở trên, xin chúc mừng! Bạn vừa gửi tin nhắn đầu tiên của mình qua API đám mây WhatsApp.
Vì khách hàng có thể nhấp vào một trong hai nút, chúng ta hãy quan tâm đến nút Nói với một người .
Bên ngoài if
câu lệnh text_message
logic, hãy chèn đoạn mã sau:
if (typeOfMsg === 'simple_button_message') {
let button_id = incomingMessage.button_reply.id;
if (button_id === 'speak_to_human') {
await Whatsapp.sendText({
recipientPhone: recipientPhone,
message: `Arguably, chatbots are faster than humans.\nCall my human with the below details:`,
});
await Whatsapp.sendContact({
recipientPhone: recipientPhone,
contact_profile: {
addresses: [
{
city: 'Nairobi',
country: 'Kenya',
},
],
name: {
first_name: 'Daggie',
last_name: 'Blanqx',
},
org: {
company: 'Mom-N-Pop Shop',
},
phones: [
{
phone: '+1 (555) 025-3483',
},
{
phone: '+254712345678',
},
],
},
});
}
};
Đoạn mã trên thực hiện hai hành động:
sendText
phương pháp nàysendContact
phương thức nàyMã này cũng phát hiện ý định của người dùng bằng cách sử dụng ID của nút mà người dùng đã nhấp vào (trong trường hợp của chúng tôi, ID là incomingMessage.button_reply.id
), và sau đó nó phản hồi với hai tùy chọn hành động.
Bây giờ, quay lại WhatsApp và nhấp vào Nói chuyện với con người . Nếu bạn làm đúng, bạn sẽ thấy một câu trả lời như sau:
Khi bạn nhấp vào thẻ liên hệ bạn nhận được, bạn sẽ thấy như sau:
Tiếp theo, chúng ta hãy làm việc trên nút Xem một số sản phẩm .
Bên trong simple_button_message if
câu lệnh, nhưng ngay bên dưới và bên ngoài speak_to_human if
câu lệnh, hãy thêm đoạn mã sau:
if (button_id === 'see_categories') {
let categories = await Store.getAllCategories();
await Whatsapp.sendSimpleButtons({
message: `We have several categories.\nChoose one of them.`,
recipientPhone: recipientPhone,
listOfButtons: categories.data
.map((category) => ({
title: category,
id: `category_${category}`,
}))
.slice(0, 3)
});
}
Đây là những gì đoạn mã trên thực hiện:
if
dùng đã nhấp vào nút Xem một số sản phẩmFakeStoreAPI
phương getAllCategories
thứcslice(0,3)
- vì WhatsApp chỉ cho phép chúng tôi gửi ba nút đơn giảntitle
và một ID duy nhất được bắt đầu bằngcategory_
sendSimpleButtons
phương pháp, chúng tôi gửi các nút này cho khách hàngQuay lại ứng dụng WhatsApp của bạn một lần nữa và nhấp vào Xem các sản phẩm khác . Nếu bạn đã làm đúng các bước trên, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình bên dưới:
Bây giờ, chúng ta hãy tạo logic để có được sản phẩm trong danh mục mà khách hàng đã chọn.
Vẫn bên trong simple_button_message if
câu lệnh, nhưng bên dưới và bên ngoài see_categories if
câu lệnh, hãy thêm mã sau:
if (button_id.startsWith('category_')) {
let selectedCategory = button_id.split('category_')[1];
let listOfProducts = await Store.getProductsInCategory(selectedCategory);
let listOfSections = [
{
title: ` Top 3: ${selectedCategory}`.substring(0,24),
rows: listOfProducts.data
.map((product) => {
let id = `product_${product.id}`.substring(0,256);
let title = product.title.substring(0,21);
let description = `${product.price}\n${product.description}`.substring(0,68);
return {
id,
title: `${title}...`,
description: `$${description}...`
};
}).slice(0, 10)
},
];
await Whatsapp.sendRadioButtons({
recipientPhone: recipientPhone,
headerText: `#BlackFriday Offers: ${selectedCategory}`,
bodyText: `Our Santa has lined up some great products for you based on your previous shopping history.\n\nPlease select one of the products below:`,
footerText: 'Powered by: BMI LLC',
listOfSections,
});
}
if
Tuyên bố trên xác nhận rằng nút mà khách hàng nhấp vào thực sự là nút có chứa một danh mục .
Điều đầu tiên chúng tôi làm ở đây là trích xuất danh mục cụ thể từ ID của nút. Sau đó, chúng tôi truy vấn FakeStoreAPI của chúng tôi để tìm các sản phẩm thuộc danh mục cụ thể đó.
Sau khi truy vấn, chúng tôi nhận được danh sách các sản phẩm bên trong một mảng , listOfProducts.data
. Bây giờ chúng tôi lặp lại mảng này và đối với mỗi sản phẩm trong đó, chúng tôi trích xuất giá, tiêu đề, mô tả và ID của nó.
Chúng tôi thêm product_
vào id
, điều này sẽ giúp chúng tôi chọn lựa của khách hàng trong bước tiếp theo. Đảm bảo bạn cắt bớt độ dài của ID, tiêu đề và mô tả theo các hạn chế về nút radio (hoặc danh sách) của WhatsApp Cloud API .
Sau đó, chúng tôi trả về ba giá trị: ID, tiêu đề và mô tả. Vì WhatsApp chỉ cho phép chúng tôi tối đa 10 hàng, chúng tôi sẽ giới hạn số lượng sản phẩm là 10 bằng cách sử dụng phương pháp mảng .slice(0,10)
.
Sau đó, chúng tôi gọi sendRadioButtons
phương thức để gửi sản phẩm cho khách hàng. Ghi lại các thuộc tính , và . headerTextbodyTextfooterTextlistOfSections
Quay lại ứng dụng WhatsApp và nhấp vào bất kỳ danh mục sản phẩm nào. Nếu bạn đã làm theo đúng hướng dẫn, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình bên dưới:
Khi bạn nhấp vào Chọn một sản phẩm , bạn sẽ thấy màn hình sau:
Tại thời điểm này, khách hàng có thể chọn một sản phẩm mà họ cảm thấy thú vị, nhưng liệu chúng ta có thể biết họ đã chọn những gì? Vẫn chưa, vì vậy hãy để chúng tôi làm việc trên phần này.
Bên ngoài simple_button_message if
câu lệnh, hãy để chúng tôi thêm một if
câu lệnh khác:
if (typeOfMsg === 'radio_button_message') {
let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
}
Bên trong if
câu lệnh trên và ngay bên dưới câu lệnh selectionId
, hãy thêm đoạn mã sau:
if (selectionId.startsWith('product_')) {
let product_id = selectionId.split('_')[1];
let product = await Store.getProductById(product_id);
const { price, title, description, category, image: imageUrl, rating } = product.data;
let emojiRating = (rvalue) => {
rvalue = Math.floor(rvalue || 0); // generate as many star emojis as whole number ratings
let output = [];
for (var i = 0; i < rvalue; i++) output.push('');
return output.length ? output.join('') : 'N/A';
};
let text = `_Title_: *${title.trim()}*\n\n\n`;
text += `_Description_: ${description.trim()}\n\n\n`;
text += `_Price_: $${price}\n`;
text += `_Category_: ${category}\n`;
text += `${rating?.count || 0} shoppers liked this product.\n`;
text += `_Rated_: ${emojiRating(rating?.rate)}\n`;
await Whatsapp.sendImage({
recipientPhone,
url: imageUrl,
caption: text,
});
await Whatsapp.sendSimpleButtons({
message: `Here is the product, what do you want to do next?`,
recipientPhone: recipientPhone,
listOfButtons: [
{
title: 'Add to cart',
id: `add_to_cart_${product_id}`,
},
{
title: 'Speak to a human',
id: 'speak_to_human',
},
{
title: 'See more products',
id: 'see_categories',
},
],
});
}
Đoạn mã trên thực hiện những việc sau:
emojiRating
chức năng. Nếu xếp hạng là 3,8, nó sẽ hiển thị biểu tượng cảm xúc ba saosendImage
phương thứcSau đó, chúng tôi gửi cho khách hàng danh sách ba nút bằng cách sử dụng sendSimpleButtons
. Một cung cấp cho khách hàng cơ hội để thêm sản phẩm vào giỏ hàng của họ. Hãy lưu ý đến ID của nút có tiền tố add_to_cart_
.
Bây giờ, quay lại ứng dụng WhatsApp của bạn và chọn một sản phẩm. Nếu bạn đã làm theo đúng hướng dẫn, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình sau:
Để theo dõi các sản phẩm mà khách hàng thêm vào giỏ hàng của họ, chúng tôi cần có một nơi để lưu trữ các mặt hàng trong giỏ hàng. Đây là nơi CustomerSession
phát huy tác dụng. Hãy thêm một số logic vào nó.
Bên ngoài radio_button_message if
câu lệnh và ngay bên dưới phần message_id
khai báo, hãy thêm đoạn mã sau:
let message_id = incomingMessage.message_id; // This line already exists. Add the below lines...
// Start of cart logic
if (!CustomerSession.get(recipientPhone)) {
CustomerSession.set(recipientPhone, {
cart: [],
});
}
let addToCart = async ({ product_id, recipientPhone }) => {
let product = await Store.getProductById(product_id);
if (product.status === 'success') {
CustomerSession.get(recipientPhone).cart.push(product.data);
}
};
let listOfItemsInCart = ({ recipientPhone }) => {
let total = 0;
let products = CustomerSession.get(recipientPhone).cart;
total = products.reduce(
(acc, product) => acc + product.price,
total
);
let count = products.length;
return { total, products, count };
};
let clearCart = ({ recipientPhone }) => {
CustomerSession.get(recipientPhone).cart = [];
};
// End of cart logic
if (typeOfMsg === 'text_message') { ... // This line already exists. Add the above lines...
Đoạn mã trên kiểm tra xem phiên của khách hàng đã được tạo hay chưa. Nếu nó chưa được tạo, nó sẽ tạo một phiên mới được nhận dạng duy nhất bởi số điện thoại của khách hàng. Sau đó, chúng tôi khởi tạo một thuộc tính được gọi cart
, bắt đầu dưới dạng một mảng trống.
Hàm addToCart
nhận a product_id
và số lượng khách hàng cụ thể. Sau đó, nó ping FakeStoreAPI để biết dữ liệu của sản phẩm cụ thể và đẩy sản phẩm vào cart
mảng.
Sau đó, listOfItemsInCart
hàm này lấy số điện thoại của khách hàng và truy xuất số điện thoại được liên kết cart
, được sử dụng để tính số lượng sản phẩm trong giỏ hàng và tổng giá của chúng. Cuối cùng, nó trả về các mặt hàng trong giỏ hàng và tổng giá của chúng.
Chức clearCart
năng lấy số điện thoại của khách hàng và chuyển vào giỏ hàng của khách hàng đó.
Với logic giỏ hàng được thực hiện, hãy xây dựng nút Thêm vào giỏ hàng . Bên trong simple_button_message if
câu lệnh và bên dưới phần button_id
khai báo, hãy thêm đoạn mã sau:
if (button_id.startsWith('add_to_cart_')) {
let product_id = button_id.split('add_to_cart_')[1];
await addToCart({ recipientPhone, product_id });
let numberOfItemsInCart = listOfItemsInCart({ recipientPhone }).count;
await Whatsapp.sendSimpleButtons({
message: `Your cart has been updated.\nNumber of items in cart: ${numberOfItemsInCart}.\n\nWhat do you want to do next?`,
recipientPhone: recipientPhone,
listOfButtons: [
{
title: 'Checkout ',
id: `checkout`,
},
{
title: 'See more products',
id: 'see_categories',
},
],
});
}
Đoạn mã trên trích xuất ID sản phẩm từ nút khách hàng nhấp vào, sau đó gọi addToCart
chức năng lưu sản phẩm vào giỏ hàng của phiên khách hàng. Sau đó, nó trích xuất số lượng mặt hàng trong giỏ hàng của phiên của khách hàng và cho khách hàng biết họ có bao nhiêu sản phẩm. Nó cũng gửi hai nút, một trong số đó cho phép người dùng kiểm tra.
Ghi lại ID nút và quay lại ứng dụng WhatsApp của bạn. Nhấp vào Thêm vào giỏ hàng . Nếu bạn làm theo đúng hướng dẫn, bạn sẽ thấy câu trả lời giống như ảnh chụp màn hình bên dưới:
Bây giờ khách hàng của chúng tôi có thể thêm các mặt hàng vào giỏ hàng, chúng tôi có thể viết logic để thanh toán.
Bên trong simple_button_message if
câu lệnh nhưng bên ngoài add_to_cart_ if
câu lệnh, hãy thêm đoạn mã sau:
if (button_id === 'checkout') {
let finalBill = listOfItemsInCart({ recipientPhone });
let invoiceText = `List of items in your cart:\n`;
finalBill.products.forEach((item, index) => {
let serial = index + 1;
invoiceText += `\n#${serial}: ${item.title} @ $${item.price}`;
});
invoiceText += `\n\nTotal: $${finalBill.total}`;
Store.generatePDFInvoice({
order_details: invoiceText,
file_path: `./invoice_${recipientName}.pdf`,
});
await Whatsapp.sendText({
message: invoiceText,
recipientPhone: recipientPhone,
});
await Whatsapp.sendSimpleButtons({
recipientPhone: recipientPhone,
message: `Thank you for shopping with us, ${recipientName}.\n\nYour order has been received & will be processed shortly.`,
message_id,
listOfButtons: [
{
title: 'See more products',
id: 'see_categories',
},
{
title: 'Print my invoice',
id: 'print_invoice',
},
],
});
clearCart({ recipientPhone });
}
Đoạn mã trên thực hiện những việc sau:
finalBill
invoiceText
, biến này sẽ chứa văn bản mà chúng tôi sẽ gửi cho khách hàng cũng như văn bản sẽ được soạn thảo thành phiên bản PDF của hóa đơnforEach
lặp chỉ đơn giản là nối title
và price
của từng sản phẩm với hóa đơngeneratePDFInvoice
thức (giống phương thức mà chúng tôi đã xác định trong EcommerceStore
lớp của mình) lấy chi tiết của đơn đặt hàng, soạn thảo tài liệu PDF và lưu nó vào đường dẫn tệp trong thư mục / thư mục cục bộ mà chúng tôi đã cung cấpsendText
thức gửi một tin nhắn văn bản đơn giản chứa thông tin chi tiết về đơn đặt hàng cho khách hàngsendSimpleButtons
gửi một số nút cho khách hàng. Hãy lưu ý đến nút In hóa đơn của tôi và ID của nóclearCart
phương pháp làm trống giỏ hàngBây giờ, hãy quay lại ứng dụng WhatsApp của bạn và nhấp vào Thanh toán . Nếu bạn làm theo đúng hướng dẫn, bạn sẽ thấy một câu trả lời giống như ảnh chụp màn hình sau:
Tại thời điểm này, khách hàng sẽ nhận được hóa đơn PDF có thể in được. Vì lý do này, hãy để chúng tôi làm việc trên một số logic liên quan đến nút In hóa đơn của tôi .
Bên trong simple_button_message if
câu lệnh nhưng bên ngoài checkout if
câu lệnh, hãy thêm đoạn mã sau:
if (button_id === 'print_invoice') {
// Send the PDF invoice
await Whatsapp.sendDocument({
recipientPhone: recipientPhone,
caption:`Mom-N-Pop Shop invoice #${recipientName}`
file_path: `./invoice_${recipientName}.pdf`,
});
// Send the location of our pickup station to the customer, so they can come and pick up their order
let warehouse = Store.generateRandomGeoLocation();
await Whatsapp.sendText({
recipientPhone: recipientPhone,
message: `Your order has been fulfilled. Come and pick it up, as you pay, here:`,
});
await Whatsapp.sendLocation({
recipientPhone,
latitude: warehouse.latitude,
longitude: warehouse.longitude,
address: warehouse.address,
name: 'Mom-N-Pop Shop',
});
}
Đoạn mã trên lấy tài liệu PDF được tạo ở bước trước từ hệ thống tệp cục bộ và gửi cho khách hàng bằng sendDocument
phương pháp này.
Khi một khách hàng đặt mua một sản phẩm trực tuyến, họ cũng cần biết họ sẽ nhận được sản phẩm vật chất như thế nào. Vì lý do này, chúng tôi đã tạo một số tọa độ ngẫu nhiên bằng cách sử dụng generateRandomGeoLocation
phương thức của EcommerceStore
lớp và gửi các tọa độ này cho khách hàng bằng sendLocation
phương pháp này để cho họ biết nơi họ có thể lấy sản phẩm của mình.
Bây giờ, hãy mở ứng dụng WhatsApp của bạn và nhấp vào In hóa đơn của tôi .
Nếu bạn đã làm theo đúng hướng dẫn ở trên, bạn sẽ thấy câu trả lời giống với ảnh chụp màn hình bên dưới:
Cuối cùng, bạn có thể nhận thấy rằng các dấu kiểm bên dưới thư có màu xám thay vì màu xanh lam. Điều này cho thấy rằng các tin nhắn chúng tôi đã gửi không trả lại các xác nhận đã đọc mặc dù thực tế là bot của chúng tôi đang đọc chúng.
Những con bọ màu xám có thể gây khó chịu cho khách hàng và vì lý do này, chúng tôi cần làm việc để hiển thị những con bọ màu xanh lam.
Bên ngoài simple_button_message if
câu lệnh và trước dấu ngoặc nhọn đóng của data?.isMessage if
câu lệnh, hãy thêm đoạn mã sau:
await Whatsapp.markMessageAsRead({ message_id });
Một dòng chữ đơn giản này đánh dấu một tin nhắn được đọc ngay sau khi chúng tôi trả lời nó.
Bây giờ, hãy mở ứng dụng WhatsApp của bạn và gửi một tin nhắn văn bản ngẫu nhiên. Bạn có thấy những gì tôi đang thấy không?
Nếu các cuộc trò chuyện trước đó của bạn đã được cập nhật bằng dấu tích màu xanh, thì xin chúc mừng! Bạn đã xem đến phần cuối của hướng dẫn này và học được một số điều trong suốt quá trình.
Với tổng số 2 tỷ người dùng hoạt động hàng tháng, việc bỏ qua WhatsApp như một chiến lược thương mại điện tử là một cách chắc chắn để tụt hậu so với đối thủ cạnh tranh của doanh nghiệp bạn và vì hầu hết khách hàng của bạn đã sử dụng WhatsApp trong các hoạt động hàng ngày của họ, tại sao không nên ' doanh nghiệp của bạn có gặp họ ở đó không?
Tôi hy vọng hướng dẫn này sẽ hữu ích trong việc làm sáng tỏ API đám mây WhatsApp và tôi hy vọng bạn đã có một chút thú vị trong suốt quá trình này. Hãy cho tôi biết những chủ đề khác mà bạn có thể thấy thú vị và đừng quên chia sẻ bài viết này với giới công nghệ của bạn.
Nguồn: https://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/
1594162500
A multi-cloud approach is nothing but leveraging two or more cloud platforms for meeting the various business requirements of an enterprise. The multi-cloud IT environment incorporates different clouds from multiple vendors and negates the dependence on a single public cloud service provider. Thus enterprises can choose specific services from multiple public clouds and reap the benefits of each.
Given its affordability and agility, most enterprises opt for a multi-cloud approach in cloud computing now. A 2018 survey on the public cloud services market points out that 81% of the respondents use services from two or more providers. Subsequently, the cloud computing services market has reported incredible growth in recent times. The worldwide public cloud services market is all set to reach $500 billion in the next four years, according to IDC.
By choosing multi-cloud solutions strategically, enterprises can optimize the benefits of cloud computing and aim for some key competitive advantages. They can avoid the lengthy and cumbersome processes involved in buying, installing and testing high-priced systems. The IaaS and PaaS solutions have become a windfall for the enterprise’s budget as it does not incur huge up-front capital expenditure.
However, cost optimization is still a challenge while facilitating a multi-cloud environment and a large number of enterprises end up overpaying with or without realizing it. The below-mentioned tips would help you ensure the money is spent wisely on cloud computing services.
Most organizations tend to get wrong with simple things which turn out to be the root cause for needless spending and resource wastage. The first step to cost optimization in your cloud strategy is to identify underutilized resources that you have been paying for.
Enterprises often continue to pay for resources that have been purchased earlier but are no longer useful. Identifying such unused and unattached resources and deactivating it on a regular basis brings you one step closer to cost optimization. If needed, you can deploy automated cloud management tools that are largely helpful in providing the analytics needed to optimize the cloud spending and cut costs on an ongoing basis.
Another key cost optimization strategy is to identify the idle computing instances and consolidate them into fewer instances. An idle computing instance may require a CPU utilization level of 1-5%, but you may be billed by the service provider for 100% for the same instance.
Every enterprise will have such non-production instances that constitute unnecessary storage space and lead to overpaying. Re-evaluating your resource allocations regularly and removing unnecessary storage may help you save money significantly. Resource allocation is not only a matter of CPU and memory but also it is linked to the storage, network, and various other factors.
The key to efficient cost reduction in cloud computing technology lies in proactive monitoring. A comprehensive view of the cloud usage helps enterprises to monitor and minimize unnecessary spending. You can make use of various mechanisms for monitoring computing demand.
For instance, you can use a heatmap to understand the highs and lows in computing visually. This heat map indicates the start and stop times which in turn lead to reduced costs. You can also deploy automated tools that help organizations to schedule instances to start and stop. By following a heatmap, you can understand whether it is safe to shut down servers on holidays or weekends.
#cloud computing services #all #hybrid cloud #cloud #multi-cloud strategy #cloud spend #multi-cloud spending #multi cloud adoption #why multi cloud #multi cloud trends #multi cloud companies #multi cloud research #multi cloud market
1595396220
As more and more data is exposed via APIs either as API-first companies or for the explosion of single page apps/JAMStack, API security can no longer be an afterthought. The hard part about APIs is that it provides direct access to large amounts of data while bypassing browser precautions. Instead of worrying about SQL injection and XSS issues, you should be concerned about the bad actor who was able to paginate through all your customer records and their data.
Typical prevention mechanisms like Captchas and browser fingerprinting won’t work since APIs by design need to handle a very large number of API accesses even by a single customer. So where do you start? The first thing is to put yourself in the shoes of a hacker and then instrument your APIs to detect and block common attacks along with unknown unknowns for zero-day exploits. Some of these are on the OWASP Security API list, but not all.
Most APIs provide access to resources that are lists of entities such as /users
or /widgets
. A client such as a browser would typically filter and paginate through this list to limit the number items returned to a client like so:
First Call: GET /items?skip=0&take=10
Second Call: GET /items?skip=10&take=10
However, if that entity has any PII or other information, then a hacker could scrape that endpoint to get a dump of all entities in your database. This could be most dangerous if those entities accidently exposed PII or other sensitive information, but could also be dangerous in providing competitors or others with adoption and usage stats for your business or provide scammers with a way to get large email lists. See how Venmo data was scraped
A naive protection mechanism would be to check the take count and throw an error if greater than 100 or 1000. The problem with this is two-fold:
skip = 0
while True: response = requests.post('https://api.acmeinc.com/widgets?take=10&skip=' + skip), headers={'Authorization': 'Bearer' + ' ' + sys.argv[1]}) print("Fetched 10 items") sleep(randint(100,1000)) skip += 10
To secure against pagination attacks, you should track how many items of a single resource are accessed within a certain time period for each user or API key rather than just at the request level. By tracking API resource access at the user level, you can block a user or API key once they hit a threshold such as “touched 1,000,000 items in a one hour period”. This is dependent on your API use case and can even be dependent on their subscription with you. Like a Captcha, this can slow down the speed that a hacker can exploit your API, like a Captcha if they have to create a new user account manually to create a new API key.
Most APIs are protected by some sort of API key or JWT (JSON Web Token). This provides a natural way to track and protect your API as API security tools can detect abnormal API behavior and block access to an API key automatically. However, hackers will want to outsmart these mechanisms by generating and using a large pool of API keys from a large number of users just like a web hacker would use a large pool of IP addresses to circumvent DDoS protection.
The easiest way to secure against these types of attacks is by requiring a human to sign up for your service and generate API keys. Bot traffic can be prevented with things like Captcha and 2-Factor Authentication. Unless there is a legitimate business case, new users who sign up for your service should not have the ability to generate API keys programmatically. Instead, only trusted customers should have the ability to generate API keys programmatically. Go one step further and ensure any anomaly detection for abnormal behavior is done at the user and account level, not just for each API key.
APIs are used in a way that increases the probability credentials are leaked:
If a key is exposed due to user error, one may think you as the API provider has any blame. However, security is all about reducing surface area and risk. Treat your customer data as if it’s your own and help them by adding guards that prevent accidental key exposure.
The easiest way to prevent key exposure is by leveraging two tokens rather than one. A refresh token is stored as an environment variable and can only be used to generate short lived access tokens. Unlike the refresh token, these short lived tokens can access the resources, but are time limited such as in hours or days.
The customer will store the refresh token with other API keys. Then your SDK will generate access tokens on SDK init or when the last access token expires. If a CURL command gets pasted into a GitHub issue, then a hacker would need to use it within hours reducing the attack vector (unless it was the actual refresh token which is low probability)
APIs open up entirely new business models where customers can access your API platform programmatically. However, this can make DDoS protection tricky. Most DDoS protection is designed to absorb and reject a large number of requests from bad actors during DDoS attacks but still need to let the good ones through. This requires fingerprinting the HTTP requests to check against what looks like bot traffic. This is much harder for API products as all traffic looks like bot traffic and is not coming from a browser where things like cookies are present.
The magical part about APIs is almost every access requires an API Key. If a request doesn’t have an API key, you can automatically reject it which is lightweight on your servers (Ensure authentication is short circuited very early before later middleware like request JSON parsing). So then how do you handle authenticated requests? The easiest is to leverage rate limit counters for each API key such as to handle X requests per minute and reject those above the threshold with a 429 HTTP response.
There are a variety of algorithms to do this such as leaky bucket and fixed window counters.
APIs are no different than web servers when it comes to good server hygiene. Data can be leaked due to misconfigured SSL certificate or allowing non-HTTPS traffic. For modern applications, there is very little reason to accept non-HTTPS requests, but a customer could mistakenly issue a non HTTP request from their application or CURL exposing the API key. APIs do not have the protection of a browser so things like HSTS or redirect to HTTPS offer no protection.
Test your SSL implementation over at Qualys SSL Test or similar tool. You should also block all non-HTTP requests which can be done within your load balancer. You should also remove any HTTP headers scrub any error messages that leak implementation details. If your API is used only by your own apps or can only be accessed server-side, then review Authoritative guide to Cross-Origin Resource Sharing for REST APIs
APIs provide access to dynamic data that’s scoped to each API key. Any caching implementation should have the ability to scope to an API key to prevent cross-pollution. Even if you don’t cache anything in your infrastructure, you could expose your customers to security holes. If a customer with a proxy server was using multiple API keys such as one for development and one for production, then they could see cross-pollinated data.
#api management #api security #api best practices #api providers #security analytics #api management policies #api access tokens #api access #api security risks #api access keys
1601381326
We’ve conducted some initial research into the public APIs of the ASX100 because we regularly have conversations about what others are doing with their APIs and what best practices look like. Being able to point to good local examples and explain what is happening in Australia is a key part of this conversation.
The method used for this initial research was to obtain a list of the ASX100 (as of 18 September 2020). Then work through each company looking at the following:
With regards to how the APIs are shared:
#api #api-development #api-analytics #apis #api-integration #api-testing #api-security #api-gateway
1594166040
The moving of applications, databases and other business elements from the local server to the cloud server called cloud migration. This article will deal with migration techniques, requirement and the benefits of cloud migration.
In simple terms, moving from local to the public cloud server is called cloud migration. Gartner says 17.5% revenue growth as promised in cloud migration and also has a forecast for 2022 as shown in the following image.
#cloud computing services #cloud migration #all #cloud #cloud migration strategy #enterprise cloud migration strategy #business benefits of cloud migration #key benefits of cloud migration #benefits of cloud migration #types of cloud migration