Personaliza la plataforma: marca blanca, pagos, idioma, email y todo lo que necesitas para hacerla tuya.
Personaliza completamente la apariencia de la plataforma para que refleje tu marca:
# Nombre del producto
APP_NAME="Tu Marca Aquí"
# URL base
APP_URL=https://tu-dominio.com
# Color primario (hexadecimal)
APP_PRIMARY_COLOR=#10b981
# Ruta del logo (relativa a /public)
APP_LOGO_PATH=img/logo-custom.png
APP_FAVICON_PATH=img/favicon.ico
# En .env
APP_URL=https://tu-dominio.com
# En Nginx (sites-available)
server_name tu-dominio.com www.tu-dominio.com;
# En Apache (sites-available)
ServerName tu-dominio.com
ServerAlias www.tu-dominio.com
empresa1.tu-dominio.com, mitienda.tu-dominio.com. Para que esto funcione,
necesitas configurar 3 cosas: DNS Wildcard, Servidor Web y SSL Wildcard.
tu-dominio.com → Panel Central (Superadmin)
www.tu-dominio.com → Redirige a tu-dominio.com
empresa1.tu-dominio.com → Panel del Tenant "empresa1"
mitienda.tu-dominio.com → Panel del Tenant "mitienda"
*.tu-dominio.com → Cualquier subdominio → Laravel identifica el tenant
Debes crear un registro DNS de tipo A con el hostname * que apunte a la IP de
tu servidor. Esto hace que cualquier subdominio resuelva a tu servidor automáticamente.
dig NS tu-dominio.com
A*104.236.209.98)3600@ (dominio raíz) apuntando a la misma IP.
# Verificar que el wildcard resuelve correctamente
dig test123.tu-dominio.com +short
# Debe mostrar la IP de tu servidor (ej: 104.236.209.98)
# Verificar el dominio raíz
dig tu-dominio.com +short
# Debe mostrar la misma IP
# Si no resuelve, espera 5-30 minutos (propagación DNS)
# Puedes verificar la propagación global en:
# https://www.whatsmydns.net/#A/*.tu-dominio.com
Tu servidor web debe aceptar requests de cualquier subdominio y dirigirlos a la aplicación Laravel.
Edita tu archivo de configuración principal:
sudo nano /etc/nginx/sites-available/tu-app
Asegúrate de que server_name incluya el wildcard:
server {
listen 80;
# ⚠️ IMPORTANTE: incluir el wildcard *.tu-dominio.com
server_name tu-dominio.com www.tu-dominio.com *.tu-dominio.com;
root /var/www/tu-app/public;
index index.php;
# ... resto de la configuración
}
Después de instalar el SSL (Paso C), tu archivo SSL también debe incluir el wildcard:
server {
listen 443 ssl;
server_name tu-dominio.com www.tu-dominio.com *.tu-dominio.com;
# ...
}
# Verificar y reiniciar
sudo nginx -t
sudo systemctl restart nginx
Un certificado SSL normal solo cubre tu-dominio.com y opcionalmente
www.tu-dominio.com. Para que los subdominios de tenants sean HTTPS, necesitas un
certificado wildcard que cubra *.tu-dominio.com.
# 1. Instalar plugin de DigitalOcean para Certbot
sudo apt install -y python3-certbot-dns-digitalocean
# 2. Crear archivo con tu API token de DigitalOcean
# Genera el token en: https://cloud.digitalocean.com/account/api/tokens
# Permisos: Full Access (Read + Write)
sudo nano /etc/letsencrypt/digitalocean.ini
Contenido del archivo:
dns_digitalocean_token = TU_TOKEN_DE_DIGITALOCEAN_API
# 3. Asegurar permisos del archivo (contiene tu token secreto)
sudo chmod 600 /etc/letsencrypt/digitalocean.ini
# 4. Generar certificado wildcard
sudo certbot certonly \
--dns-digitalocean \
--dns-digitalocean-credentials /etc/letsencrypt/digitalocean.ini \
-d tu-dominio.com \
-d "*.tu-dominio.com"
# 5. Si ya tenías un certificado, Certbot preguntará si expandir.
# Elige "E" (Expand) para agregar el wildcard al certificado existente.
# 6. Verificar que el certificado cubre el wildcard
sudo certbot certificates
# Debe mostrar: Domains: tu-dominio.com *.tu-dominio.com
# 7. Reiniciar servidor web
sudo systemctl restart nginx # o apache2
Después de generar el certificado, verifica que tu servidor web apunte a la ruta correcta:
# Ver ruta del certificado
sudo certbot certificates
# Ejemplo de salida:
# Certificate Path: /etc/letsencrypt/live/tu-dominio.com/fullchain.pem
# Private Key Path: /etc/letsencrypt/live/tu-dominio.com/privkey.pem
Verifica que tu VirtualHost SSL use estas rutas:
# Nginx:
ssl_certificate /etc/letsencrypt/live/tu-dominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tu-dominio.com/privkey.pem;
# Apache:
SSLCertificateFile /etc/letsencrypt/live/tu-dominio.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/tu-dominio.com/privkey.pem
Después de configurar DNS, servidor web y SSL, verifica todo:
# 1. Verificar DNS (debe mostrar la IP de tu servidor)
dig cualquier-subdominio.tu-dominio.com +short
# 2. Verificar HTTP (debe redirigir a HTTPS)
curl -I http://test.tu-dominio.com
# Esperado: HTTP/1.1 301 Moved Permanently
# Location: https://test.tu-dominio.com/
# 3. Verificar HTTPS (debe mostrar 200 OK con certificado válido)
curl -I https://test.tu-dominio.com
# Esperado: HTTP/2 200
# 4. Verificar certificado SSL
echo | openssl s_client -connect test.tu-dominio.com:443 -servername test.tu-dominio.com 2>/dev/null | openssl x509 -noout -subject -dates
# Debe mostrar: subject=CN = tu-dominio.com (wildcard)
| Problema | Causa | Solución |
|---|---|---|
| Subdominio muestra otro sitio (ej: landing page) | El VirtualHost de otro sitio está atrapando el request porque *.tu-dominio.com no
está en el ServerAlias del VirtualHost correcto |
Agregar *.tu-dominio.com en ServerAlias del VirtualHost HTTP y
SSL |
| Subdominio muestra "No es seguro" en HTTPS | El certificado SSL no cubre *.tu-dominio.com |
Generar certificado wildcard con Certbot (ver Paso C arriba) |
dig subdominio.tu-dominio.com no resuelve |
Registro DNS wildcard no configurado, o propagación pendiente | Crear registro A con hostname * en tu DNS. Esperar 5-30 min para
propagación |
| DNS resuelve pero da error 403/404 | El servidor web no está configurado para aceptar el subdominio | Agregar *.tu-dominio.com en server_name (Nginx) o
ServerAlias (Apache)
|
| Subdominio redirige a HTTP y se queda en "no seguro" | Falta regla de redirección HTTPS en .htaccess o Nginx |
Agregar RewriteCond %{HTTPS} off +
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI}
|
| Certbot wildcard falla con error de autenticación | Token de API del proveedor DNS es inválido o no tiene permisos de escritura | Regenerar token con permisos Full Access (Read + Write) |
| Nuevo tenant creado pero su subdominio no funciona | Si DNS wildcard, SSL wildcard y servidor web están bien configurados, el tenant debería funcionar automáticamente | Verificar los 3 pasos (A, B, C). Si todos están correctos, el problema está en la app (verificar
storage/logs/laravel.log)
|
La plataforma soporta 4 idiomas completamente traducidos:
| Código | Idioma | Archivos |
|---|---|---|
es |
🇪🇸 Español | resources/lang/es/ |
en |
🇺🇸 English | resources/lang/en/ |
fr |
🇫🇷 Français | resources/lang/fr/ |
pt |
🇧🇷 Português | resources/lang/pt/ |
# En .env — cambiar idioma predeterminado
APP_LOCALE=es
APP_FALLBACK_LOCALE=es
.env es el predeterminado para nuevos usuarios.AutomatizaNegocios utiliza Evolution API como motor de conexión con WhatsApp. Evolution API es un servicio de código abierto que gestiona las sesiones de WhatsApp, el envío y recepción de mensajes, y la administración de múltiples dispositivos.
Al centralizar la conexión en Evolution API, el sistema queda desacoplado de los cambios internos de WhatsApp. Si WhatsApp actualiza su protocolo, solo necesitarás actualizar tu instancia de Evolution API, sin modificar nada en la plataforma SaaS.
# =======================================
# EVOLUTION API — Conexión con WhatsApp
# =======================================
# URL de tu instancia de Evolution API
# Puede estar en el mismo servidor o en uno separado
EVOLUTION_API_URL=https://evo.tu-dominio.com
# API Key de autenticación (la generas al instalar Evolution API)
EVOLUTION_API_KEY=tu-api-key-secreta-aqui
# Versión de la API (por defecto v2)
EVOLUTION_API_VERSION=v2
# Webhook URL (donde Evolution API notificará mensajes entrantes)
# Debe apuntar a tu instalación de AutomatizaNegocios
EVOLUTION_WEBHOOK_URL=https://tu-dominio.com/api/webhook/evolution
Puedes instalar Evolution API en el mismo servidor que tu SaaS o en un servidor separado (recomendado para producción con alto volumen):
| Escenario | RAM Mínima | RAM Recomendada | vCPUs |
|---|---|---|---|
| Solo Evolution API | 1 GB | 2 GB | 1 |
| Evolution API + Chatwoot | 4 GB | 8 GB | 2 |
| Evolution API + Chatwoot + n8n | 4 GB | 8 GB | 2+ |
cURL error 28: SSL connection timeout.
# 1. Clonar el repositorio
git clone https://github.com/EvolutionAPI/evolution-api.git
cd evolution-api
# 2. Copiar archivo de configuración
cp .env.example .env
# 3. Configurar las variables en .env:
# - SERVER_URL=https://evo.tu-dominio.com
# - AUTHENTICATION_API_KEY=tu-api-key-secreta
# - DATABASE_CONNECTION_URI=mongodb://localhost:27017
# 4. Instalar dependencias e iniciar
npm install
npm run build
npm start
# O con Docker (recomendado):
docker compose up -d
Si usas EasyPanel para gestionar tus servicios Docker, puedes instalar Evolution API como un servicio:
| Variable | Descripción | Ejemplo |
|---|---|---|
EVOLUTION_API_URL |
URL base donde corre Evolution API | https://evo.miempresa.com |
EVOLUTION_API_KEY |
API Key para autenticación | B6D711FC... |
EVOLUTION_API_VERSION |
Versión de la API | v2 |
EVOLUTION_WEBHOOK_URL |
Webhook para mensajes entrantes | https://app.com/api/webhook/evolution |
Desde el Panel Admin → Configuración → WhatsApp puedes verificar el estado de la conexión con Evolution API:
pm2 status o docker ps)# Verificar manualmente desde terminal:
curl -X GET https://evo.tu-dominio.com/instance/fetchInstances \
-H "apikey: tu-api-key-aqui"
# Respuesta esperada: lista de instancias (array JSON)
# Si obtienes error 401: API Key incorrecta
# Si obtienes timeout: URL inaccesible
git pull && npm run build), sin tocar tu aplicación principal. Esto garantiza
continuidad del servicio para todos tus clientes.
# Desde el servidor SaaS, verificar que puede llegar a Evolution API:
# 1. Verificar DNS
dig tu-evolution-api.dominio.com +short
# Debe mostrar una IP
# 2. Verificar conexión TCP al puerto 443
timeout 5 bash -c 'cat < /dev/tcp/EVOLUTION_HOST/443' && echo "CONECTA" || echo "NO CONECTA"
# 3. Verificar respuesta HTTP
curl -I --connect-timeout 10 https://tu-evolution-api.dominio.com
# Debe responder HTTP 200 o 301
# 4. Verificar API con autenticación
curl -X GET https://tu-evolution-api.dominio.com/instance/fetchInstances \
-H "apikey: tu-api-key"
# Debe responder un JSON
Si la conexión falla, verifica:
┌──────────────────────┐
│ AutomatizaNegocios │ ← Tu plataforma SaaS
│ (Laravel + Vue.js) │
└──────────┬───────────┘
│ REST API
▼
┌──────────────────────┐
│ Evolution API │ ← Motor de WhatsApp
│ (Node.js + MongoDB) │
└──────────┬───────────┘
│ WebSocket
▼
┌──────────────────────┐
│ WhatsApp Web │ ← Sesión de WhatsApp
│ (Multi-dispositivo) │
└──────────────────────┘
Cada tenant puede tener múltiples dispositivos. Cada dispositivo crea una instancia en Evolution API con su propia sesión de WhatsApp.
El sistema implementa múltiples capas de protección para simular el comportamiento humano:
| Capa de Protección | Descripción | Configuración Actual |
|---|---|---|
| 🕐 Pausa entre mensajes | Delay aleatorio entre cada mensaje individual | 8-18 segundos (aleatorio) |
| ☕ Pausas extras aleatorias | ~25% de probabilidad de pausa adicional entre mensajes | +5-20 segundos adicionales |
| 📦 Lotes pequeños | Grupos de 5 contactos por lote | 5 contactos por lote |
| ⏸️ Delay entre lotes | Pausa natural entre cada lote de 5 contactos | 15-45 segundos + pausas extra ~20% |
| ✍️ Presencia aleatoria | Simula "escribiendo..." solo ~30% del tiempo | Evita el patrón composing→send repetitivo |
| 📱 Verificación aleatoria | Verifica si el número tiene WhatsApp solo ~50% del tiempo | Evita el patrón check→send repetitivo |
| 👤 Personalización real | Reemplaza {nombre} por el nombre real del contacto |
Hace cada mensaje genuinamente único |
| 🛑 Auto-stop en Error 500 | Si WhatsApp bloquea la cuenta, se detiene la campaña automáticamente para no quemar más contactos | Detención inmediata + notificación |
| Contactos | Tiempo Estimado | Nivel de Riesgo | Recomendación |
|---|---|---|---|
| 25 | ~8 minutos | 🟢 Bajo | Ideal para campañas de prueba |
| 75 | ~25 minutos | 🟢 Bajo | Seguro para números "calentados" |
| 150 | ~50 minutos | 🟡 Medio | Solo con números de +1 mes de antigüedad |
| 250 | ~1.5 horas | 🔴 Alto | Máximo recomendado, usar {nombre} |
| 500+ | ~3+ horas | 🔴 Muy Alto | Dividir en 2-3 campañas con diferentes números |
Un número nuevo de WhatsApp debe construir reputación antes de enviar campañas grandes:
| Semana | Mensajes/día máximo | Qué hacer |
|---|---|---|
| Semana 1 | 20-30 | Enviar mensajes personalizados a contactos conocidos |
| Semana 2 | 50-80 | Campañas pequeñas con respuestas esperadas |
| Semana 3 | 100-150 | Campañas medianas, monitorear restricciones |
| Semana 4+ | 200-300 | Envío normal, aumentar gradualmente |
{nombre} en tus mensajes. El sistema reemplaza
automáticamente {nombre} por el nombre real del contacto"Hola {nombre}, te escribimos para..."Los parámetros del algoritmo anti-spam se pueden ajustar en dos archivos:
# ProccessCampaign.php — Control de lotes
$batchSize = 5; # Contactos por lote
$accumulatedDelay += rand(15, 45); # Delay base entre lotes (seg)
# ~20% probabilidad de pausa extra: +15-60 seg
# ProcessCampaignBatch.php — Control por mensaje
$baseDelay = rand(8, 18); # Pausa entre mensajes (seg)
# ~25% probabilidad de pausa extra: +5-20 seg
# Presencia "escribiendo..." solo ~30% del tiempo
# Verificación de número solo ~50% del tiempo
# Personalización: {nombre} → nombre real del contacto
# Auto-stop en Error 500 (detección de bloqueo)
if ($response['status'] === 500) {
// Detener campaña automáticamente
$this->campaign->update(['status_id' => 4]);
return;
}