precil james86

1667393716

CELPIP Certificate Without Exam In UK, Australia, Canada,Greece.....

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Certificate without exam, Buy Registered GRE Certificate,Buy IELTS certificates without exam, Buy valid IELTS certificates,Buy GRE Certificate without exam, Buy GRE certificate online, IELTS certificates for sale.Buy IELTS certificate online, Buy TOEFL certificate online, Buy GRE Certificate Online, Buy GRE Certificate without exam, Buy GMAT Certificate Online, Buy CAE certificate online, IELTS Certificate for sale, Buy GRE certificate online, Buy CAE certificate without exam,Buy a Registered TOEFL certificate, Buy a GRE certificate without exam, Buy TOEFL Certificate without an exam.#ielts #ielts #exams #india #certificate #delhi #dubai #online #get #real #gmat #pte #esol #gre #toefl #toeic #sat #kuwaitwww.buylanguagecertificates.com#genuine #lebanon #abudhabi #pmp #saudiarabia #uae #test #australia #uk #peru #canada #authentic #qatar #singapore #egypt #spain #sydney #brazil #italy #cae #valid #score #oman #registered #punjab #kerala #chennai #hyderabad #nepal #mumbai #howto #whatsapp #email #verified #inabudhabi #without #original #exam #buy #band #modify #skype #yahoo #celpip #ielts #pteinindia #buyptecertificate #obtainieltsonline #buycelpip #celpiponline #ptetestdate #pteexam #ieltstest.


Buy CISSP certificate Online – USA
Need Real CISSP certificate for sale –INDIA
Get original CISSP certificate without Exam – SAUDI ARABIA
I want CISSP Certificate – CANADA
Buy registered CISSP Certificate – UAE
CISSP certificate for sale –UK
BUY Systems Security Certified Practitioner (SSCP) IN TORONTO
BUY Certified Information Systems Security Professional (CISSP) IN ARIZONA
BUY Certified Authorization Professional (CAP) IN NEW YORK
BUY Certified Secure Software Lifecycle Professional (CSSLP) IN HOUSTON
BUY HealthCare Information Security and Privacy Practitioner (HCISPP)OHIO

Buy original Celpip Certificate Without Exam in Jersey
Buy original Celpip Certificate Without Exam in Saudi Arabia
Buy original Celpip Certificate Without Exam in Canada
Buy CELPIP Certificate Without Exam in Peru
Buy Celpip Certificate Without Exam in Mexico
Buy CELPIP Certificate Without Exam in Turkey
Buy CELIPIP Certificate Without Exam in Qatar
Buy Celpip Certificate Without Exam in Australia
buy TOEFL certificate without exam in Spain
buy CELPIP certificate without exam in Canada
buy NEOSH certificate without exam in Hong Kong
buy Celpip certificate without exam in Ukraine
buy Celpip certificate without exam in Vietnam
buy IELTS certificate without exam in China

Contact Details:(onlinedocuments100@outlook.com)
www.buylanguagecertificates.com
General support:(verifiedielts770@yahoo.com)
WhatsApp::(+1 773 922-0936)

CELPIP Certificate Without Exam In UK,   Australia, Canada,Greece.....

precil james86

1667393357

(onlinedocuments100@outlook.com)Buy Real Verified IELTS / B.C.A / PTE

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Certificate without exam, Buy Registered GRE Certificate,Buy IELTS certificates without exam, Buy valid IELTS certificates,Buy GRE Certificate without exam, Buy GRE certificate online, IELTS certificates for sale.Buy IELTS certificate online, Buy TOEFL certificate online, Buy GRE Certificate Online, Buy GRE Certificate without exam, Buy GMAT Certificate Online, Buy CAE certificate online, IELTS Certificate for sale, Buy GRE certificate online, Buy CAE certificate without exam,Buy a Registered TOEFL certificate, Buy a GRE certificate without exam, Buy TOEFL Certificate without an exam.#ielts #ielts #exams #india #certificate #delhi #dubai #online #get #real #gmat #pte #esol #gre #toefl #toeic #sat #kuwaitwww.buylanguagecertificates.com#genuine #lebanon #abudhabi #pmp #saudiarabia #uae #test #australia #uk #peru #canada #authentic #qatar #singapore #egypt #spain #sydney #brazil #italy #cae #valid #score #oman #registered #punjab #kerala #chennai #hyderabad #nepal #mumbai #howto #whatsapp #email #verified #inabudhabi #without #original #exam #buy #band #modify #skype #yahoo #celpip #ielts #pteinindia #buyptecertificate #obtainieltsonline #buycelpip #celpiponline #ptetestdate #pteexam #ieltstest.


Buy CISSP certificate Online – USA
Need Real CISSP certificate for sale –INDIA
Get original CISSP certificate without Exam – SAUDI ARABIA
I want CISSP Certificate – CANADA
Buy registered CISSP Certificate – UAE
CISSP certificate for sale –UK
BUY Systems Security Certified Practitioner (SSCP) IN TORONTO
BUY Certified Information Systems Security Professional (CISSP) IN ARIZONA
BUY Certified Authorization Professional (CAP) IN NEW YORK
BUY Certified Secure Software Lifecycle Professional (CSSLP) IN HOUSTON
BUY HealthCare Information Security and Privacy Practitioner (HCISPP)OHIO

Buy original Celpip Certificate Without Exam in Jersey
Buy original Celpip Certificate Without Exam in Saudi Arabia
Buy original Celpip Certificate Without Exam in Canada
Buy CELPIP Certificate Without Exam in Peru
Buy Celpip Certificate Without Exam in Mexico
Buy CELPIP Certificate Without Exam in Turkey
Buy CELIPIP Certificate Without Exam in Qatar
Buy Celpip Certificate Without Exam in Australia
buy TOEFL certificate without exam in Spain
buy CELPIP certificate without exam in Canada
buy NEOSH certificate without exam in Hong Kong
buy Celpip certificate without exam in Ukraine
buy Celpip certificate without exam in Vietnam
buy IELTS certificate without exam in China

Contact Details:(onlinedocuments100@outlook.com)
www.buylanguagecertificates.com
General support:(verifiedielts770@yahoo.com)
WhatsApp::(+1 773 922-0936)

(onlinedocuments100@outlook.com)Buy Real Verified IELTS / B.C.A / PTE

precil james86

1667391491

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Ce

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Certificate without exam, Buy Registered GRE Certificate,Buy IELTS certificates without exam, Buy valid IELTS certificates,Buy GRE Certificate without exam, Buy GRE certificate online, IELTS certificates for sale.Buy IELTS certificate online, Buy TOEFL certificate online, Buy GRE Certificate Online, Buy GRE Certificate without exam, Buy GMAT Certificate Online, Buy CAE certificate online, IELTS Certificate for sale, Buy GRE certificate online, Buy CAE certificate without exam,Buy a Registered TOEFL certificate, Buy a GRE certificate without exam, Buy TOEFL Certificate without an exam.#ielts #ielts #exams #india #certificate #delhi #dubai #online #get #real #gmat #pte #esol #gre #toefl #toeic #sat #kuwaitwww.buylanguagecertificates.com#genuine #lebanon #abudhabi #pmp #saudiarabia #uae #test #australia #uk #peru #canada #authentic #qatar #singapore #egypt #spain #sydney #brazil #italy #cae #valid #score #oman #registered #punjab #kerala #chennai #hyderabad #nepal #mumbai #howto #whatsapp #email #verified #inabudhabi #without #original #exam #buy #band #modify #skype #yahoo #celpip #ielts #pteinindia #buyptecertificate #obtainieltsonline #buycelpip #celpiponline #ptetestdate #pteexam #ieltstest.


Buy CISSP certificate Online – USA
Need Real CISSP certificate for sale –INDIA
Get original CISSP certificate without Exam – SAUDI ARABIA
I want CISSP Certificate – CANADA
Buy registered CISSP Certificate – UAE
CISSP certificate for sale –UK
BUY Systems Security Certified Practitioner (SSCP) IN TORONTO
BUY Certified Information Systems Security Professional (CISSP) IN ARIZONA
BUY Certified Authorization Professional (CAP) IN NEW YORK
BUY Certified Secure Software Lifecycle Professional (CSSLP) IN HOUSTON
BUY HealthCare Information Security and Privacy Practitioner (HCISPP)OHIO

Buy original Celpip Certificate Without Exam in Jersey
Buy original Celpip Certificate Without Exam in Saudi Arabia
Buy original Celpip Certificate Without Exam in Canada
Buy CELPIP Certificate Without Exam in Peru
Buy Celpip Certificate Without Exam in Mexico
Buy CELPIP Certificate Without Exam in Turkey
Buy CELIPIP Certificate Without Exam in Qatar
Buy Celpip Certificate Without Exam in Australia
buy TOEFL certificate without exam in Spain
buy CELPIP certificate without exam in Canada
buy NEOSH certificate without exam in Hong Kong
buy Celpip certificate without exam in Ukraine
buy Celpip certificate without exam in Vietnam
buy IELTS certificate without exam in China

Contact Details:(onlinedocuments100@outlook.com)
www.buylanguagecertificates.com
General support:(verifiedielts770@yahoo.com)
WhatsApp::(+1 773 922-0936)

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Ce

precil james86

1667391022

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Ce

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Certificate without exam, Buy Registered GRE Certificate,Buy IELTS certificates without exam, Buy valid IELTS certificates,Buy GRE Certificate without exam, Buy GRE certificate online, IELTS certificates for sale.Buy IELTS certificate online, Buy TOEFL certificate online, Buy GRE Certificate Online, Buy GRE Certificate without exam, Buy GMAT Certificate Online, Buy CAE certificate online, IELTS Certificate for sale, Buy GRE certificate online, Buy CAE certificate without exam,Buy a Registered TOEFL certificate, Buy a GRE certificate without exam, Buy TOEFL Certificate without an exam.#ielts #ielts #exams #india #certificate #delhi #dubai #online #get #real #gmat #pte #esol #gre #toefl #toeic #sat #kuwaitwww.buylanguagecertificates.com#genuine #lebanon #abudhabi #pmp #saudiarabia #uae #test #australia #uk #peru #canada #authentic #qatar #singapore #egypt #spain #sydney #brazil #italy #cae #valid #score #oman #registered #punjab #kerala #chennai #hyderabad #nepal #mumbai #howto #whatsapp #email #verified #inabudhabi #without #original #exam #buy #band #modify #skype #yahoo #celpip #ielts #pteinindia #buyptecertificate #obtainieltsonline #buycelpip #celpiponline #ptetestdate #pteexam #ieltstest.


Buy CISSP certificate Online – USA
Need Real CISSP certificate for sale –INDIA
Get original CISSP certificate without Exam – SAUDI ARABIA
I want CISSP Certificate – CANADA
Buy registered CISSP Certificate – UAE
CISSP certificate for sale –UK
BUY Systems Security Certified Practitioner (SSCP) IN TORONTO
BUY Certified Information Systems Security Professional (CISSP) IN ARIZONA
BUY Certified Authorization Professional (CAP) IN NEW YORK
BUY Certified Secure Software Lifecycle Professional (CSSLP) IN HOUSTON
BUY HealthCare Information Security and Privacy Practitioner (HCISPP)OHIO

Buy original Celpip Certificate Without Exam in Jersey
Buy original Celpip Certificate Without Exam in Saudi Arabia
Buy original Celpip Certificate Without Exam in Canada
Buy CELPIP Certificate Without Exam in Peru
Buy Celpip Certificate Without Exam in Mexico
Buy CELPIP Certificate Without Exam in Turkey
Buy CELIPIP Certificate Without Exam in Qatar
Buy Celpip Certificate Without Exam in Australia
buy TOEFL certificate without exam in Spain
buy CELPIP certificate without exam in Canada
buy NEOSH certificate without exam in Hong Kong
buy Celpip certificate without exam in Ukraine
buy Celpip certificate without exam in Vietnam
buy IELTS certificate without exam in China

Contact Details:(onlinedocuments100@outlook.com)
www.buylanguagecertificates.com
General support:(verifiedielts770@yahoo.com)
WhatsApp::(+1 773 922-0936)

(onlinedocuments100@outlook.com)Buy GRE certificate online, Buy GRE Ce
Teagan  Taylor

Teagan Taylor

1666836780

WhatsApp UI Clone using NextJS and TypeScript

🔗 Web WhatsApp - UI Clone

🚀 Web apllication (Web WhatsApp) developed using NextJS + TypeScript + TailwindCSS technologies.

Running

🧭 Running in a browser (Frontend)


# Clone this repository
$ git clone git@github.com:wallacefreitas/web-whatsapp-ui-clone.git

# Access the folder project in your terminal/cmd
$ cd web-whatsapp-ui-clone

# Install the dependencies
$ npm install

# Run  the application in development mode
$ npm run start

# The application will open in port:3000 - go to http://localhost:3000

🛠 Technologies

The following tools were used in building the project:

Website (React JS + TypeScript)

See the file package.json


📷 Screenshots

Screenshot memory game 


.gitignore

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
}

module.exports = nextConfig

package.json

{
  "name": "web-whatsapp-ui-clone",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "12.2.5",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "devDependencies": {
    "@types/node": "18.7.5",
    "@types/react": "18.0.17",
    "@types/react-dom": "18.0.6",
    "autoprefixer": "^10.4.8",
    "eslint": "8.22.0",
    "eslint-config-next": "12.2.5",
    "postcss": "^8.4.16",
    "tailwindcss": "^3.1.8",
    "typescript": "4.7.4"
  }
}

postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
    fontFamily: {
      sans: 'Segoe UI, Helvetica Neue, Helvetica, Lucida Grande, Arial, Ubuntu, Cantarell, Fira Sans, sans-serif',
    },
    container: {
      center: true,
    }
  },
  plugins: [],
}

Download Details:

Author: wallacefreitas
Source Code: https://github.com/wallacefreitas/web-whatsapp-ui-clone

#whatsapp  #nextjs   #typescript 

WhatsApp UI Clone using NextJS and TypeScript

WhatsApp Clone with REACT and Firebase

WhatsApp Clone with REACT JS

🔴 LIVE DEMO

PREREQUISITES:

  • Sign up for a Firebase account HERE
  • Install Node JS in your computer HERE

This project was bootstrapped with Create React App.

Available Scripts

npx create-react-app whatsapp-clone
cd whatsapp-clone

In the project directory, you can run:

npm start

Runs the app in the development mode.
Open http://localhost:3000 to view it in your browser.

The page will reload when you make changes.
You may also see any lint errors in the console.

npm test

Launches the test runner in the interactive watch mode.
See the section about running tests for more information.

npm run build

Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.
Your app is ready to be deployed!

See the section about deployment for more information.

npm run eject

Note: this is a one-way operation. Once you eject, you can't go back!

If you aren't satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.

You don't have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.

Dependencies

Front-end

npm install react-router-dom
npm install react-router-dom

Available MATERIAL-UI Scripts

Find

npm install -f @material-ui/core
npm install -f @material-ui/icons

Firebase

log in

npm install firebase
npm install -g firebase-tools

Find

firebase init hosting
npm run build
firebase deploy

image


 
Author: SashenJayathilaka
Source code: https://github.com/SashenJayathilaka/WhatsApp-Clone

#react #javascript #Firebase #whatsapp 

WhatsApp Clone with REACT and Firebase
Python  Library

Python Library

1660289820

Building a Messaging BOT for Whatsapp with Python

Whatsapp-messaging-BOT

A bot based on python compiled to a executable file for all Windows systems to send messages in bulk to recipients whose numbers need not be saved in your phone.

Steps to use

host the message in a text file in GitHub 6

Copy the url for the raw data 7

open the Folder 3

open the names.txt file and paste the list of names 4

open the numbers.txt file and paste the list of numbers 5

open the WhatsappBot.exe file and viola

 Pr Cut-1

Download details:

Author: akhilrajs
Source code: https://github.com/akhilrajs/Whatsapp-messaging-BOT
License: MIT license

#python #bot #whatsapp

Building a Messaging BOT for Whatsapp with Python

Crie Um Aplicativo De Comércio Eletrônico Automatizado

Em maio de 2022, a Meta (a empresa anteriormente conhecida como Facebook, proprietária do WhatsApp) anunciou que estava abrindo a API do WhatsApp Business ao público. Este artigo pretende dar as boas-vindas ao mundo de oportunidades da Meta, onde os chatbots do WhatsApp podem ajudá-lo a gerar leads, receber pedidos, agendar compromissos, realizar pesquisas, receber feedback do cliente, fornecer suporte ao cliente escalável, enviar faturas e recibos e muito mais.

Este tutorial se aprofundará nos detalhes técnicos da construção de um chatbot do WhatsApp do zero.

Ao final deste tutorial, você terá criado seu próprio chatbot do WhatsApp.

Nosso tutorial se concentra em uma loja de comércio eletrônico simples que vende itens domésticos e moda rápida. O negócio terá um chatbot do WhatsApp onde os clientes podem navegar e comprar na loja de comércio eletrônico.

Toda loja de comércio eletrônico precisa de produtos (preços, nomes, descrições etc.), e para este tutorial, usaremos os produtos fictícios da FakeStoreAPI .

Pré-requisitos

Antes de prosseguirmos, este artigo pressupõe que:

Etapa 1: Configurando nosso aplicativo no painel Meta Developer

O primeiro passo para usar qualquer uma das APIs do Meta é criar um aplicativo no painel Meta, que é gratuito.

  • Enquanto estiver conectado à sua conta de desenvolvedor Meta, navegue até https://developers.facebook.com/apps
  • Clique em Criar aplicativo
  • Na tela a seguir, selecione o tipo de aplicativo Business

Selecionando o tipo de aplicativo de negócios

  • Em seguida, preencha o nome do seu aplicativo e seu endereço de e-mail e selecione a página/empresa que deseja associar a este aplicativo

Nomeando o aplicativo e selecionando a página associada a ele

  • Após enviar o formulário, você será direcionado para uma tela semelhante a esta:

Selecionando a configuração do WhatsApp

Nesta tela, selecione WhatsApp e clique no botão Configurar .

Você será levado a uma nova tela, conforme mostrado abaixo.

Página de introdução

Nesta tela, observe:

  • O App ID , que é o ID associado ao nosso aplicativo Meta. O meu é1184643492312754
  • O token de acesso temporário , que expira após 24 horas. O meu começa com EAAQ1bU6LdrIBA
  • O número de telefone de teste , que usaremos para enviar mensagens aos clientes. O meu é+1 555 025 3483
    • A ID do número de telefone . O meu é113362588047543
    • O ID da conta comercial do WhatsApp . O meu é102432872486730

Observe que o token de acesso temporário expira após 24 horas, momento em que precisaremos renová-lo. Ao alternar seu aplicativo para o modo ativo, você pode solicitar um token de acesso permanente, o que não precisamos fazer, pois nosso aplicativo está no modo de desenvolvimento.

O ID do número de telefone e o ID da conta comercial do WhatsApp estão vinculados ao número de telefone de teste.

Em seguida, vamos adicionar um número de telefone para usar para receber mensagens.

No modo de desenvolvimento, o Meta nos restringe a cinco números de destinatários por motivos relacionados à prevenção de spam/uso indevido. No modo ao vivo/produção, o número representa os números de telefone de nossos clientes.

