Parte 1: Si no tiene tiempo para leer
- Responder a un comando desconocido, esto podría ser una instrucción o tu mensaje de bienvenida;
- Enviar mensaje regular;
- Enviar imagen;
- Enviar archivo;
- Enviar video;
- Enviar contacto (vCard);
- Enviar producto;
- Crear nuevo grupo, enviar una invitación y enviar mensaje al grupo;
- Recibir y leer mensajes entrantes;
Y si necesitas ayuda, solo escríbenos en el chat de soporte en cualquier página del sitio.
Parte 2: Introducción
¿Qué es un bot de WhatsApp y por qué lo necesitas?
¿Por qué Node.js?
- Programación asíncrona. Node.js es no bloqueante, lo que significa que puede manejar múltiples conexiones simultáneamente, perfecto para un chatbot que necesita gestionar múltiples interacciones a la vez.
- Amplio soporte de la comunidad. Con un ecosistema vibrante y una gran cantidad de módulos gratuitamente disponibles en el registro npm, nunca te sentirás realmente solo programando en Node.js.
- Facilidad de aprendizaje. Si ya estás familiarizado con JavaScript, aprender Node.js será pan comido. Incluso si no lo estás, JavaScript es uno de los lenguajes de programación más fáciles de aprender.
- Nuestro soporte. Estamos encantados de ayudar a los desarrolladores en este lenguaje de programación. Si nos envías un fragmento de tu código donde algo no funciona, será más fácil para nosotros ayudarte, darte una pista o mejorar tu trabajo.
Configuración del entorno de desarrollo
- Node.js y npm. Si no tienes Node.js y npm (Node Package Manager) instalados en tu computadora, necesitarás instalarlos. Puedes descargar la última versión desde el sitio web oficial de Node.js.
- Editor de texto. Cualquier editor de texto servirá, pero IDEs como Visual Studio Code o WebStorm ofrecen características adicionales como depuración y autocompletado que pueden facilitar tu vida.
- Terminal o Símbolo del sistema. Aquí es donde ejecutarás todos tus scripts de Node.js.
Pasos para la instalación
- Paso 1: Instala Node.js y npm. Visita el sitio web oficial de Node.js y descarga el instalador para tu sistema operativo. Ejecuta el instalador y sigue las instrucciones en pantalla. Esto instalará tanto Node.js como npm.
- Paso 2: Configura la carpeta de tu proyecto. Crea una nueva carpeta donde almacenarás todos los archivos relacionados con tu bot de WhatsApp. Navega a la carpeta usando la terminal. Inicializa un nuevo proyecto de Node.js. Esto creará un archivo package.json que contendrá todos los metadatos y dependencias de tu proyecto.
- Paso 3: Instala los paquetes necesarios. Dado que trabajaremos con la API de WhatsApp, necesitaremos instalar algunos paquetes para ayudarnos con la tarea.
Conectando con el proveedor de la API de WhatsApp
Cómo conectar con Whapi.Cloud




