{ "name": "📥 Evolution → Krayin | WhatsApp para Lead (Sem Slack)", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "evolution-webhook-noslack", "responseMode": "responseNode", "options": {} }, "id": "webhook-evolution", "name": "Webhook Evolution", "type": "n8n-nodes-base.webhook", "typeVersion": 1, "position": [240, 300], "webhookId": "evolution-whatsapp-webhook-noslack" }, { "parameters": { "conditions": { "string": [ { "value1": "={{$node[\"Webhook Evolution\"].json[\"event\"]}}", "operation": "equal", "value2": "messages.upsert" } ] } }, "id": "filter-new-message", "name": "Filtro: Nova Mensagem", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [460, 300] }, { "parameters": { "jsCode": "// Processar dados da mensagem do Evolution API\nconst webhookData = $node[\"Webhook Evolution\"].json;\n\n// Extrair dados da mensagem\nconst messageData = webhookData.data || {};\nconst fromContact = messageData.key?.remoteJid || '';\nconst messageText = messageData.message?.conversation || \n messageData.message?.extendedTextMessage?.text ||\n messageData.message?.imageMessage?.caption ||\n 'Mídia sem texto';\n\n// Limpar número de telefone (remover sufixos do WhatsApp)\nconst cleanPhoneNumber = (phone) => {\n return phone.replace('@s.whatsapp.net', '')\n .replace('@g.us', '')\n .replace('@c.us', '')\n .replace(/\\D/g, '')\n .replace(/^55/, ''); // Remove código do Brasil se presente\n};\n\n// Verificar se é um grupo\nconst isGroup = fromContact.includes('@g.us');\n\n// Pular grupos por enquanto\nif (isGroup) {\n return { skip: true, reason: 'Mensagem de grupo ignorada' };\n}\n\n// Dados processados\nconst processedData = {\n phone: cleanPhoneNumber(fromContact),\n original_phone: fromContact,\n message_text: messageText,\n timestamp: messageData.messageTimestamp || Math.floor(Date.now() / 1000),\n message_id: messageData.key?.id || '',\n instance: webhookData.instance || 'default',\n formatted_date: new Date((messageData.messageTimestamp || Date.now()) * 1000).toLocaleString('pt-BR'),\n is_from_me: messageData.key?.fromMe || false\n};\n\n// Só processar mensagens recebidas (não enviadas por nós)\nif (processedData.is_from_me) {\n return { skip: true, reason: 'Mensagem enviada por nós - ignorada' };\n}\n\n// Detectar intenção de compra/interesse baseado em palavras-chave\nconst buyingKeywords = [\n 'preço', 'quanto custa', 'valor', 'orçamento', 'comprar', 'adquirir',\n 'interessado', 'interesse', 'como funciona', 'demonstração', 'demo',\n 'teste', 'trial', 'contratar', 'assinar', 'plano', 'proposta',\n 'informação', 'informações', 'detalhes', 'saber mais', 'quero'\n];\n\nconst messageWords = messageText.toLowerCase();\nconst hasBuyingIntent = buyingKeywords.some(keyword => messageWords.includes(keyword));\n\nprocessedData.buying_intent = hasBuyingIntent;\nprocessedData.priority = hasBuyingIntent ? 'ALTA' : 'NORMAL';\n\nreturn processedData;" }, "id": "process-whatsapp-message", "name": "Processar Mensagem WhatsApp", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [680, 300] }, { "parameters": { "conditions": { "boolean": [ { "value1": "={{$node[\"Processar Mensagem WhatsApp\"].json[\"skip\"]}}", "value2": true } ] } }, "id": "check-skip", "name": "Pular Processamento?", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [900, 300] }, { "parameters": { "method": "GET", "url": "https://crm.memudecore.com.br/api/contacts/search", "authentication": "predefinedCredentialType", "nodeCredentialType": "krayin-api", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "phone", "value": "={{$node[\"Processar Mensagem WhatsApp\"].json[\"phone\"]}}" } ] }, "options": {} }, "id": "search-existing-contact", "name": "Buscar Contato Existente", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [1120, 200], "credentials": { "krayin-api": { "id": "krayin-crm-api", "name": "Krayin CRM API" } } }, { "parameters": { "conditions": { "number": [ { "value1": "={{$node[\"Buscar Contato Existente\"].json[\"data\"]?.length || 0}}", "operation": "equal", "value2": 0 } ] } }, "id": "is-new-contact", "name": "Contato Novo?", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [1340, 200] }, { "parameters": { "method": "POST", "url": "https://crm.memudecore.com.br/api/contacts", "authentication": "predefinedCredentialType", "nodeCredentialType": "krayin-api", "sendBody": true, "bodyParameters": { "parameters": [ { "name": "name", "value": "Contato WhatsApp {{$node[\"Processar Mensagem WhatsApp\"].json[\"phone\"]}}" }, { "name": "emails[0][value]", "value": "whatsapp+{{$node[\"Processar Mensagem WhatsApp\"].json[\"phone\"]}}@memudecore.com.br" }, { "name": "contact_numbers[0][value]", "value": "{{$node[\"Processar Mensagem WhatsApp\"].json[\"phone\"]}}" }, { "name": "contact_numbers[0][label]", "value": "WhatsApp" } ] }, "options": {} }, "id": "create-new-contact", "name": "Criar Novo Contato", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [1560, 100], "credentials": { "krayin-api": { "id": "krayin-crm-api", "name": "Krayin CRM API" } } }, { "parameters": { "jsCode": "// Determinar qual contato usar (existente ou novo)\nconst existingContact = $node[\"Buscar Contato Existente\"].json?.data?.[0];\nconst newContact = $node[\"Criar Novo Contato\"]?.json?.data;\nconst messageData = $node[\"Processar Mensagem WhatsApp\"].json;\n\nconst contactToUse = existingContact || newContact;\n\nif (!contactToUse) {\n throw new Error('Não foi possível obter dados do contato');\n}\n\nreturn {\n contact_id: contactToUse.id,\n contact_name: contactToUse.name,\n contact_phone: messageData.phone,\n message_text: messageData.message_text,\n priority: messageData.priority,\n buying_intent: messageData.buying_intent,\n source: 'WhatsApp',\n lead_title: `Lead WhatsApp - ${messageData.phone}`,\n lead_description: `Mensagem recebida: \"${messageData.message_text}\"\\n\\nPrioridade: ${messageData.priority}\\nIntenção de compra: ${messageData.buying_intent ? 'SIM' : 'NÃO'}\\nData: ${messageData.formatted_date}`\n};" }, "id": "prepare-lead-data", "name": "Preparar Dados do Lead", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [1780, 200] }, { "parameters": { "method": "POST", "url": "https://crm.memudecore.com.br/api/leads", "authentication": "predefinedCredentialType", "nodeCredentialType": "krayin-api", "sendBody": true, "bodyParameters": { "parameters": [ { "name": "title", "value": "={{$node[\"Preparar Dados do Lead\"].json[\"lead_title\"]}}" }, { "name": "description", "value": "={{$node[\"Preparar Dados do Lead\"].json[\"lead_description\"]}}" }, { "name": "lead_value", "value": "={{$node[\"Preparar Dados do Lead\"].json[\"buying_intent\"] ? 5000 : 1000}}" }, { "name": "contact_person_id", "value": "={{$node[\"Preparar Dados do Lead\"].json[\"contact_id\"]}}" }, { "name": "lead_source_id", "value": "2" }, { "name": "lead_type_id", "value": "1" } ] }, "options": {} }, "id": "create-lead", "name": "Criar Lead no CRM", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [2000, 200], "credentials": { "krayin-api": { "id": "krayin-crm-api", "name": "Krayin CRM API" } } }, { "parameters": { "jsCode": "// Gerar log detalhado da criação do lead\nconst leadData = $node[\"Criar Lead no CRM\"].json;\nconst contactData = $node[\"Preparar Dados do Lead\"].json;\nconst messageData = $node[\"Processar Mensagem WhatsApp\"].json;\n\nconst logEntry = {\n timestamp: new Date().toISOString(),\n action: 'LEAD_CREATED_FROM_WHATSAPP',\n lead_id: leadData?.data?.id || 'ERROR',\n contact_id: contactData.contact_id,\n phone: contactData.contact_phone,\n message: messageData.message_text,\n priority: messageData.priority,\n buying_intent: messageData.buying_intent,\n lead_value: contactData.buying_intent ? 5000 : 1000,\n source: 'WhatsApp Evolution API',\n instance: messageData.instance,\n status: leadData?.data ? 'SUCCESS' : 'ERROR'\n};\n\nreturn logEntry;" }, "id": "log-creation", "name": "Gerar Log", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [2220, 200] }, { "parameters": { "mode": "append", "fileName": "/tmp/whatsapp-leads-log.txt", "fileContent": "={{JSON.stringify($node[\"Gerar Log\"].json, null, 2)}}\n---\n" }, "id": "save-log", "name": "Salvar Log em Arquivo", "type": "n8n-nodes-base.writeFile", "typeVersion": 1, "position": [2440, 200] }, { "parameters": { "respondWith": "json", "responseBody": "={\"success\": true, \"lead_id\": \"{{$node[\"Criar Lead no CRM\"].json[\"data\"][\"id\"]}}\", \"contact_id\": \"{{$node[\"Preparar Dados do Lead\"].json[\"contact_id\"]}}\", \"message\": \"Lead criado com sucesso\"}" }, "id": "webhook-response", "name": "Resposta Webhook", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [2660, 200] }, { "parameters": { "respondWith": "json", "responseBody": "{\"success\": true, \"message\": \"Mensagem processada mas ignorada\", \"reason\": \"{{$node[\"Processar Mensagem WhatsApp\"].json[\"reason\"]}}\"}" }, "id": "webhook-response-skip", "name": "Resposta Webhook (Ignorado)", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [1120, 400] } ], "connections": { "Webhook Evolution": { "main": [ [ { "node": "Filtro: Nova Mensagem", "type": "main", "index": 0 } ] ] }, "Filtro: Nova Mensagem": { "main": [ [ { "node": "Processar Mensagem WhatsApp", "type": "main", "index": 0 } ] ] }, "Processar Mensagem WhatsApp": { "main": [ [ { "node": "Pular Processamento?", "type": "main", "index": 0 } ] ] }, "Pular Processamento?": { "main": [ [ { "node": "Resposta Webhook (Ignorado)", "type": "main", "index": 0 } ], [ { "node": "Buscar Contato Existente", "type": "main", "index": 0 } ] ] }, "Buscar Contato Existente": { "main": [ [ { "node": "Contato Novo?", "type": "main", "index": 0 } ] ] }, "Contato Novo?": { "main": [ [ { "node": "Criar Novo Contato", "type": "main", "index": 0 } ], [ { "node": "Preparar Dados do Lead", "type": "main", "index": 0 } ] ] }, "Criar Novo Contato": { "main": [ [ { "node": "Preparar Dados do Lead", "type": "main", "index": 0 } ] ] }, "Preparar Dados do Lead": { "main": [ [ { "node": "Criar Lead no CRM", "type": "main", "index": 0 } ] ] }, "Criar Lead no CRM": { "main": [ [ { "node": "Gerar Log", "type": "main", "index": 0 } ] ] }, "Gerar Log": { "main": [ [ { "node": "Salvar Log em Arquivo", "type": "main", "index": 0 } ] ] }, "Salvar Log em Arquivo": { "main": [ [ { "node": "Resposta Webhook", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": {}, "versionId": "1", "meta": { "instanceId": "evolution-krayin-noslack" }, "id": "1", "tags": [ "WhatsApp", "CRM", "Leads", "Sem Slack", "Evolution" ] }