Clique em Selecione um número de telefone do destinatário e adicione seu próprio número do WhatsApp, conforme mostrado na captura de tela abaixo:

Caixa de diálogo Adicionar um número de telefone do destinatário

Depois de adicionar seu número de destinatário, você verá uma tela parecida com a abaixo. Se for a primeira vez que você adiciona seu número de telefone a plataformas Meta — como Páginas do Facebook, Meta Business suite ou o painel do desenvolvedor Meta — você receberá uma mensagem OTP do Facebook Business solicitando que você verifique se você realmente possui o número do destinatário .

Envie mensagens com a API

Testando nossa configuração

Vamos testar se tudo até esta etapa funcionou bem. Faremos isso clicando no botão Enviar mensagem .

Se tudo estiver bem, você deverá ver uma mensagem na sua caixa de entrada do WhatsApp do seu número de teste.

Mensagem Hello World do Facebook na caixa de entrada do WhatsApp

Até aqui estamos bem! Faça uma pausa e abra seu editor de código. Não feche a guia do seu navegador ainda, pois estaremos de volta ao painel Meta Developer em alguns minutos.

Etapa 2: configurar webhooks para receber mensagens

Agora que nossa configuração pode enviar mensagens com sucesso, vamos configurar uma maneira de receber mensagens. Hora de sujar as mãos e mergulhar na escrita de código. Todo o código que escreveremos para este tutorial está neste repositório do GitHub .

Crie uma nova pasta para conter nosso projeto. Abra esta pasta em um terminal e execute o script abaixo:

npm init ---yes

Em seguida, instalamos alguns pacotes:

npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev

Segue uma breve explicação de cada um:

  • O expresspacote é importante para configurar nosso servidor. O servidor conterá uma rota que atuará como nosso webhook
  • O pdfkitpacote será usado para gerar faturas para nossos clientes quando eles fizerem o check-out
  • O request pacote nos ajudará a executar solicitações de busca para o FakeStoreAPI
  • O whatsappcloudapi_wrappernos ajuda a enviar e receber mensagens do WhatsApp

Em seguida, vamos criar três arquivos:

  1. ./app.js
  2. ./.env.js
  3. ./routes/index.js

Em nosso ./.env.jsarquivo, digite o código abaixo:

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;
    }
};

No mesmo ./.env.jsarquivo:

  1. Substitua o valor de Meta_WA_accessTokenpelo token de acesso temporário para seu aplicativo Meta
  2. Substitua o valor de Meta_WA_SenderPhoneNumberIdpelo ID do seu número de telefone
  3. Substitua o valor de Meta_WA_wabaIdpelo ID da sua conta comercial do WhatsApp
  4. Defina seu próprio valor para o Meta_WA_VerifyToken. Pode ser uma string ou um número; você verá como o usamos na etapa de webhooks

O código acima primeiro importa as variáveis ​​de ambiente atuais e as desestrutura, depois adiciona novas variáveis ​​de ambiente e exporta a combinação das duas como um objeto.

No arquivo ./app.jsarquivo, insira o código abaixo:

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();

A primeira linha do bloco de código acima simplesmente importa o ./.env.jsarquivo e o atribui a process.env, que é um objeto globalmente acessível em Node.js.

No arquivo ./routes/index.js, insira o código abaixo:

'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;

Em seguida, abra o terminal e execute:

nodemon app.js

O servidor Express será executado na porta 9000.

Em seguida, abra outro terminal separado e execute:

ngrok http 9000

Este comando expõe nosso aplicativo Express à Internet mais ampla. O objetivo aqui é configurar um webhook que o WhatsApp Cloud possa fazer ping.

Anote a URL que o ngrok atribui ao seu servidor Express. No meu exemplo, o ngrok me emitiu este URL: https://7b9b-102-219-204-54.ngrok.io. Mantenha o servidor Express e o terminal ngrok em execução.

Em seguida, vamos retomar nosso trabalho no painel Meta Developer. Role até a parte intitulada Configurar Webhooks para receber mensagens e clique em Configurar Webhooks . O link exibirá uma página que se parece com a captura de tela abaixo:

Página de configuração de webhooks

Clique no botão Editar e um pop-up será exibido.

No campo URL de retorno de chamada, cole o URL que o ngrok emitiu para você e anexe-o com a rota de retorno de chamada, como na ./routes/index.jsdiretiva. Meu URL completo, neste caso, é https://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl.

No campo Verify token , insira o valor do Meta_WA_VerifyToken conforme ele aparece em seu ./.env.jsarquivo.

Inserindo valor no campo de token de verificação

Em seguida, clique em Verificar e salvar .

Se você configurou isso bem, verá uma console.logmensagem no terminal do seu servidor Express que diz:

GET: Alguém está me pingando!

Configurando nosso servidor Express

Agora, vamos fazer com que nosso servidor Express receba mensagens de assinatura do Meta.

Na mesma tela do painel Meta Developers, clique em Gerenciar e um pop-up aparecerá.

Gerenciar pop-up de mensagens de assinatura do servidor expresso

Selecione Mensagens e clique em Testar , que está na mesma linha.

Você deve ver uma console.logmensagem no terminal do servidor Express que diz:

POST: Alguém está me pingando!

Se você viu isso, volte para o mesmo pop-up e clique em Assinar na mesma linha de mensagem. Depois, clique em Concluído .

Etapa 3: escrevendo nossa lógica de negócios

Configurando uma fonte de dados de comércio eletrônico

Primeiro, configuraremos nossa lógica para buscar dados do FakeStoreAPI, gerar uma fatura em PDF e gerar um local de retirada de pedido fictício. Vamos envolver essa lógica em uma classe JavaScript, que importaremos para a lógica do nosso aplicativo.

Crie um arquivo e nomeie-o ./utils/ecommerce_store.js. Nesse arquivo, cole o seguinte código:

'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)
        ];
    }
};

No código acima, criamos uma classe chamada EcommerceStore.

O primeiro método, _fetchAssistant, recebe um endpoint que usa para pingar fakestoreapi.com .

Os métodos a seguir atuam como construtores de consulta para o primeiro método:

  1. getProductById recebe um ID de produto e, em seguida, obtém dados relativos a esse produto específico
  2. getAllCategories busca todas as categorias que estão em fakestoreapi.com
  3. getProductsInCategory recebe uma categoria de produtos e prossegue para buscar todos os produtos nessa categoria específica

Esses construtores de consultas invocarão o primeiro método.

Seguindo em frente, o método generatePDFInvoice recebe um pedaço de texto e um caminho de arquivo. Em seguida, ele cria um documento PDF, grava o texto nele e armazena o documento no caminho de arquivo fornecido.

O método generateRandomGeoLocation simplesmente retorna uma geolocalização aleatória. Este método será útil quando enviarmos o local de retirada de pedidos de nossa loja para um cliente que deseja retirar seu item.

Configurando sessões do cliente

Para lidar com nossa jornada do cliente, precisamos manter uma sessão que inclua um perfil do cliente e seu carrinho. Cada cliente terá, portanto, sua própria sessão exclusiva.

Em produção, poderíamos usar um banco de dados como MySQL, MongoDB ou algo mais resiliente, mas para manter nosso tutorial enxuto e curto, usaremos a estrutura de dados do ES2015Map . Com Mapo , podemos armazenar e recuperar dados específicos e iteráveis, como dados exclusivos de clientes.

Em seu ./routes/index.jsarquivo, adicione o seguinte código logo acima router.get('/meta_wa_callbackurl', (req, res)de .

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

A primeira linha importa a EcommerceStoreclasse, enquanto a segunda linha a inicializa. A terceira linha cria a sessão do cliente que usaremos para armazenar a jornada do cliente.

Inicializando nossa API do WhatsApp Cloud

Lembra do whatsappcloudapi_wrapperpacote que instalamos anteriormente? É hora de importá-lo e inicializá-lo.

No ./routes/index.jsarquivo, adicione as seguintes linhas de código abaixo da declaração do roteador 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,
});

Os seguintes valores são variáveis ​​de ambiente que definimos em nosso ./.env.jsarquivo:

  • process.env.Meta_WA_accessToken
  • process.env.Meta_WA_SenderPhoneNumberId
  • process.env.Meta_WA_wabaId

Inicializamos a classe WhatsAppCloudAPI com os três valores acima e nomeamos nossa instância Whatsapp.

Em seguida, vamos analisar todos os dados que estão chegando ao /meta_wa_callbackurlwebhook POST. Ao analisar o corpo das solicitações, poderemos extrair mensagens e outros detalhes, como o nome do remetente, o número de telefone do remetente etc.

Observe : Todas as edições de código que fizermos a partir deste ponto serão feitas inteiramente no ./routes/index.jsarquivo.

Adicione as seguintes linhas de código abaixo do colchete de abertura da try{instrução:

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
        }

Agora, quando um cliente nos envia uma mensagem, nosso webhook deve recebê-la. A mensagem está contida no corpo da solicitação do webhook. Para extrair informações úteis do corpo da solicitação, precisamos passar o corpo para o parseMessagemétodo da instância do WhatsApp.

Em seguida, usando uma ifinstrução, verificamos se o resultado do método contém uma mensagem válida do WhatsApp.

Dentro da ifinstrução, definimos incomingMessage, que contém a mensagem. Também definimos outras variáveis:

  • recipientPhoneé o número do cliente que nos enviou uma mensagem. Enviaremos uma resposta por mensagem, daí o prefixo “destinatário”
  • recipientNameé o nome do cliente que nos enviou uma mensagem. Este é o nome que eles definiram para si mesmos em seu perfil do WhatsApp
  • typeOfMsgé o tipo de mensagem que um cliente nos enviou. Como veremos mais adiante, algumas mensagens são textos simples, enquanto outras são respostas a botões (não se preocupe, isso fará sentido em breve!)
  • message_idé uma sequência de caracteres que identifica exclusivamente uma mensagem que recebemos. Isso é útil quando queremos realizar tarefas específicas para essa mensagem, como marcar uma mensagem como lida

Até este ponto, tudo parece bem, mas confirmaremos em breve.

Compreender e responder à intenção do nosso cliente

Como nosso tutorial não vai mergulhar em nenhuma forma de IA ou processamento de linguagem natural (NLP), vamos definir nosso fluxo de bate-papo com if…elselógica simples.

A lógica de conversação começa quando o cliente envia uma mensagem de texto. Não analisaremos a mensagem em si, portanto, não saberemos o que eles pretendiam fazer, mas podemos dizer ao cliente o que nosso bot pode fazer.

Vamos dar ao nosso cliente um contexto simples, ao qual ele possa responder com uma intenção específica.

Daremos ao cliente dois botões:

  1. Um que nos permite saber que eles querem falar com um humano real, não um chatbot
  2. Outro para navegar pelos produtos

Para isso, insira o seguinte código abaixo 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',
            },
        ],
    });
}

A ifdeclaração acima apenas nos permite lidar com mensagens de texto.

O sendSimpleButtonsmétodo nos permite enviar botões para um cliente. Anote as propriedades titlee id. O titleé o que o cliente verá e idé o que usaremos para saber em qual botão o cliente clicou.

Vamos verificar se fizemos isso certo. Abra seu aplicativo WhatsApp e envie uma mensagem de texto para a conta comercial do WhatsApp.

Enviando mensagem de texto para a conta comercial do WhatsApp

Se você receber uma resposta como a captura de tela acima, parabéns! Você acabou de enviar sua primeira mensagem por meio da API do WhatsApp Cloud.

Como o cliente pode clicar em qualquer um dos dois botões, vamos cuidar também do botão Fale com um humano .

Fora da ifdeclaração da text_messagelógica, insira o seguinte código:

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 código acima executa duas ações:

  1. Envia uma mensagem de texto para informar ao usuário que ele receberá um cartão de visita, usando o sendTextmétodo
  2. Envia um cartão de contato usando o sendContactmétodo

Esse código também detecta a intenção do usuário usando o ID do botão em que o usuário clicou (no nosso caso, o ID é o incomingMessage.button_reply.id) e, em seguida, responde com as duas opções de ação.

Agora, volte ao WhatsApp e clique em Falar com um humano . Se você fez isso corretamente, você verá uma resposta com a seguinte aparência:

Enviando "Fale com um humano" e recebendo um anexo de contato

Ao clicar no cartão de contato recebido, você verá o seguinte:

O cartão de contato mostra o nome completo, a empresa e dois números de telefone

Em seguida, vamos trabalhar no botão Visualizar alguns produtos .

Dentro da simple_button_message ifinstrução, mas logo abaixo e fora da speak_to_human ifinstrução, adicione o seguinte código:

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)
    });
}

Aqui está o que o código acima faz:

  1. A ifinstrução garante que o usuário clicou no botão Visualizar alguns produtos
  2. Busca categorias de produtos por FakeStoreAPImeio do getAllCategoriesmétodo
  3. Limita o número de botões a três usando o método array — slice(0,3)— porque o WhatsApp só nos permite enviar três botões simples
  4. Em seguida, ele percorre cada categoria, criando um botão com um title e um ID exclusivo que é prefixado comcategory_
  5. Com o sendSimpleButtonsmétodo, enviamos esses botões para o cliente

Volte novamente ao seu aplicativo WhatsApp e clique em Ver mais produtos . Se você executou as etapas acima corretamente, deverá ver uma resposta semelhante à captura de tela abaixo:

Enviando "ver alguns produtos" no chat do WhatsApp

Buscando produtos por categoria

Agora, vamos criar a lógica para obter produtos na categoria que o cliente selecionou.

Ainda dentro da simple_button_message ifinstrução, mas abaixo e fora da see_categories ifinstrução, adicione o seguinte código:

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,
    });
}

A ifdeclaração acima confirma que o botão que o cliente clicou era de fato o botão que contém uma categoria.

A primeira coisa que fazemos aqui é extrair a categoria específica do ID do botão. Em seguida, consultamos nossa FakeStoreAPI para produtos que pertencem a essa categoria específica.

Após a consulta, recebemos a lista de produtos dentro de um array, listOfProducts.data. Agora percorremos esse array e, para cada produto nele, extraímos seu preço, título, descrição e ID.

Anexamos product_ao id, o que nos ajudará a escolher a seleção de um cliente na próxima etapa. Certifique-se de cortar o comprimento do ID, título e descrição de acordo com as restrições do botão de opção (ou lista) da API do WhatsApp Cloud .

Em seguida, retornamos três valores: ID, título e descrição. Como o WhatsApp permite no máximo 10 linhas, limitaremos o número de produtos a 10 usando o método array .slice(0,10).

Depois disso, invocamos o sendRadioButtonsmétodo para enviar os produtos aos clientes. Anote as propriedades , , , e . headerTextbodyTextfooterTextlistOfSections

Retorne ao aplicativo WhatsApp e clique em qualquer categoria de produtos. Se você seguiu as instruções corretamente, deverá ver uma resposta parecida com a captura de tela abaixo:

Escolhendo a categoria de eletrônicos e recebendo a resposta

Ao clicar em Selecionar um produto , você deverá ver a seguinte tela:

Selecione uma tela pop-up de produtoNesse ponto, os clientes podem selecionar um produto que achem interessante, mas podemos saber o que eles selecionaram? Ainda não, então vamos trabalhar nessa parte.

Fora da simple_button_message ifdeclaração, vamos adicionar outra ifdeclaração:

if (typeOfMsg === 'radio_button_message') {
    let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
    
}

Dentro da ifdeclaração acima e logo abaixo do selectionId, adicione o seguinte código:

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 código acima faz o seguinte:

  1. Extrai o ID do produto do botão de opção que o cliente clicou
  2. Consulta FakeStoreAPI com esse ID de produto
  3. Ao receber e extrair os dados do produto, formata o texto. O WhatsApp usa sublinhados para renderizar texto em itálico, enquanto asteriscos renderizam texto em negrito
  4. Renderize emoji de estrela usando a emojiRatingfunção. Se uma classificação for 3,8, renderizará emojis de três estrelas
  5. Anexa a imagem do produto ao texto renderizado e o envia usando o sendImagemétodo

Depois disso, enviamos ao cliente uma lista de três botões usando o sendSimpleButtons. Um dá ao cliente a oportunidade de adicionar produtos ao carrinho. Anote o ID do botão prefixado com add_to_cart_.

Agora, retorne ao seu aplicativo WhatsApp e selecione um produto. Se você seguiu as instruções corretamente, deverá ver uma resposta semelhante à captura de tela a seguir:

Chatbot envia ao cliente três botões selecionáveis

Criação de sessões para armazenar carrinhos de clientes

Para acompanhar os produtos que um cliente adiciona ao carrinho, precisamos ter um local para armazenar os itens do carrinho. Aqui é onde CustomerSessionentra em jogo. Vamos adicionar alguma lógica a isso.

Fora da radio_button_message ifdeclaração, e logo abaixo da message_iddeclaração, adicione o seguinte código:

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 código acima verifica se a sessão de um cliente foi criada. Se não tiver sido criado, ele cria uma nova sessão que é identificada exclusivamente pelo número de telefone do cliente. Em seguida, inicializamos uma propriedade chamada cart, que começa como um array vazio.

A addToCartfunção recebe a product_ide o número do cliente específico. Em seguida, ele pinga a FakeStoreAPI para os dados do produto específico e envia o produto para o cartarray.

Em seguida, a listOfItemsInCart função recebe o número de telefone do cliente e recupera o associado cart, que é usado para calcular o número de produtos no carrinho e a soma de seus preços. Por fim, retorna os itens no carrinho e seu preço total.

A clearCartfunção recebe o número de telefone do cliente e esvazia o carrinho desse cliente.

Com a lógica do carrinho pronta, vamos construir o botão Adicionar ao carrinho . Dentro da simple_button_message ifdeclaração e abaixo de sua button_iddeclaração, adicione o seguinte código:

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 código acima extrai o ID do produto do botão que o cliente clicou e, em seguida, invoca a addToCartfunção para salvar o produto no carrinho da sessão do cliente. Em seguida, ele extrai o número de itens no carrinho da sessão do cliente e informa ao cliente quantos produtos ele possui. Ele também envia dois botões, um dos quais permite que o usuário faça o check-out.

Anote o ID do botão e volte para o seu aplicativo WhatsApp. Clique em Adicionar ao carrinho . Se você seguiu bem as instruções, deverá ver uma resposta semelhante à captura de tela abaixo:

Adicionar ao carrinho

Agora que nossos clientes podem adicionar itens ao carrinho, podemos escrever a lógica para o check-out.

Escrevendo a lógica de checkout

Dentro da simple_button_message ifinstrução, mas fora da add_to_cart_ ifinstrução, adicione o seguinte código:

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 código acima faz o seguinte:

  1. Pega todos os itens no carrinho e os coloca dentrofinalBill
  2. Inicializa uma variável invoiceText, que conterá o texto que enviaremos ao cliente, bem como o texto que será redigido na versão PDF da fatura
    1. O forEachloop simplesmente concatena o titleand pricede cada produto à fatura
  3. O generatePDFInvoicemétodo (o mesmo que definimos em nossa EcommerceStoreclasse) recebe os detalhes do pedido, rascunha um documento PDF e o salva no caminho do arquivo em nosso diretório/pasta local que fornecemos
  4. O sendTextmétodo envia uma mensagem de texto simples contendo os detalhes do pedido para o cliente
  5. sendSimpleButtonsenvia alguns botões para o cliente. Anote o botão Imprimir minha fatura e seu ID
  6. Finalmente, o clearCartmétodo esvazia o carrinho