Estableciendo los fundamentos del bot de WhatsApp
Inicializando el servidor con Express
npm install express --save
const express = require('express');
const app = express();
const port = 3000;
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}/`);
});
Conceptos básicos de programación asíncrona en Node.js
async function fetchData() {
const data = await getData();
console.log(data);
}
Manejando mensajes entrantes
Hemos explorado todos los matices del trabajo con webhooks en más detalle en nuestra base de conocimientos: Ver artículo sobre webhooks


Enrutamiento y manejo de solicitudes
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
// Handle incoming messages
});
app.listen(3000, () => {
console.log('Server started');
});
app.post('/webhook', async (req, res) => {
const message = req.body.message.text;
if (message === 'hello') {
await sendMessage('Hi there!');
} else if (message === 'help') {
await sendMessage('How can I assist you today?');
}
res.sendStatus(200);
});
Enviar mensajes de WhatsApp usando Node JS
Enviando mensajes de texto
const request = require('request');
const options = {
method: 'POST',
url: 'https://gate.whapi.cloud/messages/text?token=YOUR_API_TOKEN',
headers: {accept: 'application/json', 'content-type': 'application/json'},
body: {typing_time: 10, to: '1234567891@s.whatsapp.net', body: 'Hello, world!'},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
Enviando multimedia, documentos
const request = require('request');
const options = {
method: 'POST',
url: 'https://gate.whapi.cloud/messages/document?token=YOUR_API_TOKEN',
headers: {accept: 'application/json', 'content-type': 'application/json'},
body: {
to: '1234567891@s.whatsapp.net',
media: 'data:application/octet-stream;name=site.webmanifest;base64,ewogICAgIm5hbWUiOiAiIiwKICAgICJzaG9ydF9uYW1lIjogIiIsCiAgICAiaWNvbnMiOiBbCiAgICAgICAgewogICAgICAgICAgICAic3JjIjogIi9hbmRyb2lkLWNocm9tZS0xOTJ4MTkyLnBuZyIsCiAgICAgICAgICAgICJzaXplcyI6ICIxOTJ4MTkyIiwKICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UvcG5nIgogICAgICAgIH0KICAgIF0sCiAgICAidGhlbWVfY29sb3IiOiAiI2ZmZmZmZiIsCiAgICAiYmFja2dyb3VuZF9jb2xvciI6ICIjZmZmZmZmIiwKICAgICJkaXNwbGF5IjogInN0YW5kYWxvbmUiCn0K'
},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});


Trabajando con grupos de WhatsApp usando Node.JS
Obteniendo la lista de grupos
const request = require('request');
const options = {
method: 'GET',
url: 'https://gate.whapi.cloud/groups?token=YOUR_API_TOKEN',
headers: {accept: 'application/json'}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
Contando el número de participantes en el grupo de WhatsApp
request(options, function (error, response, body) {
if (error) throw new Error(error);
const groups = JSON.parse(body);
groups.forEach(group => {
console.log(`Group Name: ${group.name}`);
console.log(`Number of Participants: ${group.participants.length}`);
});
});
Manejando mensajes de grupo
app.post('/webhook', (req, res) => {
const message = req.body;
if (message.from.endsWith('@g.us')) {
// This is a group message
handleGroupMessage(message);
} else if (message.type === 'text') {
// Handle Text Messages
sendTextMessage(message.from, 'You said: ' + message.body);
}
res.status(200).end();
});
function handleGroupMessage(message) {
console.log(`Received a group message from ${message.from}: ${message.body}`);
// Further logic for group messages can be implemented here.
}
Pruebas y depuración
- Descarga ngrok y descomprímelo.
- Abre tu terminal y navega hasta la carpeta donde se encuentra ngrok.
- Ejecuta ./ngrok http NÚMERO_DE_PUERTO, reemplazando NÚMERO_DE_PUERTO con el puerto donde se está ejecutando localmente tu servidor Express.
- Ahora deberías tener una URL pública que puedes usar como URL de webhook en tu panel de Whapi.Cloud.
Implementación y alojamiento
- Instala la CLI de Heroku e inicia sesión.
- Navega al directorio de tu proyecto e inicializa un repositorio git si aún no lo has hecho.
- Ejecuta heroku create para crear una nueva aplicación en Heroku.
- Envía tu código a Heroku usando git push heroku master.
- Abre el panel de Heroku, navega a la configuración de la aplicación y añade tus variables de entorno, incluido tu token de API de Whapi.Cloud.
- Finalmente, establece la URL del webhook en tu panel de Whapi.Cloud a la URL proporcionada por Heroku.
Código fuente de un bot de WhatsApp simple listo para usar en Node.JS
module.exports = {
// API endpoint URL
apiUrl: "https://gate.whapi.cloud",
// API token from your channel
token: "YOUR CHANNEL TOKEN",
// The ID of the group to which we will send the message. Use to find out the ID: https://whapi.readme.io/reference/getgroups
group: '120363167596599603@g.us',
// The ID of the product we will send for the example. Create a product in your WhatsApp and find out the product ID: https://whapi.readme.io/reference/getproducts
product: '6559353560856703',
// Bot`s URL (for static file). Webhook Link to your server. At ( {server link}/messages ), when POST is requested, processing occurs
botUrl: "https://yoursite.com/messages"
}
const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
const fetch = require('node-fetch');
const FormData = require('form-data');
const config = require('./config.js');
process.on('unhandledRejection', err => {
console.log(err)
});
const COMMANDS = {
TEXT: 'Simple text message',
IMAGE: 'Send image',
DOCUMENT: 'Send document',
VIDEO: 'Send video',
CONTACT: 'Send contact',
PRODUCT: 'Send product',
GROUP_CREATE: 'Create group',
GROUP_TEXT: 'Simple text message for the group',
GROUPS_IDS: 'Get the id\'s of your three groups'
}
const FILES = {
IMAGE: './files/file_example_JPG_100kB.jpg',
DOCUMENT: './files/file-example_PDF_500_kB.pdf',
VIDEO: './files/file_example_MP4_480_1_5MG.mp4',
VCARD: './files/sample-vcard.txt'
}
/**
* Send request to Whapi.Cloud
* @param endpoint - endpoint path
* @param params - request body
* @param method - GET, POST, PATCH, DELETE
* @returns {Promise (object) }
*/
async function sendWhapiRequest(endpoint, params= {}, method = 'POST') {
let options = {
method: method,
headers: {
Authorization: `Bearer ${config.token}`
},
};
if (!params.media) options.headers['Content-Type'] = 'application/json';
let url = `${config.apiUrl}/${endpoint}`;
if(params && Object.keys(params).length > 0) {
if(method === 'GET')
url += '?' + new URLSearchParams(params);
else
options.body = params?.media ? toFormData(params) : JSON.stringify(params);
}
const response = await fetch(url, options);
let json = await response.json();
console.log('Whapi response:', JSON.stringify(json, null, 2));
return json;
}
/**
* Convert object to FormData
* @param obj
* @returns {FormData}
*/
function toFormData(obj) {
const form = new FormData();
for (let key in obj) {
form.append(key, obj[key]);
}
return form;
}
async function setHook() {
if (config.botUrl) {
/** type {import('./whapi').Settings} */
const settings = {
webhooks: [
{
url: config.botUrl,
events: [
// default event for getting messages
{type: "message", method: "post"}
],
mode: "method"
}
]
}
await sendWhapiRequest('settings', settings, 'PATCH');
}
}
async function handleNewMessages(req, res){
try {
/** type {import('./whapi').Message[]} */
const messages = req?.body?.messages;
for (let message of messages) {
if (message.from_me) continue;
/** type {import('./whapi').Sender} */
const sender = {
to: message.chat_id
}
let endpoint = 'messages/text';
const command = Object.keys(COMMANDS)[+message.text?.body?.trim() - 1];
switch (command) {
case 'TEXT': {
sender.body = 'Simple text message';
break;
}
case 'IMAGE': {
sender.caption = 'Text under the photo.';
sender.media = fs.createReadStream(FILES.IMAGE);
endpoint = 'messages/image';
break;
}
case 'DOCUMENT': {
sender.caption = 'Text under the document.';
sender.media = fs.createReadStream(FILES.DOCUMENT);
endpoint = 'messages/document';
break;
}
case 'VIDEO': {
sender.caption = 'Text under the video.';
sender.media = fs.createReadStream(FILES.VIDEO);
endpoint = 'messages/video';
break;
}
case 'CONTACT': {
sender.name = 'Whapi Test';
sender.vcard = fs.readFileSync(FILES.VCARD).toString();
endpoint = 'messages/contact';
break;
}
case 'PRODUCT': {
/* you can get real product id using endpoint https://whapi.readme.io/reference/getproducts */
endpoint = `business/products/${config.product}`;
break;
}
case 'GROUP_CREATE': {
/* Warning : you can create group only with contacts from phone contact list */
const res = await sendWhapiRequest(`groups`, {subject: 'Whapi.Cloud Test', participants: [message.chat_id.split('@')[0]]});
sender.body = res.group_id ? `Group created. Group id: ${res.group_id}` : 'Error';
break;
}
case 'GROUP_TEXT': {
/*To get group id, use /groups endpoint */
sender.to = config.group;
sender.body = 'Simple text message for the group';
break;
}
case 'GROUPS_IDS': {
const {groups} = await sendWhapiRequest('groups', {count: 3}, 'GET');
sender.body = groups && groups.reduce((prevVal, currVal, i) => {
return i === 0 ? `${currVal.id} - ${currVal.name}` : prevVal + ',\n ' + `${currVal.id} - ${currVal.name}`;
}, '') || 'No groups';
break;
}
default: {
sender.body = 'Hi. Send me a number from the list. Don\'t forget to change the actual data in the code! \n\n' +
Object.values(COMMANDS).map((text, i) => `${i + 1}. ${text}`).join('\n');
}
}
await sendWhapiRequest(endpoint, sender);
}
res.send('Ok');
} catch (e) {
res.send(e.message);
}
}
// Create a new instance of express
const app = express();
app.use(bodyParser.json());
app.get('/', function (req, res) {
res.send('Bot is running');
});
app.post('/messages', handleNewMessages);
setHook().then(() => {
const port = config.port || (config.botUrl.indexOf('https:') === 0 ? 443 : 80)
app.listen(port, function () {
console.log(`Listening on port ${port}...`);
});
});
- Inicializamos el servidor con Express e instalamos un webhook para manejar los mensajes entrantes.
- Cuando se recibe un mensaje de texto, el bot responde repitiendo el texto recibido.
- Para enviar mensajes, utilizamos las funciones sendTextMessage y sendImageMessage.