Agora, volte para o seu aplicativo WhatsApp e clique em Checkout . Se você seguiu bem as instruções, verá uma resposta semelhante à captura de tela a seguir:

Clicando no botão de checkout

Neste ponto, o cliente deve receber uma fatura em PDF para impressão. Por isso, vamos trabalhar em alguma lógica referente ao botão Imprimir minha fatura .

Escrevendo nossa lógica de fatura imprimível

Dentro da simple_button_message ifinstrução, mas fora da checkout ifinstrução, adicione o seguinte código:

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 código acima obtém o documento PDF gerado na etapa anterior do sistema de arquivos local e o envia ao cliente usando o sendDocumentmétodo.

Quando um cliente solicita um produto online, ele também precisa saber como receberá o produto físico. Por esse motivo, geramos algumas coordenadas aleatórias usando o generateRandomGeoLocationmétodo da EcommerceStoreclasse e enviamos essas coordenadas para o cliente usando o sendLocationmétodo para que ele saiba onde pode retirar fisicamente seu produto.

Agora, abra seu aplicativo WhatsApp e clique em Imprimir minha fatura .

Se você seguiu as instruções acima corretamente, deverá ver uma resposta semelhante à captura de tela abaixo:

Envio de mensagem "imprimir minha fatura" e recebimento de arquivo PDF e instruções para retirada do produto.

Exibição de recibos de leitura para clientes

Por fim, você deve ter notado que as marcas de seleção abaixo das mensagens são cinza, em vez de azul. Isso indica que as mensagens que enviamos não retornaram confirmações de leitura, apesar de nosso bot as estar lendo.

Os tiques cinzas podem ser frustrantes para os clientes e, por esse motivo, precisamos trabalhar para mostrar os tiques azuis.

Fora da simple_button_message ifinstrução e antes da chave de fechamento da data?.isMessage ifinstrução, adicione o seguinte código:

await Whatsapp.markMessageAsRead({ message_id });

Esta simples linha marca uma mensagem como lida assim que a respondemos.

Agora, abra seu aplicativo WhatsApp e envie uma mensagem de texto aleatória. Você está vendo o que eu estou vendo?

Mensagens "hey" e chatbot respondem com mensagem padrão

Se seus bate-papos anteriores foram atualizados com marcações azuis, parabéns! Você chegou ao final deste tutorial e aprendeu algumas coisas ao longo do caminho.

Pensamentos finais

Com um total geral de 2 bilhões de usuários ativos mensais, ignorar o WhatsApp como estratégia de comércio eletrônico é uma maneira certa de ficar para trás da concorrência de sua empresa e, como a maioria de seus clientes já usa o WhatsApp em suas atividades diárias, por que não deveria? t seu negócio encontrá-los lá?

Espero que este tutorial tenha sido útil para desmistificar a API do WhatsApp Cloud e espero que você tenha se divertido ao longo do caminho. Deixe-me saber quais outros tópicos você pode achar interessantes e não se esqueça de compartilhar este artigo com seus círculos de tecnologia.

 Fonte: https://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/

#whatsapp #ecommerce #cloud #api #nodejs 

Crie Um Aplicativo De Comércio Eletrônico Automatizado
Hoang  Kim

Hoang Kim

1658842095

Xây Dựng ứng Dụng Thương Mại điện Tử Tự động Với WhatsApp Cloud API

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 .

Điều kiện tiên quyết

Trước khi chúng tôi tiếp tục, bài viết này giả định rằng:

  • Bạn có tài khoản nhà phát triển Meta hợp lệ. Nếu bạn không, vui lòng xem https://developers.facebook.com/
  • Bạn am hiểu về JavaScript và Node.js
  • Bạn đã cài đặt ngrok

Bước 1: Định cấu hình ứng dụng của chúng tôi trên bảng điều khiển Meta Developer

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í.

  • Trong khi đăng nhập vào tài khoản nhà phát triển Meta của bạn, hãy điều hướng đến https://developers.facebook.com/apps
  • Nhấp vào Tạo ứng dụng
  • Trong màn hình tiếp theo, hãy chọn loại ứng dụng Doanh nghiệp

Chọn loại ứng dụng kinh doanh

  • Tiếp theo, điền tên ứng dụng và địa chỉ email của bạn, sau đó chọn trang / doanh nghiệp bạn muốn liên kết với ứng dụng này

Đặt tên ứng dụng và chọn trang được liên kết với nó

  • Sau khi gửi biểu mẫu, bạn sẽ được dẫn đến một màn hình như sau:

Chọn thiết lập WhatsApp

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.

Trang bắt đầu

Trên màn hình này, hãy lưu ý:

  • ID ứng dụng , là ID được liên kết với ứng dụng Meta của chúng tôi. Của tôi là1184643492312754
  • thông báo truy cập tạm thời , sẽ hết hạn sau 24 giờ. Của tôi bắt đầu bằng EAAQ1bU6LdrIBA
  • Số điện thoại Kiểm tra mà chúng tôi sẽ sử dụng để gửi tin nhắn cho khách hàng. Của tôi là+1 555 025 3483
    • ID số điện thoại . Của tôi là113362588047543
    • ID tài khoản doanh nghiệp WhatsApp . Của tôi là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:

Thêm hộp thoại số điện thoại người nhận

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 .

Gửi tin nhắn bằng API

Kiểm tra thiết lập của chúng tôi

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.

Tin nhắn Hello World từ Facebook trong hộp thư đến WhatsApp

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ước 2: Thiết lập webhook để nhận tin nhắn

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:

  • Gói expressnà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ôi
  • Gói pdfkitnà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án
  • Gói request này sẽ giúp chúng tôi chạy các yêu cầu tìm nạp tới FakeStoreAPI
  • Giúp chúng tôi gửi và whatsappcloudapi_wrappernhận tin nhắn WhatsApp

Tiếp theo, chúng ta sẽ tạo ba tệp:

  1. ./app.js
  2. ./.env.js
  3. ./routes/index.js

Trong ./.env.jstệ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.jstệp:

  1. Thay thế giá trị của Meta_WA_accessTokenbằng mã thông báo truy cập tạm thời cho ứng dụng Meta của bạn
  2. Thay thế giá trị của Meta_WA_SenderPhoneNumberIdbằng ID số điện thoại của bạn
  3. Thay thế giá trị của Meta_WA_wabaIdbằng ID tài khoản doanh nghiệp WhatsApp của bạn
  4. Đặt giá trị của riêng bạn cho Meta_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.jstệ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.jstệ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:

Trang cấu hình webhooks

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.jstệp của bạn.

Nhập giá trị vào trường mã thông báo xác minh

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.logthô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!

Định cấu hình máy chủ Express của chúng 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.

Quản lý cửa sổ bật lên thông báo đăng ký máy chủ nhanh

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.logthô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 .

Bước 3: Viết logic kinh doanh của chúng tôi

Định cấu hình nguồn dữ liệu thương mại điện tử

Đầ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:

  1. 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ể đó
  2. getAllCategories tìm nạp tất cả các danh mục có trong fakestoreapi.com
  3. getProductsInCategory 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ọ.

Định cấu hình phiên khách hàng

Để 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.jstệ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 EcommerceStorelớ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.

Khởi tạo API đám mây WhatsApp của chúng tôi

Nhớ whatsappcloudapi_wrappergó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.jstệ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.jstệ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_callbackurlwebhook 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.jstệ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 parseMessagephương thức của phiên bản WhatsApp.

Sau đó, sử dụng một ifcâ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 ifcâ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:

  • recipientPhonelà 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"
  • recipientNamelà 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ọ
  • typeOfMsglà 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_idlà 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à đã đọc

Cho đế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.

Hiểu và đáp ứng ý định của khách hàng

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…elselogic đơ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:

  1. Một cho chúng tôi biết họ muốn nói chuyện với một con người thực tế, không phải một chatbot
  2. Một cái khác để duyệt sản phẩm

Để 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 ifchỉ cho phép chúng tôi xử lý tin nhắn văn bản.

Phương sendSimpleButtonsphá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 titleid. Đó là những gì khách titlehàng sẽ thấy và idlà 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.

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 ifcâu lệnh text_messagelogic, 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:

  1. Gửi tin nhắn văn bản để cho người dùng biết rằng họ sẽ nhận được thẻ liên hệ, sử dụng sendTextphương pháp này
  2. Gửi thẻ liên hệ bằng sendContactphương thức này

Mã 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:

Gửi "Nói chuyện với con người" và nhận tệp đính kèm liên hệ

Khi bạn nhấp vào thẻ liên hệ bạn nhận được, bạn sẽ thấy như sau:

Thẻ liên hệ hiển thị đầy đủ tên, doanh nghiệp và hai số điện thoại

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 ifcâu lệnh, nhưng ngay bên dưới và bên ngoài speak_to_human ifcâ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:

  1. Tuyên bố đảm bảo rằng người ifdùng đã nhấp vào nút Xem một số sản phẩm
  2. Tìm nạp danh mục sản phẩm từ FakeStoreAPIphương getAllCategoriesthức
  3. Giới hạn số lượng nút là ba bằng cách sử dụng phương pháp mảng - slice(0,3)- vì WhatsApp chỉ cho phép chúng tôi gửi ba nút đơn giản
  4. Sau đó, nó lặp lại từng danh mục, tạo một nút có một title và một ID duy nhất được bắt đầu bằngcategory_
  5. Với sendSimpleButtonsphương pháp, chúng tôi gửi các nút này cho khách hàng

Quay 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:

Gửi "xem một số sản phẩm" trong trò chuyện WhatsApp

Tìm nạp sản phẩm theo danh mục

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 ifcâu lệnh, nhưng bên dưới và bên ngoài see_categories ifcâ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,
    });
}

ifTuyê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 sendRadioButtonsphươ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:

Chọn danh mục điện tử và nhận phản hồ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:

Chọn một màn hình bật lên của sản phẩmTạ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 ifcâu lệnh, hãy để chúng tôi thêm một ifcâ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 ifcâ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:

  1. Trích xuất ID sản phẩm từ nút radio mà khách hàng đã nhấp vào
  2. Truy vấn FakeStoreAPI với ID sản phẩm đó
  3. Khi nhận và trích xuất dữ liệu của sản phẩm, nó sẽ định dạng văn bản. WhatsApp sử dụng dấu gạch dưới để hiển thị văn bản in nghiêng, trong khi dấu hoa thị hiển thị văn bản in đậm
  4. Hiển thị biểu tượng cảm xúc ngôi sao bằng cách sử dụng emojiRatingchứ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 sao
  5. Đính kèm hình ảnh của sản phẩm vào văn bản được hiển thị và gửi nó bằng sendImagephương thức

Sau đó, 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:

Chatbot gửi cho khách hàng ba nút có thể lựa chọn

Phiên xây dựng để lưu trữ giỏ hàng của khách hàng

Để 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 CustomerSessionphát huy tác dụng. Hãy thêm một số logic vào nó.

Bên ngoài radio_button_message ifcâu lệnh và ngay bên dưới phần message_idkhai 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 addToCartnhận a product_idvà 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 cartmả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 clearCartnă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 ifcâu lệnh và bên dưới phần button_idkhai 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 addToCartchứ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:

Thêm vào giỏ hàng

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.

Viết logic thanh toán

Bên trong simple_button_message ifcâu lệnh nhưng bên ngoài add_to_cart_ ifcâ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:

  1. Nhận tất cả các mặt hàng trong giỏ hàng và đặt chúng vào bên trongfinalBill
  2. Khởi tạo một biến 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 đơn
    1. Vòng forEachlặp chỉ đơn giản là nối titlepricecủa từng sản phẩm với hóa đơn
  3. Phương generatePDFInvoicethức (giống phương thức mà chúng tôi đã xác định trong EcommerceStorelớ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ấp
  4. Phương sendTextthứ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àng
  5. sendSimpleButtonsgử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ó
  6. Cuối cùng, clearCartphương pháp làm trống giỏ hàng

Bâ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:

Nhấp vào nút thanh toán

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 .

Viết logic hóa đơn có thể in của chúng tôi

Bên trong simple_button_message ifcâu lệnh nhưng bên ngoài checkout ifcâ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 sendDocumentphươ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 generateRandomGeoLocationphương thức của EcommerceStorelớp và gửi các tọa độ này cho khách hàng bằng sendLocationphươ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:

Nhắn tin "in hóa đơn của tôi" và nhận tệp PDF và hướng dẫn lấy sản phẩm.

Hiển thị biên nhận đã đọc cho khách hàng

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 ifcâu lệnh và trước dấu ngoặc nhọn đóng của data?.isMessage ifcâ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?

Tin nhắn "hey" và chatbot trả lời bằng tin nhắn mặc định

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.

Suy nghĩ cuối cùng

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 

Xây Dựng ứng Dụng Thương Mại điện Tử Tự động Với WhatsApp Cloud API
Diego  Elizondo

Diego Elizondo

1658842023

Cree Una Aplicación De Comercio Electrónico Automatizada Con WhatsApp

En mayo de 2022, Meta (la empresa antes conocida como Facebook, propietaria de WhatsApp) anunció que abriría al público la API empresarial de WhatsApp. Este artículo pretende darle la bienvenida al mundo de oportunidades de Meta, donde los chatbots de WhatsApp pueden ayudarlo a generar clientes potenciales, recibir pedidos, programar citas, realizar encuestas, recibir comentarios de los clientes, brindar atención al cliente escalable, enviar facturas y recibos, y más.

Este tutorial profundizará en los aspectos técnicos de la creación de un chatbot de WhatsApp desde cero.

Al final de este tutorial, habrá creado su propio chatbot de WhatsApp.

Nuestro tutorial se centra en una sencilla tienda de comercio electrónico familiar que vende artículos para el hogar y moda rápida. El negocio tendrá un chatbot de WhatsApp donde los clientes podrán navegar y comprar en la tienda de comercio electrónico.

Cada tienda de comercio electrónico necesita productos (precios, nombres, descripciones, etc.), y para este tutorial, usaremos los productos ficticios de FakeStoreAPI .

requisitos previos

Antes de continuar, este artículo asume que:

Paso 1: Configurando nuestra aplicación en el tablero de Meta Developer

El primer paso para usar cualquiera de las API de Meta es crear una aplicación en el tablero de Meta, que es gratis.

  • Mientras está conectado a su cuenta de desarrollador de Meta, navegue a https://developers.facebook.com/apps
  • Haz clic en Crear aplicación
  • En la siguiente pantalla, seleccione el tipo de aplicación Business

Selección del tipo de aplicación comercial

  • Luego, complete el nombre de su aplicación y su dirección de correo electrónico, y luego seleccione la página/negocio que desea asociar con esta aplicación

Nombrando la aplicación y seleccionando la página asociada a ella

  • Después de enviar el formulario, accederá a una pantalla que se ve así:

Seleccionando la configuración de WhatsApp

En esta pantalla, seleccione WhatsApp y haga clic en su botón Configurar .

Luego será conducido a una nueva pantalla, como se muestra a continuación.

Página de inicio

En esta pantalla, toma nota de:

  • El ID de la aplicación , que es el ID asociado con nuestra aplicación Meta. El mio es1184643492312754
  • El token de acceso temporal , que caduca a las 24 horas. El mio empieza con EAAQ1bU6LdrIBA...
  • El número de teléfono de prueba , que usaremos para enviar mensajes a los clientes. El mio es+1 555 025 3483
    • El ID del número de teléfono . El mio es113362588047543
    • El ID de la cuenta comercial de WhatsApp . El mio es102432872486730

Tenga en cuenta que el token de acceso temporal caduca después de 24 horas, momento en el que tendremos que renovarlo. Cuando cambia su aplicación al modo en vivo, puede solicitar un token de acceso permanente, que no necesitamos hacer ya que nuestra aplicación está en modo de desarrollo.

El ID del número de teléfono y el ID de la cuenta comercial de WhatsApp están vinculados al número de teléfono de prueba.

A continuación, agreguemos un número de teléfono para usar para recibir mensajes.

En el modo de desarrollo, Meta nos restringe a cinco números de destinatarios por motivos relacionados con la prevención del spam/uso indebido. En el modo en vivo/producción, el número representa los números de teléfono de nuestros clientes.

Haga clic en Seleccione un número de teléfono del destinatario y agregue su propio número de WhatsApp, como se muestra en la siguiente captura de pantalla:

Agregar un cuadro de diálogo de número de teléfono del destinatario

Después de agregar su número de destinatario, verá una pantalla similar a la siguiente. Si es la primera vez que agrega su número de teléfono a las plataformas Meta, como las páginas de Facebook, la suite Meta Business o el panel de desarrollo de Meta, recibirá un mensaje OTP de Facebook Business que le pedirá que verifique que realmente es el propietario del número del destinatario. .

Enviar mensajes con la API

Probando nuestra configuración

Probemos si todo hasta este paso funcionó bien. Lo haremos haciendo clic en el botón Enviar mensaje .

Si todo está bien, debería ver un mensaje en su bandeja de entrada de WhatsApp desde su número de prueba.

Mensaje de Hello World de Facebook en la bandeja de entrada de WhatsApp

Hasta este punto, ¡lo estamos haciendo bien! Haz una pausa y abre tu editor de código. No cierres la pestaña de tu navegador todavía porque volveremos al panel de Meta Developer en unos minutos.

Paso 2: Configuración de webhooks para recibir mensajes

Ahora que nuestra configuración puede enviar mensajes con éxito, configuremos una forma de recibir mensajes. Es hora de ensuciarse las manos y sumergirnos en la escritura de código. Todo el código que escribiremos para este tutorial está en este repositorio de GitHub .

Cree una nueva carpeta para contener nuestro proyecto. Abra esta carpeta en una terminal y ejecute el siguiente script:

npm init ---yes

A continuación, instalamos algunos paquetes:

npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev

He aquí una breve explicación de cada uno:

  • El expresspaquete es importante para configurar nuestro servidor. El servidor contendrá una ruta que actuará como nuestro webhook.
  • El pdfkitpaquete se utilizará para generar facturas para nuestros clientes cuando realicen el pago.
  • El request paquete nos ayudará a ejecutar solicitudes de recuperación a FakeStoreAPI
  • El whatsappcloudapi_wrappernos ayuda a enviar y recibir mensajes de WhatsApp

A continuación, vamos a crear tres archivos:

  1. ./app.js
  2. ./.env.js
  3. ./routes/index.js

En nuestro ./.env.jsarchivo, escriba el siguiente código:

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;
    }
};

En el mismo ./.env.jsarchivo:

  1. Reemplace el valor de Meta_WA_accessTokencon el token de acceso temporal para su aplicación Meta
  2. Reemplace el valor de Meta_WA_SenderPhoneNumberIdcon su ID de número de teléfono
  3. Reemplace el valor de Meta_WA_wabaIdcon su ID de cuenta comercial de WhatsApp
  4. Establezca su propio valor para el Meta_WA_VerifyToken. Puede ser una cadena o un número; verás cómo lo usamos en el paso de webhooks

El código anterior primero importa las variables de entorno actuales y las desestructura, luego agrega nuevas variables de entorno y exporta la combinación de las dos como un objeto.

En el archivo ./app.jsfile, inserte el siguiente código:

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();

La primera línea del bloque de código anterior simplemente importa el ./.env.jsarchivo y lo asigna a process.env, que es un objeto accesible globalmente en Node.js.

En el archivo ./routes/index.js, inserte el siguiente código:

'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;

A continuación, abra la terminal y ejecute:

nodemon app.js

El servidor Express se ejecutará en el puerto 9000.

Luego, abra otra terminal separada y ejecute:

ngrok http 9000

Este comando expone nuestra aplicación Express a Internet en general. El objetivo aquí es configurar un webhook al que WhatsApp Cloud pueda hacer ping.

Tome nota de la URL que ngrok asigna a su servidor Express. En mi ejemplo, ngrok me envió esta URL: https://7b9b-102-219-204-54.ngrok.io. Mantenga en funcionamiento tanto el servidor Express como el terminal ngrok.

A continuación, reanudemos nuestro trabajo en el panel de Meta Developer. Desplácese hasta la parte titulada Configurar webhooks para recibir mensajes y haga clic en Configurar webhooks . El enlace mostrará una página que se parece a la siguiente captura de pantalla:

Página de configuración de webhooks

Haga clic en el botón Editar y aparecerá una ventana emergente.

En el campo URL de devolución de llamada , pegue la URL que ngrok le envió y agréguela con la ruta de devolución de llamada, como en la ./routes/index.jsdirectiva. Mi URL completa, en este caso, es https://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl.

En el campo Verificar token , ingrese el valor de Meta_WA_VerifyToken tal como aparece en su ./.env.jsarchivo.

Ingresar valor en el campo de token de verificación

Luego haga clic en Verificar y guardar .

Si configuró esto bien, verá un console.logmensaje en la terminal de su servidor Express que dice:

GET: ¡Alguien me está haciendo ping!

Configurando nuestro servidor Express

Ahora, hagamos que nuestro servidor Express reciba mensajes de suscripción de Meta.

En la misma pantalla del tablero de Meta Developers, haga clic en Administrar y aparecerá una ventana emergente.

Administrar la ventana emergente de mensajes de suscripción del servidor express

Seleccione Mensajes y haga clic en Prueba , que se encuentra en la misma fila.

Debería ver un console.logmensaje en la terminal de su servidor Express que dice:

POST: ¡Alguien me está haciendo ping!

Si vio esto, regrese a la misma ventana emergente y haga clic en Suscribirse en la misma fila de mensajes. Luego, haga clic en Listo .

Paso 3: escribir nuestra lógica de negocios

Configuración de una fuente de datos de comercio electrónico

Primero, configuraremos nuestra lógica para obtener datos de FakeStoreAPI, generar una factura en PDF y generar una ubicación ficticia de recogida de pedidos. Envolveremos esta lógica en una clase de JavaScript, que luego importaremos a la lógica de nuestra aplicación.

Cree un archivo y asígnele un nombre ./utils/ecommerce_store.js. En este archivo, pegue el siguiente código:

'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)
        ];
    }
};

En el código anterior, hemos creado una clase llamada EcommerceStore.

El primer método, _fetchAssistantrecibe un punto final que utiliza para hacer ping a fakestoreapi.com .

Los siguientes métodos actúan como generadores de consultas para el primer método:

  1. getProductById recibe una identificación de producto y luego obtiene datos relacionados con ese producto específico
  2. getAllCategories recupera todas las categorías que están en fakestoreapi.com
  3. getProductsInCategory recibe una categoría de productos y luego procede a buscar todos los productos en esa categoría específica

Estos generadores de consultas invocarán el primer método.

Continuando, el método generatePDFInvoice recibe un fragmento de texto y una ruta de archivo. Luego crea un documento PDF, escribe el texto en él y luego almacena el documento en la ruta del archivo proporcionada.

El método generateRandomGeoLocation simplemente devuelve una geolocalización aleatoria. Este método será útil cuando enviemos el lugar de recogida de pedidos de nuestra tienda a un cliente que quiera recoger su artículo.

Configuración de sesiones de clientes

Para manejar el viaje de nuestro cliente, debemos mantener una sesión que incluya un perfil de cliente y su carrito. Cada cliente tendrá, por lo tanto, su propia sesión única.

En producción, podríamos usar una base de datos como MySQL, MongoDB u otra resistente, pero para que nuestro tutorial sea sencillo y breve, usaremos la estructura de datos de ES2015Map . Con Map, podemos almacenar y recuperar datos iterables específicos, como datos de clientes únicos.

En su ./routes/index.jsarchivo, agregue el siguiente código justo arriba 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

La primera línea importa la EcommerceStoreclase, mientras que la segunda línea la inicializa. La tercera línea crea la sesión del cliente que usaremos para almacenar el viaje del cliente.

Inicializando nuestra API de WhatsApp Cloud

¿Recuerdas el whatsappcloudapi_wrapperpaquete que instalamos antes? Es hora de importarlo e inicializarlo.

En el ./routes/index.jsarchivo, agregue las siguientes líneas de código debajo de la declaración del enrutador 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,
});

Los siguientes valores son variables de entorno que definimos en nuestro ./.env.jsarchivo:

  • process.env.Meta_WA_accessToken
  • process.env.Meta_WA_SenderPhoneNumberId
  • process.env.Meta_WA_wabaId

Inicializamos la clase WhatsAppCloudAPI con los tres valores anteriores y nombramos nuestra instancia Whatsapp.

A continuación, analicemos todos los datos que ingresan al /meta_wa_callbackurlwebhook POST. Al analizar el cuerpo de las solicitudes, podremos extraer mensajes y otros detalles, como el nombre del remitente, el número de teléfono del remitente, etc.

Tenga en cuenta : todas las ediciones de código que hagamos desde este punto se realizarán por completo en el ./routes/index.jsarchivo.

Agregue las siguientes líneas de código debajo del paréntesis de apertura de la try{instrucción:

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
        }

Ahora, cuando un cliente nos envíe un mensaje, nuestro webhook debería recibirlo. El mensaje está contenido en el cuerpo de solicitud del webhook. Para extraer información útil del cuerpo de la solicitud, debemos pasar el cuerpo al parseMessagemétodo de la instancia de WhatsApp.

Luego, usando una ifdeclaración, verificamos si el resultado del método contiene un mensaje de WhatsApp válido.

Dentro de la ifdeclaración, definimos incomingMessage, que contiene el mensaje. También definimos otras variables:

  • recipientPhonees el número del cliente que nos envió un mensaje. Les enviaremos un mensaje de respuesta, de ahí el prefijo “destinatario”
  • recipientNamees el nombre del cliente que nos envió un mensaje. Este es el nombre que se han puesto en su perfil de WhatsApp
  • typeOfMsges el tipo de mensaje que un cliente nos envió. Como veremos más adelante, algunos mensajes son textos simples, mientras que otros son respuestas a botones (¡no te preocupes, esto tendrá sentido pronto!)
  • message_ides una cadena de caracteres que identifica de forma única un mensaje que hemos recibido. Esto es útil cuando queremos hacer tareas que son específicas de ese mensaje, como marcar un mensaje como leído

Hasta este punto, todo parece estar bien, pero lo confirmaremos en breve.

Comprender y responder a la intención de nuestro cliente.

Dado que nuestro tutorial no se sumergirá en ninguna forma de IA o procesamiento de lenguaje natural (NLP), definiremos nuestro flujo de chat con una if…elselógica simple.

La lógica de la conversación comienza cuando el cliente envía un mensaje de texto. No miraremos el mensaje en sí, por lo que no sabremos qué pretendían hacer, pero podemos decirle al cliente lo que puede hacer nuestro bot.

Démosle a nuestro cliente un contexto simple, al que pueda responder con una intención específica.

Le daremos al cliente dos botones:

  1. Uno que nos permita saber que quieren hablar con un ser humano real, no con un chatbot.
  2. Otro para buscar productos

Para hacer esto, inserte el siguiente código a continuación 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',
            },
        ],
    });
}

La ifdeclaración anterior solo nos permite manejar mensajes de texto.

El sendSimpleButtonsmétodo nos permite enviar botones a un cliente. Tome nota de las propiedades titley id. es lo titleque verá el cliente y ides lo que usaremos para saber en qué botón hizo clic el cliente.

Veamos si lo hicimos bien. Abra su aplicación WhatsApp y envíe un mensaje de texto a la cuenta comercial de WhatsApp.

Enviar mensaje de texto a la cuenta comercial de WhatsApp

Si obtiene una respuesta como la captura de pantalla anterior, ¡felicidades! Acabas de enviar tu primer mensaje a través de la API de WhatsApp Cloud.

Dado que el cliente puede hacer clic en cualquiera de los dos botones, también nos ocuparemos del botón Hablar con una persona.

Fuera de la ifdeclaración de la text_messagelógica, inserte el siguiente código:

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',
                    },
                ],
            },
        });
    }
};

El código anterior realiza dos acciones:

  1. Envía un mensaje de texto para decirle al usuario que recibirá una tarjeta de contacto, usando el sendTextmétodo
  2. Envía una tarjeta de contacto usando el sendContactmétodo

Este código también detecta la intención del usuario usando la ID del botón en el que el usuario hizo clic (en nuestro caso, la ID es el incomingMessage.button_reply.id), y luego responde con las dos opciones de acción.

Ahora, regresa a WhatsApp y haz clic en Hablar con un humano . Si lo hiciste bien, verás una respuesta como la siguiente:

Enviar "Hablar con un humano" y recibir un archivo adjunto de contacto

Al hacer clic en la tarjeta de contacto que recibió, debería ver lo siguiente:

La tarjeta de contacto muestra el nombre completo, la empresa y dos números de teléfono

A continuación, trabajemos en el botón Ver algunos productos .

Dentro de la simple_button_message ifdeclaración, pero justo debajo y fuera de la speak_to_human ifdeclaración, agregue el siguiente código:

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)
    });
}

Esto es lo que hace el código anterior:

  1. La ifdeclaración asegura que el usuario hizo clic en el botón Ver algunos productos
  2. Obtiene categorías de productos a FakeStoreAPItravés del getAllCategoriesmétodo
  3. Limita la cantidad de botones a tres usando el método de matriz — slice(0,3)— porque WhatsApp solo nos permite enviar tres botones simples
  4. Luego recorre cada categoría, creando un botón con una title y una identificación única que tiene el prefijo concategory_
  5. Con el sendSimpleButtonsmétodo, enviamos estos botones al cliente.

Regrese nuevamente a su aplicación WhatsApp y haga clic en Ver más productos . Si realizó correctamente los pasos anteriores, debería ver una respuesta similar a la siguiente captura de pantalla:

Enviando "ver algunos productos" en el chat de WhatsApp

Obtención de productos por categoría

Ahora, creemos la lógica para obtener productos en la categoría que seleccionó el cliente.

Todavía dentro de la simple_button_message ifdeclaración, pero debajo y fuera de la see_categories ifdeclaración, agregue el siguiente código:

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,
    });
}

La ifdeclaración anterior confirma que el botón en el que el cliente hizo clic era de hecho el botón que contiene una categoría.

Lo primero que hacemos aquí es extraer la categoría específica de la ID del botón. Luego, consultamos nuestra FakeStoreAPI para productos que pertenecen a esa categoría específica.

Después de consultar, recibimos la lista de productos dentro de una matriz, listOfProducts.data. Ahora recorremos esta matriz, y para cada producto en ella extraemos su precio, título, descripción e ID.

Agregamos product_al id, que nos ayudará a seleccionar la selección de un cliente en el siguiente paso. Asegúrese de recortar la longitud de la identificación, el título y la descripción de acuerdo con las restricciones del botón de radio (o lista) de la API de WhatsApp Cloud .

Luego devolvemos tres valores: ID, título y descripción. Dado que WhatsApp solo nos permite un máximo de 10 filas, limitaremos el número de productos a 10 mediante el método array .slice(0,10).

Después de eso, invocamos el sendRadioButtonsmétodo para enviar los productos a los clientes. Tome nota de las propiedades , , y . headerTextbodyTextfooterTextlistOfSections

Regrese a la aplicación WhatsApp y haga clic en cualquier categoría de productos. Si siguió las instrucciones correctamente, debería ver una respuesta similar a la siguiente captura de pantalla:

Elegir categoría de electrónica y recibir respuesta

Al hacer clic en Seleccionar un producto , debería ver la siguiente pantalla:

Seleccionar una pantalla emergente de productoEn este punto, los clientes pueden seleccionar un producto que les parezca interesante, pero ¿podemos saber qué han seleccionado? Todavía no, así que trabajemos en esta parte.

Fuera de la simple_button_message ifdeclaración, agreguemos otra ifdeclaración:

if (typeOfMsg === 'radio_button_message') {
    let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
    
}

Dentro de la ifdeclaración anterior y justo debajo del selectionId, agregue el siguiente código:

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',
            },
        ],
    });
}

El código anterior hace lo siguiente:

  1. Extrae el ID del producto del botón de radio en el que hizo clic el cliente
  2. Consulta FakeStoreAPI con ese ID de producto
  3. Cuando recibe y extrae los datos del producto, formatea el texto. WhatsApp usa guiones bajos para representar el texto en cursiva, mientras que los asteriscos representan el texto en negrita
  4. Renderiza emoji de estrella usando la emojiRatingfunción. Si una calificación es 3.8, generará emojis de tres estrellas.
  5. Adjunta la imagen del producto al texto renderizado y lo envía usando el sendImagemétodo

Después de esto, enviamos al cliente una lista de tres botones usando el sendSimpleButtons. Uno le da al cliente la oportunidad de agregar productos a su carrito. Tome nota de la identificación del botón que tiene el prefijo add_to_cart_.

Ahora, regrese a su aplicación WhatsApp y seleccione un producto. Si siguió las instrucciones correctamente, debería ver una respuesta similar a la siguiente captura de pantalla:

Chatbot envía al cliente tres botones seleccionables

Creación de sesiones para almacenar carritos de clientes

Para realizar un seguimiento de los productos que un cliente agrega a su carrito, necesitamos tener un lugar para almacenar los artículos del carrito. Aquí es donde CustomerSessionentra en juego. Vamos a añadirle algo de lógica.

Fuera de la radio_button_message ifdeclaración, y justo debajo de la message_iddeclaración, agregue el siguiente código:

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...

El código anterior comprueba si se ha creado la sesión de un cliente. Si no se ha creado, crea una nueva sesión que se identifica de forma única por el número de teléfono del cliente. Luego inicializamos una propiedad llamada cart, que comienza como una matriz vacía.

La addToCartfunción toma en un product_idy el número del cliente específico. Luego, hace ping a FakeStoreAPI para obtener los datos del producto específico y empuja el producto a la cartmatriz.

Luego, la listOfItemsInCart función toma el número de teléfono del cliente y recupera el asociado cart, que se usa para calcular la cantidad de productos en el carrito y la suma de sus precios. Finalmente, devuelve los artículos del carrito y su precio total.

La clearCartfunción toma el número de teléfono del cliente y vacía el carrito de ese cliente.

Una vez terminada la lógica del carrito, construyamos el botón Agregar al carrito . Dentro de la simple_button_message ifdeclaración y debajo de su button_iddeclaración, agregue el siguiente código:

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',
            },
        ],
    });
}

El código anterior extrae el ID del producto del botón en el que hizo clic el cliente, luego invoca la addToCartfunción para guardar el producto en el carrito de la sesión del cliente. Luego, extrae la cantidad de artículos en el carrito de la sesión del cliente y le dice al cliente cuántos productos tiene. También envía dos botones, uno de los cuales permite al usuario realizar el pago.

Tome nota del ID del botón y vuelva a su aplicación de WhatsApp. Haz clic en Añadir al carrito . Si siguió bien las instrucciones, debería ver una respuesta similar a la siguiente captura de pantalla:

Añadir a la cesta

Ahora que nuestros clientes pueden agregar artículos al carrito, podemos escribir la lógica para pagar.

Escribir la lógica de pago

Dentro de la simple_button_message ifdeclaración pero fuera de la add_to_cart_ ifdeclaración, agregue el siguiente código:

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 });
}

El código anterior hace lo siguiente:

  1. Toma todos los artículos en el carrito y los pone dentrofinalBill
  2. Inicializa una variable invoiceText, que contendrá el texto que enviaremos al cliente, así como el texto que se redactará en la versión PDF de la factura.
    1. El forEachciclo simplemente concatena el titley pricede cada producto a la factura
  3. El generatePDFInvoicemétodo (el mismo que definimos en nuestra EcommerceStoreclase) toma los detalles del pedido, redacta un documento PDF y lo guarda en la ruta del archivo en nuestro directorio/carpeta local que le proporcionamos
  4. El sendTextmétodo envía un mensaje de texto simple que contiene los detalles del pedido al cliente
  5. sendSimpleButtonsenvía algunos botones al cliente. Toma nota del botón Imprimir mi factura y su ID
  6. Finalmente, el clearCartmétodo vacía el carro .

Ahora, vuelva a su aplicación WhatsApp y haga clic en Finalizar compra . Si siguió bien las instrucciones, verá una respuesta similar a la siguiente captura de pantalla:

Haciendo clic en el botón de pago

En este punto, el cliente debe recibir una factura en PDF imprimible. Por esta razón, trabajemos en alguna lógica con respecto al botón Imprimir mi factura .

Escribiendo nuestra lógica de factura imprimible

Dentro de la simple_button_message ifdeclaración pero fuera de la checkout ifdeclaración, agregue el siguiente código:

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',
  });
}

El código anterior obtiene el documento PDF generado en el paso anterior del sistema de archivos local y lo envía al cliente utilizando el sendDocumentmétodo.

Cuando un cliente solicita un producto en línea, también necesita saber cómo recibirá el producto físico. Por esta razón, generamos algunas coordenadas aleatorias utilizando el generateRandomGeoLocationmétodo de la EcommerceStoreclase y enviamos estas coordenadas al cliente utilizando el sendLocationmétodo para informarle dónde puede recoger físicamente su producto.

Ahora, abra su aplicación WhatsApp y haga clic en Imprimir mi factura .

Si ha seguido las instrucciones anteriores correctamente, debería ver una respuesta similar a la siguiente captura de pantalla:

Enviar mensaje de texto "imprimir mi factura" y recibir un archivo PDF e instrucciones para recoger el producto.

Mostrar confirmaciones de lectura a los clientes

Por último, es posible que haya notado que las marcas de verificación debajo de los mensajes son grises, en lugar de azules. Esto indica que los mensajes que enviamos no devolvieron recibos de lectura a pesar de que nuestro bot los estaba leyendo.

Las marcas grises pueden ser frustrantes para los clientes y, por este motivo, debemos trabajar para mostrar las marcas azules.

Fuera de la simple_button_message ifdeclaración y antes de la llave de cierre de la data?.isMessage ifdeclaración, agregue el siguiente código:

await Whatsapp.markMessageAsRead({ message_id });

Esta simple línea marca un mensaje como leído tan pronto como lo hayamos respondido.

Ahora, abra su aplicación WhatsApp y envíe un mensaje de texto aleatorio. ¿Estás viendo lo que estoy viendo?

Mensajes "hey" y chatbot responde con mensaje predeterminado

Si sus chats anteriores se han actualizado con marcas azules, ¡felicidades! Has llegado al final de este tutorial y has aprendido algunas cosas en el camino.

Pensamientos finales

Con un total de 2000 millones de usuarios activos mensuales, ignorar WhatsApp como estrategia de comercio electrónico es una forma segura de quedarse atrás de la competencia de su negocio, y dado que la mayoría de sus clientes ya usan WhatsApp en sus actividades diarias, ¿por qué no hacerlo? t su negocio encontrarlos allí?

Espero que este tutorial haya sido útil para desmitificar la API de WhatsApp Cloud, y espero que te hayas divertido en el camino. Cuéntame qué otros temas te pueden interesar y no olvides compartir este artículo con tus círculos tecnológicos.

 Fuente: https://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/

#whatsapp #ecommerce #cloud #api #nodejs 

Cree Una Aplicación De Comercio Electrónico Automatizada Con WhatsApp
郝 玉华

郝 玉华

1658838660

使用 WhatsApp Cloud API 和 Node.js 构建自动化电子商务应用程序

2022 年 5 月,Meta(前身为 Facebook 的公司,拥有 WhatsApp)宣布将向公众开放 WhatsApp Business API。本文旨在欢迎您来到 Meta 的机会世界,WhatsApp 聊天机器人可以帮助您产生潜在客户、接收订单、安排约会、进行调查、获取客户反馈、提供可扩展的客户支持、发送发票和收据等等。

本教程将深入探讨从头开始构建 WhatsApp 聊天机器人的技术细节。

在本教程结束时,您将创建自己的 WhatsApp 聊天机器人

我们的教程侧重于销售家居用品和快时尚的简单妈妈和流行电子商务商店。该企业将拥有一个 WhatsApp 聊天机器人,客户可以在其中浏览和从电子商务商店购买。

每个电子商务商店都需要产品(价格、名称、描述等),在本教程中,我们将使用FakeStoreAPI中的虚拟产品。

先决条件

在我们继续之前,本文假设:

第 1 步:在 Meta Developer 仪表板上配置我们的应用程序

使用任何 Meta 的 API 的第一步是在 Meta 仪表板上创建一个应用程序,这是免费的。

选择业务应用类型

  • 接下来,填写您的应用名称和您的电子邮件地址,然后选择您要与此应用关联的页面/业务

命名应用程序并选择与其关联的页面

  • 提交表单后,您将进入一个如下所示的屏幕:

选择 WhatsApp 设置

在此屏幕上,选择WhatsApp并单击其设置按钮。

然后,您将进入一个新屏幕,如下所示。

入门页面

在此屏幕上,请注意:

  • App ID,这是与我们的 Meta 应用关联的 ID 。我的是1184643492312754
  • 临时访问令牌,24 小时后过期。我的开头是EAAQ1bU6LdrIBA……
  • 测试电话号码,我们将使用它向客户发送消息。我的是+1 555 025 3483
    • 电话号码ID 。我的是113362588047543
    • WhatsApp企业帐户 ID。我的是102432872486730

请注意,临时访问令牌会在 24 小时后过期,届时我们需要对其进行更新。当您将应用切换到实时模式时,您可以申请永久访问令牌,我们不需要这样做,因为我们的应用处于开发模式。

电话号码 ID 和 WhatsApp 企业帐户 ID 与测试电话号码相关联。

接下来,让我们添加一个用于接收消息的电话号码。

在开发模式下,Meta 将我们限制为五个收件人号码,以防止垃圾邮件/滥用。在直播/制作模式下,数字代表我们客户的电话号码。

单击选择收件人电话号码并添加您自己的 WhatsApp 号码,如下面的屏幕截图所示:

添加收件人电话号码对话框

添加收件人号码后,您将看到如下图所示的屏幕。如果这是您第一次将您的电话号码添加到 Meta 平台(例如 Facebook Pages、Meta Business 套件或 Meta 开发人员仪表板),您将收到来自 Facebook Business 的 OTP 消息,提示您验证您确实拥有收件人号码.

使用 API 发送消息

测试我们的设置

让我们测试到这一步是否一切正常。我们将通过单击发送消息按钮来完成此操作。

如果一切顺利,您应该会在 WhatsApp 收件箱中看到一条来自您的测试号码的消息。

WhatsApp 收件箱中来自 Facebook 的 Hello World 消息

到目前为止,我们做得很好!暂停一下,打开您的代码编辑器。不要关闭您的浏览器选项卡,因为我们将在几分钟后返回 Meta Developer 仪表板。

第 2 步:设置 webhook 以接收消息

现在我们的设置可以成功发送消息,让我们设置一种接收消息的方式。是时候弄脏我们的手并沉浸在编写代码中了。我们将为本教程编写的所有代码都在这个 GitHub 存储库中。

创建一个新文件夹来包含我们的项目。在终端中打开此文件夹并运行以下脚本:

npm init ---yes

接下来,我们安装一些包:

npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev

以下是每个的简要说明:

  • express软件包对于设置我们的服务器很重要。服务器将包含一个将充当我们的 webhook 的路由
  • pdfkit包裹将用于在我们的客户结账时为他们生成发票
  • request 包将帮助我们运行对 FakeStoreAPI 的获取请求
  • 帮助我们whatsappcloudapi_wrapper发送和接收 WhatsApp 消息

接下来,我们将创建三个文件:

  1. ./app.js
  2. ./.env.js
  3. ./routes/index.js

在我们的./.env.js文件中,输入以下代码:

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;
    }
};

在同一个./.env.js文件中:

  1. 将 的值替换Meta_WA_accessToken为您的 Meta 应用程序的临时访问令牌
  2. 将值替换为Meta_WA_SenderPhoneNumberId您的电话号码 ID
  3. 将 的值替换为Meta_WA_wabaId您的 WhatsApp 企业帐户 ID
  4. Meta_WA_VerifyToken. 它可以是字符串或数字;您将在 webhook 步骤中看到我们如何使用它

上面的代码首先导入当前的环境变量并对其进行解构,然后添加新的环境变量并将两者的组合导出为一个对象。

在文件./app.js文件中,插入以下代码:

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();

上面代码块的第一行只是导入./.env.js文件并将其分配给process.envNode.js 中可全局访问的对象。

在文件./routes/index.js中,插入以下代码:

'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;

接下来,打开终端并运行:

nodemon app.js

Express 服务器将在端口 9000 上运行。

接下来,打开另一个单独的终端并运行:

ngrok http 9000

此命令将我们的 Express 应用程序暴露给更广泛的互联网。这里的目标是设置一个 WhatsApp Cloud 可以 ping 的 webhook。

记下 ngrok 分配给您的 Express 服务器的 URL。在我的示例中,ngrok 向我发出了这个 URL https://7b9b-102-219-204-54.ngrok.io:. 保持 Express 服务器和 ngrok 终端都运行。

接下来,让我们在 Meta Developer 仪表板中继续我们的工作。滚动到标题为配置 Webhook 以接收消息的部分,然后单击配置 Webhook。该链接将显示一个类似于以下屏幕截图的页面:

Webhook 配置页面

单击编辑按钮,将显示一个弹出窗口。

回调 URL字段中,粘贴 ngrok 发布给您的 URL,并将其附加到回调路由中,如./routes/index.js指令中所示。在这种情况下,我的完整 URL 是https://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl.

验证令牌字段中,输入文件中出现的Meta_WA_VerifyToken./.env.js的值。

在验证令牌字段中输入值

然后单击验证并保存

如果您配置得当,您将console.log在 Express 服务器的终端中看到一条消息:

GET:有人在ping我!

配置我们的 Express 服务器

现在,让我们的 Express 服务器接收来自 Meta 的订阅消息。

在同一个 Meta Developers 仪表板屏幕上,单击管理,将出现一个弹出窗口。

管理快速服务器订阅消息弹出窗口

选择Messages并单击位于同一行的Test 。

您应该console.log在 Express 服务器的终端中看到一条消息:

POST:有人在ping我!

如果您看到了这一点,请返回到同一个弹出窗口,然后单击同一消息行中的订阅。之后,单击完成

第三步:编写我们的业务逻辑

配置电子商务数据源

首先,我们将设置我们的逻辑以从 FakeStoreAPI 获取数据、生成 PDF 发票并生成虚拟订单取货位置。我们将把这个逻辑包装到一个 JavaScript 类中,然后我们将它导入到我们的应用程序的逻辑中。

创建一个文件并命名它./utils/ecommerce_store.js。在此文件中,粘贴以下代码:

'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)
        ];
    }
};

在上面的代码中,我们创建了一个名为EcommerceStore.

第一种方法_fetchAssistant接收一个端点,用于 ping fakestoreapi.com

以下方法充当第一种方法的查询构建器:

  1. getProductById 接收产品 ID,然后获取与该特定产品有关的数据
  2. getAllCategories 获取fakestoreapi.com中的所有类别
  3. getProductsInCategory 接收一个产品类别,然后继续获取该特定类别中的所有产品

这些查询构建器将调用第一个方法。

继续前进,该方法generatePDFInvoice 接收一段文本和一个文件路径。然后它会创建一个 PDF 文档,在上面写入文本,然后将文档存储在提供的文件路径中。

该方法generateRandomGeoLocation 只是返回一个随机的地理位置。当我们将商店的订单取货地点发送给想要取货的客户时,此方法将很有用。

配置客户会话

为了处理我们的客户旅程,我们需要保留一个包含客户资料和他们的购物车的会话。因此,每个客户都有自己独特的会话。

在生产环境中,我们可以使用 MySQL、MongoDB 或其他具有弹性的数据库,但为了保持我们的教程精简和简短,我们将使用ES2015 的Map数据结构。使用Map,我们可以存储和检索特定的、可迭代的数据,例如唯一的客户数据。

在您的./routes/index.js文件中,在上面添加以下代码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

第一行导入EcommerceStore类,而第二行初始化它。第三行创建客户的会话,我们将使用它来存储客户的旅程。

初始化我们的 WhatsApp Cloud API

还记得whatsappcloudapi_wrapper我们之前安装的包吗?是时候导入和初始化它了。

./routes/index.js文件中,在 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,
});

以下值是我们在./.env.js文件中定义的环境变量:

  • process.env.Meta_WA_accessToken
  • process.env.Meta_WA_SenderPhoneNumberId
  • process.env.Meta_WA_wabaId

我们用上面的三个值初始化类 WhatsAppCloudAPI 并命名我们的实例Whatsapp

接下来,让我们解析进入/meta_wa_callbackurlPOST webhook 的所有数据。通过解析请求的正文,我们将能够提取消息和其他详细信息,例如发件人的姓名、发件人的电话号码等。

请注意:我们从这一点开始所做的所有代码编辑都将完全在./routes/index.js文件中进行。

try{在语句的左括号下方添加以下代码行:

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
        }

现在,当客户向我们发送消息时,我们的 webhook 应该会收到它。该消息包含在 webhook 的请求正文中。要从请求正文中提取有用信息,我们需要将正文传递给parseMessageWhatsApp 实例的方法。

然后,使用if语句,我们检查方法的结果是否包含有效的 WhatsApp 消息。

if语句中,我们定义incomingMessage了包含消息的 。我们还定义了其他变量:

  • recipientPhone是向我们发送消息的客户的号码。我们将向他们发送消息回复,因此前缀为“recipient”
  • recipientName是向我们发送消息的客户的姓名。这是他们在 WhatsApp 个人资料中为自己设置的名称
  • typeOfMsg是客户发送给我们的消息类型。正如我们稍后将看到的,有些消息是简单的文本,而另一些则是对按钮的回复(别担心,这很快就会有意义!)
  • message_id是唯一标识我们收到的消息的字符串。当我们想要执行特定于该消息的任务时,这很有用,例如将消息标记为已读

到目前为止,一切似乎都很好,但我们将很快确认。

了解并响应客户的意图

由于我们的教程不会深入探讨任何形式的 AI 或自然语言处理 (NLP),因此我们将使用简单的if…else逻辑来定义我们的聊天流程。

当客户发送短信时,对话逻辑开始。我们不会查看消息本身,因此我们不会知道他们打算做什么,但我们可以告诉客户我们的机器人可以做什么。

让我们给我们的客户一个简单的上下文,他们可以用特定的意图来回复。

我们会给客户两个按钮:

  1. 一个让我们知道他们想与真实的人交谈,而不是聊天机器人
  2. 另一个浏览产品

为此,请在下面插入以下代码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',
            },
        ],
    });
}

上面的if语句只让我们处理短信。

sendSimpleButtons方法允许我们向客户发送按钮。注意titleid属性。这title是客户将看到的内容,id也是我们用来了解客户点击了哪个按钮的内容。

让我们检查一下我们是否做对了。打开您的 WhatsApp 应用程序并向 WhatsApp 企业帐户发送短信。

向 WhatsApp 企业帐户发送短信

如果您收到如上图所示的回复,恭喜!您刚刚通过 WhatsApp Cloud API 发送了第一条消息。

由于客户可以单击这两个按钮中的任何一个,我们还要处理Speak to a human按钮。

if在逻辑语句之外text_message,插入以下代码:

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',
                    },
                ],
            },
        });
    }
};

上面的代码执行两个动作:

  1. sendText使用方法发送一条短信告诉用户他们将收到一张联系人卡片
  2. sendContact使用方法发送联系人卡片

此代码还使用用户单击的按钮的 ID(在我们的例子中,ID 是incomingMessage.button_reply.id)检测用户的意图,然后使用两个操作选项进行响应。

现在,返回 WhatsApp 并单击与人交谈。如果你做对了,你会看到如下回复:

发送“与人交谈”并接收联系人附件

当您单击收到的联系人卡片时,您应该会看到以下内容:

联系人卡片显示全名、公司和两个电话号码

接下来,让我们处理查看一些产品按钮。

simple_button_message if语句内部,但就在语句的下方和外部speak_to_human if,添加以下代码:

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)
    });
}

这是上面代码的作用:

  1. if语句确保用户单击了查看某些产品按钮
  2. FakeStoreAPI通过getAllCategories方法获取产品类别
  3. 使用数组方法将按钮的数量限制为三个slice(0,3)——因为 WhatsApp 只允许我们发送三个简单的按钮
  4. 然后它遍历每个类别,创建一个按钮,该按钮带有title 一个唯一的 ID,前缀为category_
  5. 通过该sendSimpleButtons方法,我们将这些按钮发送给客户

再次返回您的 WhatsApp 应用程序,然后单击查看更多产品。如果您正确执行了上述步骤,您应该会看到如下截图所示的回复:

在 WhatsApp 聊天中发送“查看一些产品”

按类别获取产品

现在,让我们创建逻辑以获取客户选择的类别中的产品。

仍然在simple_button_message if语句内部,但在语句的下方和外部see_categories if,添加以下代码:

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语句确认了客户单击的按钮确实是包含类别的按钮。

我们在这里做的第一件事是从按钮的 ID 中提取特定的类别。然后,我们在 FakeStoreAPI 中查询属于该特定类别的产品。

查询后,我们收到一个数组中的产品列表,listOfProducts.data. 我们现在遍历这个数组,并为其中的每个产品提取其价格、标题、描述和 ID。

我们附加product_id,这将帮助我们在下一步中选择客户的选择。确保根据WhatsApp Cloud API 的单选按钮(或列表)限制修剪 ID、标题和描述的长度。

然后我们返回三个值:ID、标题和描述。由于 WhatsApp 只允许我们最多 10 行,我们将使用数组方法将产品数量限制为 10 .slice(0,10)

之后,我们调用该sendRadioButtons方法将产品发送给客户。记下属性、、和。 headerTextbodyTextfooterTextlistOfSections

返回 WhatsApp 应用程序并单击任何类别的产品。如果您按照正确的说明进行操作,您应该会看到如下截图所示的回复:

选择电子产品类别并接收响应

当您单击Select a product时,您应该会看到以下屏幕:

选择产品弹出屏幕此时,客户可以选择他们感兴趣的产品,但我们能知道他们选择了什么吗?还没有,所以让我们在这部分工作。

simple_button_message if语句之外,让我们添加另一个if语句:

if (typeOfMsg === 'radio_button_message') {
    let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
    
}

在上面的if语句中,在 的正下方selectionId,添加以下代码:

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',
            },
        ],
    });
}

上面的代码执行以下操作:

  1. 从客户单击的单选按钮中提取产品 ID
  2. 使用该产品 ID 查询 FakeStoreAPI
  3. 当它接收并提取产品数据时,它会格式化文本。WhatsApp 使用下划线以斜体呈现文本,而星号以粗体呈现文本
  4. emojiRating使用该功能渲染星星表情符号。如果评分为 3.8,它将呈现三颗星表情符号
  5. 将产品图像附加到渲染文本并使用sendImage方法发送

在此之后,我们使用 向客户发送三个按钮的列表sendSimpleButtons。一个让客户有机会将产品添加到他们的购物车中。记下前缀为 的按钮 ID add_to_cart_

现在,返回您的 WhatsApp 应用程序并选择一个产品。如果您正确地按照说明进行操作,您应该会看到类似于以下屏幕截图的回复:

聊天机器人向客户发送三个可选按钮

建立会话以存储客户购物车

为了跟踪客户添加到购物车中的产品,我们需要有一个地方来存储购物车中的物品。这就是CustomerSession发挥作用的地方。让我们为其添加一些逻辑。

在声明之外,在radio_button_message if声明的正下方message_id,添加以下代码:

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...

上面的代码检查是否已经创建了客户的会话。如果尚未创建,它会创建一个由客户电话号码唯一标识的新会话。然后我们初始化一个名为 的属性cart,它以一个空数组开始。

addToCart函数接受 aproduct_id和特定客户的数量。然后它 ping FakeStoreAPI 以获取特定产品的数据并将产品推送到cart数组中。

然后,该listOfItemsInCart 函数获取客户的电话号码并检索关联的cart,用于计算购物车中的产品数量及其价格总和。最后,它返回购物车中的商品及其总价。

clearCart函数接收客户的电话号码并清空该客户的购物车。

完成购物车逻辑后,让我们构建“添加到购物车”按钮。在simple_button_message if语句内部及其button_id声明下方,添加以下代码:

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',
            },
        ],
    });
}

上面的代码从客户单击的按钮中提取产品 ID,然后调用addToCart函数将产品保存到客户会话的购物车中。然后,它会提取客户会话购物车中的商品数量,并告诉客户他们有多少产品。它还发送两个按钮,其中一个允许用户结帐。

记下按钮 ID 并返回到您的 WhatsApp 应用程序。单击添加到购物车。如果您很好地按照说明进行操作,您应该会看到类似于以下屏幕截图的回复:

添加到购物车

现在我们的客户可以将商品添加到购物车,我们可以编写结账逻辑。

编写结帐逻辑

simple_button_message if语句内部但在语句外部add_to_cart_ if,添加以下代码:

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 });
}

上面的代码执行以下操作:

  1. 获取购物车中的所有商品并将它们放入finalBill
  2. 初始化一个变量invoiceText,它将包含我们将发送给客户的文本以及将被起草到发票的 PDF 版本中的文本
    1. forEach循环只是将每个产品的titleand连接price到发票
  3. generatePDFInvoice方法(与我们在EcommerceStore类中定义的方法相同)获取订单的详细信息,起草一份 PDF 文档,并将其保存在我们提供给它的本地目录/文件夹中的文件路径中
  4. sendText方法向客户发送包含订单详细信息的简单文本消息
  5. sendSimpleButtons向客户发送一些按钮。记下打印我的发票按钮及其 ID
  6. 最后,clearCart方法清空购物车

现在,切换回您的 WhatsApp 应用并点击Checkout。如果您按照说明正确操作,您将看到类似于以下屏幕截图的回复:

点击结帐按钮

此时,客户应该会收到一张可打印的 PDF 发票。出于这个原因,让我们处理一些关于打印我的发票按钮的逻辑。

编写我们的可打印发票逻辑

simple_button_message if语句内部但在语句外部checkout if,添加以下代码:

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',
  });
}

上面的代码从本地文件系统中获取上一步生成的PDF文档,通过该方法发送给客户sendDocument

当客户在线订购产品时,他们还需要知道他们将如何收到实物产品。出于这个原因,我们使用类的方法生成了一些随机坐标,并使用该generateRandomGeoLocation方法EcommerceStore将这些坐标发送给客户sendLocation,让他们知道他们可以在哪里实际提取他们的产品。

现在,打开您的 WhatsApp 应用并点击打印我的发票

如果您正确按照上述说明进行操作,您应该会看到类似于以下屏幕截图的回复:

发短信“打印我的发票”并收到 PDF 文件和提货说明。

向客户显示已读回执

最后,您可能已经注意到消息下方的复选标记是灰色的,而不是蓝色的。这表明我们发送的消息没有返回已读回执,尽管我们的机器人正在阅读它们。

灰色刻度可能会让客户感到沮丧,因此,我们需要努力显示蓝色刻度。

在语句之外和simple_button_message if语句的右大括号之前data?.isMessage if,添加以下代码:

await Whatsapp.markMessageAsRead({ message_id });

一旦我们回复了一条消息,这个简单的单行就将其标记为已读。

现在,打开您的 WhatsApp 应用程序并发送一条随机短信。你看到我看到的了吗?

消息“嘿”和聊天机器人以默认消息响应

如果您之前的聊天已用蓝色勾号更新,那么恭喜!您已经完成了本教程并在此过程中学到了一些东西。

最后的想法

每月共有 20 亿活跃用户,忽略 WhatsApp 作为电子商务策略肯定会落后于您的企业竞争,而且由于您的大多数客户已经在他们的日常活动中使用 WhatsApp,为什么不应该呢?你的公司在那里遇到他们吗?

我希望本教程有助于揭开 WhatsApp Cloud API 的神秘面纱,并希望您在此过程中玩得开心。让我知道您可能会感兴趣的其他主题,并且不要忘记与您的技术圈分享这篇文章。

 来源:https ://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/

#whatsapp #ecommerce #cloud #api #nodejs 

使用 WhatsApp Cloud API 和 Node.js 构建自动化电子商务应用程序
Anne  de Morel

Anne de Morel

1658838250

Créez Une Application De Commerce Électronique Automatisée

En mai 2022, Meta (la société anciennement connue sous le nom de Facebook, propriétaire de WhatsApp) a annoncé qu'elle ouvrait l'API WhatsApp Business au public. Cet article a pour but de vous accueillir dans le monde des opportunités de Meta, où les chatbots WhatsApp peuvent vous aider à générer des prospects, à recevoir des commandes, à planifier des rendez-vous, à exécuter des enquêtes, à recueillir les commentaires des clients, à fournir un support client évolutif, à envoyer des factures et des reçus, etc.

Ce didacticiel plongera dans les détails techniques de la création d'un chatbot WhatsApp à partir de zéro.

A la fin de ce tutoriel, vous aurez créé votre propre chatbot WhatsApp.

Notre didacticiel se concentre sur une simple boutique de commerce électronique familiale qui vend des articles ménagers et de la mode rapide. L'entreprise disposera d'un chatbot WhatsApp où les clients pourront naviguer et acheter dans la boutique de commerce électronique.

Chaque boutique en ligne a besoin de produits (prix, noms, descriptions, etc.), et pour ce tutoriel, nous utiliserons les produits factices de FakeStoreAPI .

Conditions préalables

Avant de poursuivre, cet article suppose que :

  • Vous avez un compte de développeur Meta valide. Si ce n'est pas le cas, veuillez consulter https://developers.facebook.com/
  • Vous maîtrisez JavaScript et Node.js
  • Vous avez installé ngrok

Étape 1 : Configuration de notre application sur le tableau de bord Meta Developer

La première étape pour utiliser l'une des API de Meta consiste à créer une application sur le tableau de bord Meta, ce qui est gratuit.

  • Une fois connecté à votre compte de développeur Meta, accédez à https://developers.facebook.com/apps
  • Cliquez sur Créer une application
  • Dans l'écran qui suit, sélectionnez le type d'application Business

Sélection du type d'application professionnelle

  • Ensuite, renseignez le nom de votre application et votre adresse e-mail, puis sélectionnez la page/l'entreprise que vous souhaitez associer à cette application

Nommer l'application et sélectionner la page qui lui est associée

  • Après avoir soumis le formulaire, vous serez introduit dans un écran qui ressemble à ceci :

Sélection de la configuration de WhatsApp

Sur cet écran, sélectionnez WhatsApp et cliquez sur son bouton Configurer .

Vous serez alors introduit dans un nouvel écran, comme indiqué ci-dessous.

Page de démarrage

Sur cet écran, notez :

  • L' App ID , qui est l'ID associé à notre application Meta. Le mien est1184643492312754
  • Le jeton d'accès temporaire , qui expire après 24 heures. Le mien commence par EAAQ1bU6LdrIBA...
  • Le numéro de téléphone de test , que nous utiliserons pour envoyer des messages aux clients. Le mien est+1 555 025 3483
    • L' identifiant du numéro de téléphone . Le mien est113362588047543
    • L' identifiant du compte WhatsApp Business . Le mien est102432872486730

Veuillez noter que le jeton d'accès temporaire expire après 24 heures, date à laquelle nous devrons le renouveler. Lorsque vous passez votre application en mode live, vous pouvez demander un jeton d'accès permanent, ce que nous n'avons pas besoin de faire car notre application est en mode développement.

L'ID du numéro de téléphone et l'ID du compte professionnel WhatsApp sont liés au numéro de téléphone de test.

Ensuite, ajoutons un numéro de téléphone à utiliser pour recevoir des messages.

En mode développement, Meta nous limite à cinq numéros de destinataires pour des raisons liées à la prévention des spams/abus. En mode direct/production, le numéro représente les numéros de téléphone de nos clients.

Cliquez sur Sélectionner un numéro de téléphone destinataire et ajoutez votre propre numéro WhatsApp, comme indiqué dans la capture d'écran ci-dessous :

Boîte de dialogue Ajouter un numéro de téléphone de destinataire

Après avoir ajouté votre numéro de destinataire, vous verrez un écran qui ressemble à celui ci-dessous. Si c'est la première fois que vous ajoutez votre numéro de téléphone aux plates-formes Meta - telles que les pages Facebook, la suite Meta Business ou le tableau de bord du développeur Meta - vous recevrez un message OTP de Facebook Business qui vous invite à vérifier que vous possédez bien le numéro du destinataire. .

Envoyer des messages avec l'API

Test de notre configuration

Testons si tout jusqu'à cette étape a bien fonctionné. Nous le ferons en cliquant sur le bouton Envoyer un message .

Si tout va bien, vous devriez voir un message dans votre boîte de réception WhatsApp à partir de votre numéro de test.

Message Hello World de Facebook dans la boîte de réception WhatsApp

Jusqu'ici, nous nous en sortons bien ! Faites une pause et ouvrez votre éditeur de code. Ne fermez pas encore l'onglet de votre navigateur car nous serons de retour dans le tableau de bord Meta Developer dans quelques minutes.

Étape 2 : Configurer des webhooks pour recevoir des messages

Maintenant que notre configuration peut envoyer des messages avec succès, configurons un moyen de recevoir des messages. Il est temps de se salir les mains et de se plonger dans l'écriture de code. Tout le code que nous écrirons pour ce tutoriel se trouve dans ce référentiel GitHub .

Créez un nouveau dossier pour contenir notre projet. Ouvrez ce dossier dans un terminal et exécutez le script ci-dessous :

npm init ---yes

Ensuite, nous installons quelques packages :

npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev

Voici une brève explication de chacun :

  • Le expresspackage est important pour la configuration de notre serveur. Le serveur contiendra une route qui agira comme notre webhook
  • Le pdfkitpackage sera utilisé pour générer des factures pour nos clients lors de leur paiement
  • Le request package nous aidera à exécuter des requêtes de récupération vers FakeStoreAPI
  • Le whatsappcloudapi_wrappernous aide à envoyer et recevoir des messages WhatsApp

Ensuite, nous allons créer trois fichiers :

  1. ./app.js
  2. ./.env.js
  3. ./routes/index.js

Dans notre ./.env.jsfichier, tapez le code ci-dessous :

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;
    }
};

Dans le même ./.env.jsfichier :

  1. Remplacez la valeur de Meta_WA_accessTokenpar le jeton d'accès temporaire pour votre application Meta
  2. Remplacez la valeur de Meta_WA_SenderPhoneNumberIdpar votre ID de numéro de téléphone
  3. Remplacez la valeur de Meta_WA_wabaIdpar votre ID de compte WhatsApp Business
  4. Définissez votre propre valeur pour le Meta_WA_VerifyToken. Il peut s'agir d'une chaîne ou d'un nombre ; vous verrez comment nous l'utilisons dans l'étape webhooks

Le code ci-dessus importe d'abord les variables d'environnement actuelles et les déstructure, puis ajoute de nouvelles variables d'environnement et exporte la combinaison des deux en tant qu'objet.

Dans le fichier ./app.jsfile, insérez le code ci-dessous :

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();

La première ligne du bloc de code ci-dessus importe simplement le ./.env.jsfichier et l'affecte à process.env, qui est un objet globalement accessible dans Node.js.

Dans le fichier ./routes/index.js, insérez le code ci-dessous :

'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;

Ensuite, ouvrez le terminal et exécutez :

nodemon app.js

Le serveur Express fonctionnera sur le port 9000.

Ensuite, ouvrez un autre terminal séparé et exécutez :

ngrok http 9000

Cette commande expose notre application Express à Internet au sens large. Le but ici est de configurer un webhook que WhatsApp Cloud peut pinger.

Prenez note de l'URL que ngrok attribue à votre serveur Express. Dans mon exemple, ngrok m'a donné cette URL : https://7b9b-102-219-204-54.ngrok.io. Gardez le serveur Express et le terminal ngrok en cours d'exécution.

Ensuite, reprenons notre travail dans le tableau de bord Meta Developer. Faites défiler jusqu'à la partie intitulée Configurer les Webhooks pour recevoir des messages , puis cliquez sur Configurer les Webhooks . Le lien affichera une page qui ressemble à la capture d'écran ci-dessous :

Page de configuration des webhooks

Cliquez sur le bouton Modifier et une fenêtre contextuelle s'affichera.

Dans le champ URL de rappel, collez l'URL que ngrok vous a envoyée et ajoutez-y la route de rappel, comme dans la ./routes/index.jsdirective. Mon URL complète, dans ce cas, est https://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl.

Dans le champ Verify token , entrez la valeur de Meta_WA_VerifyToken telle qu'elle apparaît dans votre ./.env.jsfichier.

Saisie d'une valeur dans le champ Vérifier le jeton

Cliquez ensuite sur Vérifier et enregistrer .

Si vous l'avez bien configuré, vous verrez un console.logmessage dans le terminal de votre serveur Express indiquant :

GET : Quelqu'un me contacte !

Configuration de notre serveur Express

Maintenant, faisons en sorte que notre serveur Express reçoive les messages d'abonnement de Meta.

Sur le même écran de tableau de bord Meta Developers, cliquez sur Gérer et une fenêtre contextuelle apparaîtra.

Gérer la fenêtre contextuelle des messages d'abonnement au serveur express

Sélectionnez Messages et cliquez sur Test , qui se trouve sur la même ligne.

Vous devriez voir un console.logmessage dans le terminal de votre serveur Express indiquant :

POST : Quelqu'un me contacte !

Si vous avez vu cela, revenez à la même fenêtre contextuelle et cliquez sur S'abonner dans la même ligne de message. Ensuite, cliquez sur Terminé .

Etape 3 : Ecrire notre logique métier

Configuration d'une source de données de commerce électronique

Tout d'abord, nous allons configurer notre logique pour récupérer les données de FakeStoreAPI, générer une facture PDF et générer un lieu de retrait de commande fictif. Nous encapsulerons cette logique dans une classe JavaScript, que nous importerons ensuite dans la logique de notre application.

Créez un fichier et nommez-le ./utils/ecommerce_store.js. Dans ce fichier, collez le code suivant :

'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)
        ];
    }
};

Dans le code ci-dessus, nous avons créé une classe appelée EcommerceStore.

La première méthode, _fetchAssistant, reçoit un point de terminaison qu'elle utilise pour envoyer un ping à fakestoreapi.com .

Les méthodes suivantes agissent comme des générateurs de requêtes pour la première méthode :

  1. getProductById reçoit un identifiant de produit, puis obtient des données relatives à ce produit spécifique
  2. getAllCategories récupère toutes les catégories qui sont dans fakestoreapi.com
  3. getProductsInCategory reçoit une catégorie de produits, puis procède à la récupération de tous les produits de cette catégorie spécifique

Ces générateurs de requêtes invoqueront la première méthode.

Ensuite, la méthode generatePDFInvoice reçoit un morceau de texte et un chemin de fichier. Il crée ensuite un document PDF, écrit le texte dessus, puis stocke le document dans le chemin de fichier fourni.

La méthode generateRandomGeoLocation renvoie simplement une géolocalisation aléatoire. Cette méthode sera utile lorsque nous enverrons le lieu de retrait de commande de notre boutique à un client qui souhaite récupérer son article.

Configuration des sessions client

Pour gérer notre parcours client, nous devons conserver une session qui inclut un profil client et son panier. Chaque client aura donc sa propre session unique.

En production, nous pourrions utiliser une base de données telle que MySQL, MongoDB ou autre chose de résilient, mais pour que notre didacticiel reste léger et court, nous utiliserons la structure de données d'ES2015Map . Avec Map, nous pouvons stocker et récupérer des données spécifiques et itérables, telles que des données client uniques.

Dans votre ./routes/index.jsfichier, ajoutez le code suivant juste au-dessus de 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

La première ligne importe la EcommerceStoreclasse, tandis que la deuxième ligne l'initialise. La troisième ligne crée la session du client que nous utiliserons pour stocker le parcours du client.

Initialisation de notre API WhatsApp Cloud

Vous souvenez-vous du whatsappcloudapi_wrapperpackage que nous avons installé plus tôt ? Il est temps de l'importer et de l'initialiser.

Dans le ./routes/index.jsfichier, ajoutez les lignes de code suivantes sous la déclaration du routeur 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,
});

Les valeurs suivantes sont des variables d'environnement que nous avons définies dans notre ./.env.jsfichier :

  • process.env.Meta_WA_accessToken
  • process.env.Meta_WA_SenderPhoneNumberId
  • process.env.Meta_WA_wabaId

Nous initialisons la classe WhatsAppCloudAPI avec les trois valeurs ci-dessus et nommons notre instance Whatsapp.

Ensuite, analysons toutes les données qui arrivent dans le /meta_wa_callbackurlwebhook POST. En analysant le corps des requêtes, nous pourrons extraire des messages et d'autres détails, comme le nom de l'expéditeur, le numéro de téléphone de l'expéditeur, etc.

Remarque : toutes les modifications de code que nous effectuons à partir de ce point seront entièrement effectuées dans le ./routes/index.jsfichier.

Ajoutez les lignes de code suivantes sous la parenthèse ouvrante de l' try{instruction :

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
        }

Désormais, lorsqu'un client nous envoie un message, notre webhook devrait le recevoir. Le message est contenu dans le corps de la requête du webhook. Pour extraire des informations utiles du corps de la requête, nous devons transmettre le corps à la parseMessageméthode de l'instance WhatsApp.

Ensuite, à l'aide d'une ifinstruction, nous vérifions si le résultat de la méthode contient un message WhatsApp valide.

À l'intérieur de l' ifinstruction, nous définissons incomingMessage, qui contient le message. Nous définissons également d'autres variables :

  • recipientPhoneest le numéro du client qui nous a envoyé un message. Nous leur enverrons une réponse par message, d'où le préfixe "destinataire"
  • recipientNameest le nom du client qui nous a envoyé un message. C'est le nom qu'ils se sont donné dans leur profil WhatsApp
  • typeOfMsgest le type de message qu'un client nous envoie. Comme nous le verrons plus tard, certains messages sont de simples textes, tandis que d'autres sont des réponses à des boutons (ne vous inquiétez pas, cela aura bientôt du sens !)
  • message_idest une chaîne de caractères qui identifie de manière unique un message que nous avons reçu. Ceci est utile lorsque nous voulons effectuer des tâches spécifiques à ce message, telles que marquer un message comme lu

Jusqu'à présent, tout semble bien, mais nous vous confirmerons sous peu.

Comprendre et répondre à l'intention de nos clients

Étant donné que notre didacticiel ne plongera dans aucune forme d'IA ou de traitement du langage naturel (PNL), nous allons définir notre flux de discussion avec une if…elselogique simple.

La logique de conversation démarre lorsque le client envoie un SMS. Nous ne regarderons pas le message lui-même, donc nous ne saurons pas ce qu'ils avaient l'intention de faire, mais nous pouvons dire au client ce que notre bot peut faire.

Donnons à notre client un contexte simple, auquel il peut répondre avec une intention spécifique.

Nous donnerons au client deux boutons :

  1. Un qui nous fait savoir qu'ils veulent parler à un humain réel, pas à un chatbot
  2. Un autre pour parcourir les produits

Pour cela, insérez le code suivant ci-dessous 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',
            },
        ],
    });
}

La ifdéclaration ci-dessus nous permet uniquement de gérer les messages texte.

La sendSimpleButtonsméthode nous permet d'envoyer des boutons à un client. Prenez note des propriétés titleet id. Le titleest ce que le client verra, et le idest ce que nous utiliserons pour savoir sur quel bouton le client a cliqué.

Vérifions si nous avons bien fait. Ouvrez votre application WhatsApp et envoyez un SMS au compte professionnel WhatsApp.

Envoi de SMS vers le compte professionnel WhatsApp

Si vous obtenez une réponse comme la capture d'écran ci-dessus, félicitations ! Vous venez d'envoyer votre premier message via l'API WhatsApp Cloud.

Étant donné que le client peut cliquer sur l'un ou l'autre des deux boutons, occupons-nous également du bouton Parler à un humain .

En dehors de l' ifinstruction de la text_messagelogique, insérez le code suivant :

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',
                    },
                ],
            },
        });
    }
};

Le code ci-dessus effectue deux actions :

  1. Envoie un message texte pour informer l'utilisateur qu'il recevra une carte de contact, en utilisant la sendTextméthode
  2. Envoie une carte de contact en utilisant la sendContactméthode

Ce code détecte également l'intention de l'utilisateur à l'aide de l'ID du bouton sur lequel l'utilisateur a cliqué (dans notre cas, l'ID est le incomingMessage.button_reply.id), puis il répond avec les deux options d'action.

Maintenant, revenez à WhatsApp et cliquez sur Parler à un humain . Si vous avez bien fait cela, vous verrez une réponse qui ressemble à ceci :

Envoi de "Parler à un humain" et réception d'une pièce jointe de contact

Lorsque vous cliquez sur la carte de contact que vous avez reçue, vous devriez voir ce qui suit :

La fiche de contact indique le nom complet, l'entreprise et deux numéros de téléphone

Ensuite, travaillons sur le bouton Afficher certains produits .

À l'intérieur de l' simple_button_message ifinstruction, mais juste en dessous et à l'extérieur de l' speak_to_human ifinstruction, ajoutez le code suivant :

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)
    });
}

Voici ce que fait le code ci-dessus :

  1. La ifdéclaration garantit que l'utilisateur a cliqué sur le bouton Afficher certains produits
  2. Récupère les catégories de produits FakeStoreAPIvia la getAllCategoriesméthode
  3. Limite le nombre de boutons à trois en utilisant la méthode de tableau — slice(0,3)— parce que WhatsApp ne nous permet d'envoyer que trois boutons simples
  4. Il parcourt ensuite chaque catégorie, créant un bouton avec un title et un identifiant unique préfixé parcategory_
  5. Avec la sendSimpleButtonsméthode, on envoie ces boutons au client

Revenez à votre application WhatsApp et cliquez sur Voir plus de produits . Si vous avez bien suivi les étapes ci-dessus, vous devriez voir une réponse qui ressemble à la capture d'écran ci-dessous :

Envoi "voir certains produits" dans le chat WhatsApp

Récupération des produits par catégorie

Maintenant, créons la logique pour obtenir des produits dans la catégorie que le client a sélectionnée.

Toujours à l'intérieur de l' simple_button_message ifinstruction, mais en dessous et à l'extérieur de l' see_categories ifinstruction, ajoutez le code suivant :

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,
    });
}

La ifdéclaration ci-dessus confirme que le bouton sur lequel le client a cliqué était bien le bouton qui contient une catégorie.

La première chose que nous faisons ici est d'extraire la catégorie spécifique de l'ID du bouton. Ensuite, nous interrogeons notre FakeStoreAPI pour les produits appartenant à cette catégorie spécifique.

Après interrogation, nous recevons la liste des produits à l'intérieur d'un tableau, listOfProducts.data. Nous parcourons maintenant ce tableau et, pour chaque produit qu'il contient, nous extrayons son prix, son titre, sa description et son identifiant.

Nous ajoutons product_au id, ce qui nous aidera à sélectionner la sélection d'un client à l'étape suivante. Assurez-vous de réduire la longueur de l'identifiant, du titre et de la description conformément aux restrictions du bouton radio (ou de la liste) de l'API WhatsApp Cloud .

Nous renvoyons ensuite trois valeurs : ID, titre et description. Étant donné que WhatsApp ne nous autorise qu'un maximum de 10 lignes, nous limiterons le nombre de produits à 10 en utilisant la méthode de tableau .slice(0,10).

Après cela, nous invoquons la sendRadioButtonsméthode pour envoyer les produits aux clients. Prenez note des propriétés , , et . headerTextbodyTextfooterTextlistOfSections

Revenez à l'application WhatsApp et cliquez sur n'importe quelle catégorie de produits. Si vous avez bien suivi les instructions, vous devriez voir une réponse qui ressemble à la capture d'écran ci-dessous :

Choix de la catégorie électronique et réception de la réponse

Lorsque vous cliquez sur Sélectionner un produit , vous devriez voir l'écran suivant :

Sélectionner un écran contextuel de produitÀ ce stade, les clients peuvent sélectionner un produit qu'ils trouvent intéressant, mais pouvons-nous savoir ce qu'ils ont sélectionné ? Pas encore, alors travaillons sur cette partie.

En dehors de l' simple_button_message ifénoncé, ajoutons un autre ifénoncé :

if (typeOfMsg === 'radio_button_message') {
    let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
    
}

Dans l' ifinstruction ci-dessus et juste en dessous de selectionId, ajoutez le code suivant :

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',
            },
        ],
    });
}

Le code ci-dessus effectue les opérations suivantes :

  1. Extrait l'ID du produit du bouton radio sur lequel le client a cliqué
  2. Interroge FakeStoreAPI avec cet ID de produit
  3. Lorsqu'il reçoit et extrait les données du produit, il formate le texte. WhatsApp utilise des traits de soulignement pour rendre le texte en italique, tandis que les astérisques rendent le texte en gras
  4. Rendre l'emoji étoile à l'aide de la emojiRatingfonction. Si une note est de 3,8, cela rendra les emojis trois étoiles
  5. Attache l'image du produit au texte rendu et l'envoie en utilisant la sendImageméthode

Après cela, nous envoyons au client une liste de trois boutons en utilisant le sendSimpleButtons. L'un donne au client la possibilité d'ajouter des produits à son panier. Prenez note de l'ID du bouton précédé de add_to_cart_.

Maintenant, revenez à votre application WhatsApp et sélectionnez un produit. Si vous avez suivi les instructions correctement, vous devriez voir une réponse qui ressemble à la capture d'écran suivante :

Chatbot envoie au client trois boutons sélectionnables

Création de sessions pour stocker les paniers des clients

Pour garder une trace des produits qu'un client ajoute à son panier, nous devons disposer d'un endroit pour stocker les articles du panier. C'est ici CustomerSessionqu'entre en jeu. Ajoutons-y un peu de logique.

En dehors de l' radio_button_message ifinstruction, et juste en dessous de la message_iddéclaration, ajoutez le code suivant :

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...

Le code ci-dessus vérifie si la session d'un client a été créée. S'il n'a pas été créé, il crée une nouvelle session qui est identifiée de manière unique par le numéro de téléphone du client. Nous initialisons ensuite une propriété appelée cart, qui commence par un tableau vide.

La addToCartfonction prend en compte a product_idet le numéro du client spécifique. Il envoie ensuite un ping à FakeStoreAPI pour les données du produit spécifique et pousse le produit dans le carttableau.

Ensuite, la listOfItemsInCart fonction prend en compte le numéro de téléphone du client et récupère le , qui lui est associé cart, qui sert à calculer le nombre de produits dans le panier et la somme de leurs prix. Enfin, il renvoie les articles du panier et leur prix total.

La clearCartfonction prend le numéro de téléphone du client et vide le panier de ce client.

Une fois la logique du panier terminée, construisons le bouton Ajouter au panier . Dans l' simple_button_message ifinstruction et sous sa button_iddéclaration, ajoutez le code suivant :

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',
            },
        ],
    });
}

Le code ci-dessus extrait l'ID de produit du bouton sur lequel le client a cliqué, puis appelle la addToCartfonction pour enregistrer le produit dans le panier de la session du client. Ensuite, il extrait le nombre d'articles dans le panier de la session du client et indique au client le nombre de produits dont il dispose. Il envoie également deux boutons, dont l'un permet à l'utilisateur de vérifier.

Prenez note de l'ID du bouton et revenez à votre application WhatsApp. Cliquez sur Ajouter au panier . Si vous avez bien suivi les instructions, vous devriez voir une réponse qui ressemble à la capture d'écran ci-dessous :

Ajouter au panier

Maintenant que nos clients peuvent ajouter des articles au panier, nous pouvons écrire la logique de paiement.

Rédaction de la logique de paiement

À l'intérieur de l' simple_button_message ifinstruction, mais en dehors de l' add_to_cart_ ifinstruction, ajoutez le code suivant :

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 });
}

Le code ci-dessus effectue les opérations suivantes :

  1. Obtient tous les articles dans le panier et les met à l'intérieurfinalBill
  2. Initialise une variable invoiceText, qui contiendra le texte que nous enverrons au client ainsi que le texte qui sera rédigé dans la version PDF de la facture
    1. La forEachboucle concatène simplement le titleet pricede chaque produit à la facture
  3. La generatePDFInvoiceméthode (la même que celle que nous avons définie dans notre EcommerceStoreclasse) prend les détails de la commande, rédige un document PDF et l'enregistre dans le chemin du fichier dans notre répertoire/dossier local que nous lui avons fourni
  4. La sendTextméthode envoie un message texte simple contenant les détails de la commande au client
  5. sendSimpleButtonsenvoie des boutons au client. Prenez note du bouton Imprimer ma facture et de son identifiant
  6. Enfin, la clearCartméthode vide le panier

Maintenant, revenez à votre application WhatsApp et cliquez sur Commander . Si vous avez bien suivi les instructions, vous verrez une réponse qui ressemble à la capture d'écran suivante :

En cliquant sur le bouton de paiement

À ce stade, le client devrait recevoir une facture PDF imprimable. Pour cette raison, travaillons sur une certaine logique concernant le bouton Imprimer ma facture .

Rédaction de notre logique de facture imprimable

À l'intérieur de l' simple_button_message ifinstruction, mais en dehors de l' checkout ifinstruction, ajoutez le code suivant :

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',
  });
}

Le code ci-dessus récupère le document PDF généré à l'étape précédente à partir du système de fichiers local et l'envoie au client à l'aide de la sendDocumentméthode.

Lorsqu'un client commande un produit en ligne, il doit également savoir comment il recevra le produit physique. Pour cette raison, nous avons généré des coordonnées aléatoires en utilisant la generateRandomGeoLocationméthode de la EcommerceStoreclasse et avons envoyé ces coordonnées au client en utilisant la sendLocationméthode pour lui faire savoir où il peut physiquement récupérer son produit.

Maintenant, ouvrez votre application WhatsApp et cliquez sur Imprimer ma facture .

Si vous avez correctement suivi les instructions ci-dessus, vous devriez voir une réponse similaire à la capture d'écran ci-dessous :

Envoyant un SMS "imprimer ma facture" et en recevant un fichier PDF et des instructions pour récupérer le produit.

Affichage des confirmations de lecture aux clients

Enfin, vous avez peut-être remarqué que les coches sous les messages sont grises au lieu de bleues. Cela indique que les messages que nous avons envoyés n'ont pas renvoyé de confirmation de lecture malgré le fait que notre bot les lisait.

Les tiques grises peuvent être frustrantes pour les clients, et pour cette raison, nous devons travailler sur l'affichage des tiques bleues.

En dehors de l' simple_button_message ifinstruction et avant l'accolade fermante de l' data?.isMessage ifinstruction, ajoutez le code suivant :

await Whatsapp.markMessageAsRead({ message_id });

Ce simple one-liner marque un message comme lu dès que nous y avons répondu.

Maintenant, ouvrez votre application WhatsApp et envoyez un message texte aléatoire. Voyez-vous ce que je vois ?

Messages "hey" et le chatbot répond avec le message par défaut

Si vos discussions précédentes ont été mises à jour avec des coches bleues, alors félicitations ! Vous avez atteint la fin de ce didacticiel et appris quelques choses en cours de route.

Dernières pensées

Avec un grand total de 2 milliards d'utilisateurs actifs par mois, ignorer WhatsApp en tant que stratégie de commerce électronique est un moyen sûr de prendre du retard sur la concurrence de votre entreprise, et puisque la plupart de vos clients utilisent déjà WhatsApp dans leurs activités quotidiennes, pourquoi ne pas t votre entreprise les rencontrer là-bas?

J'espère que ce tutoriel a été utile pour démystifier l'API WhatsApp Cloud, et j'espère que vous vous êtes bien amusé en cours de route. Faites-moi savoir quels autres sujets pourraient vous intéresser, et n'oubliez pas de partager cet article avec vos cercles techniques.

 Source : https://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/

#whatsapp #ecommerce #cloud #api #nodejs 

Créez Une Application De Commerce Électronique Automatisée
山岸  英樹

山岸 英樹

1658834400

WhatsAppCloudAPIとNode.jsを使用して自動化されたeコマースアプリを構築します

2022年5月、Meta(WhatsAppを所有する以前はFacebookとして知られていた会社)は、WhatsAppBusinessAPIを一般に公開すると発表しました。この記事は、WhatsAppチャットボットがリードの生成、注文の受信、予定のスケジュール設定、調査の実行、顧客フィードバックの取得、スケーラブルなカスタマーサポートの提供、請求書と領収書の送信などを支援するMetaの機会の世界にあなたを歓迎することを目的としています。

このチュートリアルでは、WhatsAppチャットボットを最初から構築するための技術的な部分について詳しく説明します。

このチュートリアルが終了すると、独自のWhatsAppチャットボットが作成されます。

私たちのチュートリアルは、家庭用品とファストファッションを販売するシンプルなママとポップのeコマースショップに焦点を当てています。このビジネスには、顧客がeコマースストアから閲覧して購入できるWhatsAppチャットボットがあります。

すべてのeコマースストアには商品(価格、名前、説明など)が必要です。このチュートリアルでは、FakeStoreAPIのダミー商品を使用します。

前提条件

先に進む前に、この記事では次のことを前提としています。

ステップ1:MetaDeveloperダッシュボードでアプリを構成する

MetaのAPIを使用するための最初のステップは、Metaダッシュボードにアプリを作成することです。これは無料で実行できます。

ビジネスアプリの種類の選択

  • 次に、アプリの名前とメールアドレスを入力し、このアプリに関連付けるページ/ビジネスを選択します

アプリに名前を付け、それに関連付けられているページを選択する

  • フォームを送信すると、次のような画面が表示されます。

WhatsAppセットアップの選択

この画面で、WhatsAppを選択し、[設定]ボタンをクリックします。

次に、以下に示すように、新しい画面が表示されます。

スタートページ

この画面で、次の点に注意してください。

  • メタアプリに関連付けられているIDであるアプリID 。私のは1184643492312754
  • 一時アクセストークン。24時間後に有効期限が切れます。EAAQ1bU6LdrIBA私のは…で始まります
  • 顧客にメッセージを送信するために使用するテスト電話番号。私のは+1 555 025 3483
    • 電話番号ID 。私のは113362588047543
    • WhatsAppビジネスアカウントID。私のは102432872486730

一時アクセストークンは24時間後に期限切れになることに注意してください。その時点で、トークンを更新する必要があります。アプリをライブモードに切り替えると、永続的なアクセストークンを申請できます。これは、アプリが開発モードであるため、行う必要はありません。

電話番号IDとWhatsAppビジネスアカウントIDは、テスト電話番号に関連付けられています。

次に、メッセージの受信に使用する電話番号を追加しましょう。

開発モードでは、スパム/誤用を防ぐために、メタは5つの受信者番号に制限します。ライブ/プロダクションモードでは、番号はお客様の電話番号を表します。

以下のスクリーンショットに示すように、 [受信者の電話番号を選択して]をクリックし、独自のWhatsApp番号を追加します。

受信者の電話番号ダイアログボックスを追加する

受信者番号を追加すると、次のような画面が表示されます。Facebookページ、Meta Business Suite、Meta開発者ダッシュボードなどのMetaプラットフォームに電話番号を追加するのが初めての場合は、Facebook BusinessからOTPメッセージが届き、実際に受信者番号を所有していることを確認するよう求められます。 。

APIを使用してメッセージを送信する

セットアップのテスト

このステップまでのすべてがうまく機能したかどうかをテストしてみましょう。これを行うには、[メッセージの送信]ボタンをクリックします。

すべてが順調であれば、テスト番号からWhatsApp受信ボックスにメッセージが表示されます。

WhatsApp受信ボックスのFacebookからのHelloWorldメッセージ

これまでは順調です!一時停止して、コードエディタを開きます。数分後にMetaDeveloperダッシュボードに戻るため、まだブラウザタブを閉じないでください。

ステップ2:メッセージを受信するようにWebhookを設定する

セットアップでメッセージを正常に送信できるようになったので、メッセージを受信する方法をセットアップしましょう。手を汚して、コードの記述に没頭する時が来ました。このチュートリアル用に作成するすべてのコードは、このGitHubリポジトリにあります。

プロジェクトを含む新しいフォルダーを作成します。ターミナルでこのフォルダーを開き、以下のスクリプトを実行します。

npm init ---yes

次に、いくつかのパッケージをインストールします。

npm install express pdfkit request whatsappcloudapi_wrapper
npm install nodemon --dev

それぞれの簡単な説明は次のとおりです。

  • このexpressパッケージは、サーバーをセットアップするために重要です。サーバーには、Webhookとして機能するルートが含まれます
  • このpdfkitパッケージは、お客様がチェックアウトするときに請求書を生成するために使用されます
  • このrequest パッケージは、FakeStoreAPIへのフェッチリクエストの実行に役立ちます
  • WhatsAppメッセージのwhatsappcloudapi_wrapper送受信に役立ちます

次に、3つのファイルを作成します。

  1. ./app.js
  2. ./.env.js
  3. ./routes/index.js

この./.env.jsファイルに、次のコードを入力します。

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;
    }
};

同じ./.env.jsファイル内:

  1. の値をメタアプリMeta_WA_accessTokenの一時アクセストークンに置き換えます
  2. Meta_WA_SenderPhoneNumberIdの値を電話番号IDに置き換えます
  3. Meta_WA_wabaIdの値をWhatsAppビジネスアカウントIDに置き換えます
  4. に独自の値を設定しますMeta_WA_VerifyToken。文字列または数値のいずれかです。Webhookのステップでどのように使用するかがわかります

上記のコードは、最初に現在の環境変数をインポートして構造を解除し、次に新しい環境変数を追加して、2つの組み合わせをオブジェクトとしてエクスポートします。

ファイル./app.jsファイルに、次のコードを挿入します。

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();

上記のコードブロックの最初の行は、ファイルをインポートして、Node.jsでグローバルにアクセス可能なオブジェクトであるに./.env.js割り当てます。process.env

ファイル./routes/index.jsに、次のコードを挿入します。

'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;

次に、ターミナルを開いて実行します。

nodemon app.js

Expressサーバーはポート9000で実行されます。

次に、別の別のターミナルを開いて、次のコマンドを実行します。

ngrok http 9000

このコマンドは、Expressアプリをより広範なインターネットに公開します。ここでの目標は、WhatsAppCloudがpingできるWebhookを設定することです。

ngrokがExpressサーバーに割り当てるURLをメモします。私の例では、ngrokは私に次のURLを発行しました:https://7b9b-102-219-204-54.ngrok.io。Expressサーバーとngrokターミナルの両方を実行し続けます。

次に、MetaDeveloperダッシュボードで作業を再開しましょう。「メッセージを受信するためのWebhookの構成」というタイトルの部分までスクロールし、「 Webhookの構成」をクリックします。リンクには、以下のスクリーンショットのようなページが表示されます。

Webhook設定ページ

[編集]ボタンをクリックすると、ポップアップが表示されます。

[コールバックURL ]フィールドに、ngrokが発行したURLを貼り付け、./routes/index.jsディレクティブのようにコールバックルートを追加します。この場合、私の完全なURLはですhttps://7b9b-102-219-204-54.ngrok.io/meta_wa_callbackurl

[トークンの確認]フィールドに、ファイルに表示されているMeta_WA_VerifyTokenの値を入力し./.env.jsます。

トークンの確認フィールドに値を入力する

次に、[確認して保存]をクリックします。

これを適切に構成するとconsole.log、Expressサーバーの端末に次のようなメッセージが表示されます。

GET:誰かが私にpingを送信しています!

Expressサーバーの構成

それでは、ExpressサーバーがMetaからサブスクリプションメッセージを受信するようにしましょう。

同じMetaDevelopersダッシュボード画面で、[管理]をクリックすると、ポップアップが表示されます。

ExpressServerサブスクリプションメッセージのポップアップを管理する

[メッセージ]を選択し、同じ行にある[テスト]をクリックします。

Expressサーバーの端末に次のようなconsole.logメッセージが表示されます。

POST:誰かが私にpingを送信しています!

これが表示された場合は、同じポップアップに戻り、同じメッセージ行の[購読]をクリックします。その後、[完了]をクリックします。

ステップ3:ビジネスロジックを書く

eコマースデータソースの構成

まず、FakeStoreAPIからデータをフェッチし、PDFの請求書を生成し、ダミーの注文受け取り場所を生成するロジックを設定します。このロジックをJavaScriptクラスにラップし、それをアプリのロジックにインポートします。

ファイルを作成し、名前を付けます./utils/ecommerce_store.js。このファイルに、次のコードを貼り付けます。

'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)
        ];
    }
};

上記のコードでは、というクラスを作成しましたEcommerceStore

最初のメソッドは、 fakestoreapi.com_fetchAssistantへのpingに使用するエンドポイントを受け取ります。

次のメソッドは、最初のメソッドのクエリビルダーとして機能します。

  1. getProductById 製品IDを受け取り、その特定の製品に関連するデータを取得します
  2. getAllCategories fakestoreapi.comにあるすべてのカテゴリをフェッチします
  3. getProductsInCategory 製品のカテゴリを受け取り、その特定のカテゴリのすべての製品のフェッチに進みます

これらのクエリビルダーは、最初のメソッドを呼び出します。

次に進むと、メソッドgeneratePDFInvoice はテキストとファイルパスを受け取ります。次に、PDFドキュメントを作成し、その上にテキストを書き込んでから、指定されたファイルパスにドキュメントを保存します。

このメソッドgenerateRandomGeoLocation は、ランダムなジオロケーションを返すだけです。この方法は、当店の注文受付場所を、商品の受け取りを希望するお客様に送信する場合に役立ちます。

カスタマーセッションの構成

カスタマージャーニーを処理するには、顧客プロファイルとそのカートを含むセッションを維持する必要があります。したがって、各顧客は独自のセッションを持ちます。

本番環境では、MySQL、MongoDB、またはその他の復元力のあるデータベースを使用できますが、チュートリアルを簡潔に保つために、ES2015のMapデータ構造を使用します。を使用Mapすると、一意の顧客データなど、特定の反復可能なデータを保存および取得できます。

./routes/index.jsファイルに、次のコードをすぐ上に追加します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

最初の行はクラスをインポートしEcommerceStore、2番目の行はクラスを初期化します。3行目は、顧客の旅を保存するために使用する顧客のセッションを作成します。

WhatsAppCloudAPIの初期化

whatsappcloudapi_wrapper以前にインストールしたパッケージを覚えていますか?インポートして初期化する時が来ました。

./routes/index.jsファイルで、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,
});

./.env.js次の値は、ファイルで定義した環境変数です。

  • process.env.Meta_WA_accessToken
  • process.env.Meta_WA_SenderPhoneNumberId
  • process.env.Meta_WA_wabaId

クラスWhatsAppCloudAPIを上記の3つの値で初期化し、インスタンスに名前を付けますWhatsapp

次に、/meta_wa_callbackurlPOSTWebhookに入ってくるすべてのデータを解析しましょう。リクエストの本文を解析することで、メッセージや、送信者の名前、送信者の電話番号などの詳細を抽出できます。

注意:この時点から行うすべてのコード編集は、完全に./routes/index.jsファイル内で行われます。

try{ステートメントの開始括弧の下に次のコード行を追加します。

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
        }

これで、顧客がメッセージを送信すると、Webhookがメッセージを受信するはずです。メッセージはWebhookのリクエスト本文に含まれています。parseMessageリクエストの本文から有用な情報を抽出するには、WhatsAppインスタンスのメソッドに本文を渡す必要があります。

次に、ifステートメントを使用して、メソッドの結果に有効なWhatsAppメッセージが含まれているかどうかを確認します。

ステートメント内で、メッセージを含むifを定義incomingMessageします。他の変数も定義します。

  • recipientPhoneメッセージを送信したお客様の番号です。メッセージの返信を送信するため、プレフィックス「recipient」
  • recipientNameメッセージを送ってくださったお客様のお名前です。これは、WhatsAppプロファイルで自分で設定した名前です
  • typeOfMsgお客様が当社に送信したメッセージの種類です。後で見るように、いくつかのメッセージは単純なテキストですが、他のメッセージはボタンへの返信です(心配しないでください、これはすぐに意味があります!)
  • message_id受信したメッセージを一意に識別する文字列です。これは、メッセージに既読のマークを付けるなど、そのメッセージに固有のタスクを実行する場合に役立ちます。

これまでのところ、すべて順調に見えますが、まもなく確認します。

お客様の意図を理解し、それに対応する

このチュートリアルでは、AIや自然言語処理(NLP)の形式について詳しく説明しないため、単純なif…elseロジックを使用してチャットフローを定義します。

会話ロジックは、顧客がテキストメッセージを送信したときに開始されます。メッセージ自体は確認しないため、メッセージの意図はわかりませんが、ボットで何ができるかをお客様に伝えることはできます。

お客様に簡単なコンテキストを提供して、特定の意図で返信できるようにしましょう。

お客様に2つのボタンを提供します。

  1. チャットボットではなく、実際の人間と話したいことを知らせてくれるもの
  2. 製品を閲覧するための別の

これを行うには、以下のコードを挿入します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',
            },
        ],
    });
}

上記のifステートメントでは、テキストメッセージのみを処理できます。

このsendSimpleButtons方法では、ボタンを顧客に送信できます。titleおよびidプロパティに注意してください。これtitleは顧客に表示されるものでありid、顧客がクリックしたボタンを知るために使用するものです。

これが正しく行われたかどうかを確認しましょう。WhatsAppアプリを開き、テキストメッセージをWhatsAppビジネスアカウントに送信します。

WhatsAppビジネスアカウントにテキストメッセージを送信する

上のスクリーンショットのような応答があったら、おめでとうございます!WhatsAppCloudAPIを介して最初のメッセージを送信しました。

お客様は2つのボタンのいずれかをクリックする可能性があるため、「人間に話す」ボタンにも注意してみましょう。

ifロジックのステートメントの外にtext_message、次のコードを挿入します。

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',
                    },
                ],
            },
        });
    }
};

上記のコードは2つのアクションを実行します。

  1. sendTextこの方法を使用して、連絡先カードを受け取ることをユーザーに伝えるテキストメッセージを送信します
  2. sendContactメソッドを使用して連絡先カードを送信します

このコードは、ユーザーがクリックしたボタンのID(この場合、IDはincomingMessage.button_reply.id)を使用してユーザーの意図も検出し、2つのアクションオプションで応答します。

ここで、WhatsAppに戻り、[人間に話しかける]をクリックします。これを正しく行うと、次のような返信が表示されます。

「人間に話しかける」を送信し、連絡先の添付ファイルを受信する

受け取った連絡先カードをクリックすると、次のように表示されます。

連絡先カードには、氏名、会社名、および2つの電話番号が表示されます

次に、 [いくつかの製品を表示]ボタンで作業しましょう。

ステートメントの内側simple_button_message if、ただしステートメントのすぐ下と外側にspeak_to_human if、次のコードを追加します。

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)
    });
}

上記のコードの機能は次のとおりです。

  1. このifステートメントは、ユーザーが[一部の製品を表示]ボタンをクリックしたことを確認します
  2. メソッドをFakeStoreAPI介してから製品カテゴリを取得しますgetAllCategories
  3. 配列メソッドを使用してボタンの数を3つに制限しますslice(0,3)— —WhatsAppでは3つの単純なボタンしか送信できないため
  4. 次に、各カテゴリをループして、title 接頭辞が付いた一意のIDを持つボタンを作成しますcategory_
  5. このsendSimpleButtons方法では、これらのボタンをお客様に送信します

もう一度WhatsAppアプリに戻り、[その他の製品を表示]をクリックします。上記の手順を正しく実行すると、次のスクリーンショットのような返信が表示されます。

WhatsAppチャットで「いくつかの製品を見る」を送信する

カテゴリ別の商品の取得

それでは、顧客が選択したカテゴリの製品を取得するためのロジックを作成しましょう。

まだステートメントの内側ですが、simple_button_message ifステートメントの下と外側にsee_categories if、次のコードを追加します。

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ステートメントは、顧客がクリックしたボタンが実際にカテゴリを含むボタンであることを確認しています。

ここで最初に行うことは、ボタンのIDから特定のカテゴリを抽出することです。次に、その特定のカテゴリに属する​​製品についてFakeStoreAPIにクエリを実行します。

クエリを実行すると、配列内の製品のリストを受け取りますlistOfProducts.data。ここで、この配列をループし、その中の各製品について、価格、タイトル、説明、およびIDを抽出します。

に追加product_しますid。これは、次のステップで顧客の選択を選択するのに役立ちます。WhatsApp Cloud APIのラジオボタン(またはリスト)の制限に従って、ID、タイトル、および説明の長さをトリミングしてください。

次に、ID、タイトル、説明の3つの値を返します。WhatsAppでは最大10行しか使用できないため、配列メソッドを使用して製品の数を10に制限します.slice(0,10)

その後、sendRadioButtonsメソッドを呼び出して製品を顧客に送信します。プロパティ、、、、およびに注意してください。 headerTextbodyTextfooterTextlistOfSections

WhatsAppアプリに戻り、任意のカテゴリの製品をクリックします。正しい指示に従った場合、以下のスクリーンショットのような返信が表示されます。

エレクトロニクスカテゴリの選択と応答の受信

[製品の選択]をクリックすると、次の画面が表示されます。

製品のポップアップ画面を選択しますこの時点で、顧客は興味のある製品を選択できますが、何を選択したかを知ることはできますか?まだですので、この部分に取り組みましょう。

ステートメントの外に、別のステートメントsimple_button_message ifを追加しましょう。if

if (typeOfMsg === 'radio_button_message') {
    let selectionId = incomingMessage.list_reply.id; // the customer clicked and submitted a radio button
    
}

上記のifステートメント内で、のすぐ下にselectionId、次のコードを追加します。

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',
            },
        ],
    });
}

上記のコードは次のことを行います。

  1. 顧客がクリックしたラジオボタンから製品IDを抽出します
  2. その製品IDを使用してFakeStoreAPIにクエリを実行します
  3. 製品のデータを受信して​​抽出すると、テキストがフォーマットされます。WhatsAppはアンダースコアを使用してテキストをイタリックでレンダリングし、アスタリスクはテキストを太字でレンダリングします
  4. 関数を使用して星の絵文字をレンダリングしemojiRatingます。評価が3.8の場合、3つ星の絵文字がレンダリングされます
  5. 商品の画像をレンダリングされたテキストに添付し、sendImageメソッドを使用して送信します

この後、を使用して3つのボタンのリストをお客様に送信しますsendSimpleButtons。1つは、顧客に商品をカートに追加する機会を提供します。接頭辞が。のボタンIDに注意してくださいadd_to_cart_

次に、WhatsAppアプリに戻り、製品を選択します。指示に正しく従った場合、次のスクリーンショットのような返信が表示されます。

チャットボットは顧客に3つの選択可能なボタンを送信します

顧客カートを保管するためのセッションの構築

顧客がカートに追加した商品を追跡するには、カートの商品を保管する場所が必要です。ここで効果がありCustomerSessionます。それにいくつかのロジックを追加しましょう。

ステートメントの外側でradio_button_message if、宣言のすぐ下にmessage_id、次のコードを追加します。

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...

上記のコードは、顧客のセッションが作成されたかどうかを確認します。作成されていない場合は、顧客の電話番号によって一意に識別される新しいセッションが作成されます。cart次に、空の配列として始まる、というプロパティを初期化します。

このaddToCart関数はproduct_id、特定の顧客の番号を取り込みます。次に、特定の製品のデータについてFakeStoreAPIにpingを実行し、製品をcart配列にプッシュします。

次に、このlistOfItemsInCart 関数は顧客の電話番号を受け取り、関連するを取得しますcart。これは、カート内の製品の数とそれらの価格の合計を計算するために使用されます。最後に、カート内のアイテムとその合計価格を返します。

このclearCart関数は、顧客の電話番号を取り込み、その顧客のカートを空にします。

カートロジックが完了したら、[カートに追加]ボタンを作成しましょう。ステートメント内simple_button_message ifおよびそのbutton_id宣言の下に、次のコードを追加します。

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',
            },
        ],
    });
}

上記のコードは、顧客がクリックしたボタンから製品IDを抽出し、addToCart関数を呼び出して製品を顧客のセッションのカートに保存します。次に、顧客のセッションのカート内のアイテムの数を抽出し、顧客に製品の数を通知します。また、2つのボタンを送信し、そのうちの1つでユーザーがチェックアウトできるようにします。

ボタンIDをメモして、WhatsAppアプリに戻ります。[カートに追加]をクリックします。指示によく従えば、以下のスクリーンショットのような返信が表示されます。

カートに追加

顧客がカートにアイテムを追加できるようになったので、チェックアウトのロジックを記述できます。

チェックアウトロジックの記述

ステートメントの内側でsimple_button_message ifステートメントの外側にadd_to_cart_ if、次のコードを追加します。

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 });
}

上記のコードは次のことを行います。

  1. カート内のすべてのアイテムを取得し、中に入れますfinalBill
  2. 変数を初期化します。この変数invoiceTextには、顧客に送信するテキストと、PDFバージョンの請求書にドラフトされるテキストが含まれます。
    1. ループは、各製品のとを請求書に連結forEachするだけです。titleprice
  3. このgeneratePDFInvoiceメソッド(クラスで定義したものと同じEcommerceStore)は、注文の詳細を受け取り、PDFドキュメントをドラフトし、提供したローカルディレクトリ/フォルダーのファイルパスに保存します。
  4. このsendTextメソッドは、注文の詳細を含む簡単なテキストメッセージを顧客に送信します
  5. sendSimpleButtonsいくつかのボタンを顧客に送信します。[請求書を印刷]ボタンとそのIDをメモしてください
  6. 最後に、clearCartメソッドはカートを空にします

次に、WhatsAppアプリに戻り、[チェックアウト]をクリックします。指示によく従うと、次のスクリーンショットのような返信が表示されます。

チェックアウトボタンをクリックする

この時点で、顧客は印刷可能なPDF請求書を受け取るはずです。このため、[請求書の印刷]ボタンに関するいくつかのロジックに取り組みましょう。

印刷可能な請求書ロジックの作成

ステートメントの内側でsimple_button_message ifステートメントの外側にcheckout if、次のコードを追加します。

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',
  });
}

上記のコードは、前の手順で生成されたPDFドキュメントをローカルファイルシステムから取得し、sendDocumentメソッドを使用して顧客に送信します。

顧客がオンラインで製品を注文するときは、実際の製品をどのように受け取るかについても知る必要があります。このため、クラスのgenerateRandomGeoLocationメソッドを使用してランダムな座標を生成し、メソッドを使用EcommerceStoreしてこれらの座標を顧客に送信sendLocationして、製品を物理的に受け取ることができる場所を顧客に知らせました。

次に、WhatsAppアプリを開き、[請求書を印刷]をクリックします。

上記の手順を正しく実行すると、以下のスクリーンショットのような返信が表示されます。

「請求書を印刷してください」というテキストメッセージを送信し、PDFファイルと製品の受け取り手順を受け取ります。

開封確認を顧客に表示する

最後に、メッセージの下のチェックマークが青ではなく灰色になっていることに気付いたかもしれません。これは、ボットがメッセージを読み取っていたにもかかわらず、送信したメッセージが開封確認を返さなかったことを示しています。

灰色のダニは顧客を苛立たせる可能性があるため、青いダニの表示に取り組む必要があります。

ステートメントの外側で、simple_button_message ifステートメントの最後の中括弧の前にdata?.isMessage if、次のコードを追加します。

await Whatsapp.markMessageAsRead({ message_id });

このシンプルなワンライナーは、返信するとすぐにメッセージを既読としてマークします。

次に、WhatsAppアプリを開き、ランダムなテキストメッセージを送信します。あなたは私が見ているものを見ていますか?

メッセージ「ねえ」とチャットボットはデフォルトのメッセージで応答します

以前のチャットが青いチェックマークで更新されている場合は、おめでとうございます。このチュートリアルの最後に到達し、その過程でいくつかのことを学びました。

最終的な考え

毎月合計20億人のアクティブユーザーがいるため、eコマース戦略としてWhatsAppを無視することは、ビジネスの競争に遅れをとる確実な方法です。ほとんどの顧客はすでに日常の活動でWhatsAppを使用しているので、なぜそうすべきではありませんか。あなたのビジネスはそこで彼らに会いますか?

このチュートリアルがWhatsAppCloudAPIの謎を解くのに役立つことを願っています。また、その過程で楽しんでいただけたことを願っています。他に興味深いトピックを教えてください。この記事を技術者と共有することを忘れないでください。

 ソース:https ://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/

#whatsapp #ecommerce #cloud #api #nodejs 

WhatsAppCloudAPIとNode.jsを使用して自動化されたeコマースアプリを構築します

Build an Automated Ecommerce App with WhatsApp Cloud API and Node.js

In May 2022, Meta (the company formerly known as Facebook, which owns WhatsApp) announced that they were opening up the WhatsApp Business API to the public. This article intends to welcome you to Meta’s world of opportunities, where WhatsApp chatbots can help you generate leads, receive orders, schedule appointments, run surveys, take customer feedback, provide scalable customer support, send invoices and receipts, and more.

This tutorial will dive deep into the technical bits of building a WhatsApp chatbot from scratch.

By the end of this tutorial, you will have created your own WhatsApp chatbot

Our tutorial focuses on a simple mom-and-pop ecommerce shop that sells household items and fast fashion. The business will have a WhatsApp chatbot where customers can browse and buy from the ecommerce store.

 See more at: https://blog.logrocket.com/build-ecommerce-app-whatsapp-cloud-api-node-js/

#whatsapp #ecommerce #cloud #api #nodejs 

Build an Automated Ecommerce App with WhatsApp Cloud API and Node.js
Flutter App

Flutter App

1656035790

How to Design WhatsApp UI in Flutter | WhatsApp Clone UI/UX Design Flutter

Hello Friends, in this video We will teach you how to design whatsapp ui, design whatsapp clone, whatsapp ui design, whatsapp ui kit, whatsapp ui redesign, whatsapp clone flutter, whatsapp ui flutter.

Subscribe: https://www.youtube.com/c/DearProgrammer/featured 

#flutter #whatsapp 

How to Design WhatsApp UI in Flutter | WhatsApp Clone UI/UX Design Flutter