Add webhook creation on WhatsApp connect
Implement POST request to Evolution API to create a webhook after successful WhatsApp QR code connection, including correct endpoint, headers, and body formatting. Log request status.
This commit is contained in:
parent
c7292ee600
commit
a930b755eb
@ -11,8 +11,9 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||||
import { RefreshCw, ScanQrCode } from 'lucide-react';
|
import { RefreshCw, ScanQrCode } from 'lucide-react';
|
||||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
||||||
import { fetchQrCode } from '@/services/whatsAppService';
|
import { fetchQrCode, fetchConnectionState } from '@/services/whatsAppService';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
|
import { useWebhookConnection } from '@/hooks/whatsApp/useWebhookConnection';
|
||||||
|
|
||||||
interface QrCodeDialogProps {
|
interface QrCodeDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -28,26 +29,86 @@ const QrCodeDialog = ({
|
|||||||
onStatusCheck
|
onStatusCheck
|
||||||
}: QrCodeDialogProps) => {
|
}: QrCodeDialogProps) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const { setupWebhookAfterConnection } = useWebhookConnection();
|
||||||
const [loadingQR, setLoadingQR] = useState(false);
|
const [loadingQR, setLoadingQR] = useState(false);
|
||||||
const [qrCodeData, setQrCodeData] = useState<string | null>(null);
|
const [qrCodeData, setQrCodeData] = useState<string | null>(null);
|
||||||
const [qrError, setQrError] = useState<string | null>(null);
|
const [qrError, setQrError] = useState<string | null>(null);
|
||||||
|
const [isCheckingConnection, setIsCheckingConnection] = useState(false);
|
||||||
|
const [connectionCheckInterval, setConnectionCheckInterval] = useState<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
// Auto-fetch QR code when dialog opens with an active instance
|
// Auto-fetch QR code when dialog opens with an active instance
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open && activeInstance) {
|
if (open && activeInstance) {
|
||||||
handleRefreshQrCode();
|
handleRefreshQrCode();
|
||||||
|
startConnectionCheck();
|
||||||
} else {
|
} else {
|
||||||
// Clear QR code data when dialog closes
|
// Clear QR code data when dialog closes
|
||||||
setQrCodeData(null);
|
setQrCodeData(null);
|
||||||
setQrError(null);
|
setQrError(null);
|
||||||
|
stopConnectionCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
stopConnectionCheck();
|
||||||
|
};
|
||||||
}, [open, activeInstance]);
|
}, [open, activeInstance]);
|
||||||
|
|
||||||
|
const startConnectionCheck = () => {
|
||||||
|
if (!activeInstance) return;
|
||||||
|
|
||||||
|
console.log('Iniciando verificação periódica de conexão...');
|
||||||
|
setIsCheckingConnection(true);
|
||||||
|
|
||||||
|
const interval = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
const connectionState = await fetchConnectionState(activeInstance.instanceName);
|
||||||
|
console.log(`Estado da conexão para ${activeInstance.instanceName}:`, connectionState);
|
||||||
|
|
||||||
|
if (connectionState === 'open') {
|
||||||
|
console.log('🎉 Conexão estabelecida com sucesso!');
|
||||||
|
|
||||||
|
// Parar a verificação
|
||||||
|
stopConnectionCheck();
|
||||||
|
|
||||||
|
// Configurar webhook
|
||||||
|
const userEmail = localStorage.getItem('userEmail');
|
||||||
|
if (userEmail) {
|
||||||
|
await setupWebhookAfterConnection(userEmail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mostrar sucesso
|
||||||
|
toast({
|
||||||
|
title: "WhatsApp Conectado!",
|
||||||
|
description: "Conexão estabelecida com sucesso. Webhook configurado automaticamente.",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fechar o dialog e atualizar status
|
||||||
|
onOpenChange(false);
|
||||||
|
onStatusCheck();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao verificar estado da conexão:', error);
|
||||||
|
}
|
||||||
|
}, 3000); // Verifica a cada 3 segundos
|
||||||
|
|
||||||
|
setConnectionCheckInterval(interval);
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopConnectionCheck = () => {
|
||||||
|
if (connectionCheckInterval) {
|
||||||
|
console.log('Parando verificação de conexão...');
|
||||||
|
clearInterval(connectionCheckInterval);
|
||||||
|
setConnectionCheckInterval(null);
|
||||||
|
setIsCheckingConnection(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleOpenChange = (newOpen: boolean) => {
|
const handleOpenChange = (newOpen: boolean) => {
|
||||||
onOpenChange(newOpen);
|
onOpenChange(newOpen);
|
||||||
|
|
||||||
// After dialog closes, trigger status check to update connection state
|
// After dialog closes, trigger status check to update connection state
|
||||||
if (!newOpen) {
|
if (!newOpen) {
|
||||||
|
stopConnectionCheck();
|
||||||
onStatusCheck();
|
onStatusCheck();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -67,6 +128,11 @@ const QrCodeDialog = ({
|
|||||||
// Save the base64 image data directly - it already contains the data:image prefix
|
// Save the base64 image data directly - it already contains the data:image prefix
|
||||||
setQrCodeData(data.base64);
|
setQrCodeData(data.base64);
|
||||||
setQrError(null);
|
setQrError(null);
|
||||||
|
|
||||||
|
// Iniciar verificação de conexão quando QR code é exibido
|
||||||
|
if (!isCheckingConnection) {
|
||||||
|
startConnectionCheck();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setQrCodeData(null);
|
setQrCodeData(null);
|
||||||
setQrError("QR Code não disponível. A instância pode já estar conectada ou houve um erro na API.");
|
setQrError("QR Code não disponível. A instância pode já estar conectada ou houve um erro na API.");
|
||||||
@ -92,6 +158,11 @@ const QrCodeDialog = ({
|
|||||||
<DialogTitle>Conectar WhatsApp - {activeInstance?.instanceName}</DialogTitle>
|
<DialogTitle>Conectar WhatsApp - {activeInstance?.instanceName}</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Escaneie o QR Code com seu WhatsApp para finalizar a conexão
|
Escaneie o QR Code com seu WhatsApp para finalizar a conexão
|
||||||
|
{isCheckingConnection && (
|
||||||
|
<span className="block mt-1 text-blue-600 font-medium">
|
||||||
|
⏳ Aguardando conexão... (verificando automaticamente)
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="flex flex-col items-center space-y-4 py-4">
|
<div className="flex flex-col items-center space-y-4 py-4">
|
||||||
@ -119,6 +190,14 @@ const QrCodeDialog = ({
|
|||||||
<ScanQrCode className="h-4 w-4" />
|
<ScanQrCode className="h-4 w-4" />
|
||||||
<p>Escaneie este QR Code com seu WhatsApp para finalizar a conexão</p>
|
<p>Escaneie este QR Code com seu WhatsApp para finalizar a conexão</p>
|
||||||
</div>
|
</div>
|
||||||
|
{isCheckingConnection && (
|
||||||
|
<div className="text-center text-blue-600 text-sm">
|
||||||
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
<RefreshCw className="h-4 w-4 animate-spin" />
|
||||||
|
<span>Verificando conexão automaticamente...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
35
src/hooks/whatsApp/useWebhookConnection.ts
Normal file
35
src/hooks/whatsApp/useWebhookConnection.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
import { useToast } from '@/hooks/use-toast';
|
||||||
|
import { createEvolutionWebhook } from '@/services/whatsApp/webhookService';
|
||||||
|
|
||||||
|
export const useWebhookConnection = () => {
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const setupWebhookAfterConnection = async (userEmail: string) => {
|
||||||
|
try {
|
||||||
|
console.log('🔗 Configurando webhook após conexão bem-sucedida...');
|
||||||
|
|
||||||
|
await createEvolutionWebhook(userEmail);
|
||||||
|
|
||||||
|
console.log('✅ Webhook configurado com sucesso');
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "Webhook Configurado",
|
||||||
|
description: "Webhook foi configurado automaticamente para receber mensagens.",
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erro ao configurar webhook:', error);
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "Aviso: Webhook",
|
||||||
|
description: "WhatsApp conectado, mas houve falha na configuração do webhook.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
setupWebhookAfterConnection
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -3,6 +3,8 @@
|
|||||||
export * from './instanceManagement';
|
export * from './instanceManagement';
|
||||||
export * from './instanceActions';
|
export * from './instanceActions';
|
||||||
export * from './localStorage';
|
export * from './localStorage';
|
||||||
|
export * from './webhookService';
|
||||||
|
|
||||||
// Import and re-export the disconnect function specifically
|
// Import and re-export the disconnect function specifically
|
||||||
export { disconnectInstance } from './instanceActions';
|
export { disconnectInstance } from './instanceActions';
|
||||||
|
export { createEvolutionWebhook } from './webhookService';
|
||||||
|
|||||||
45
src/services/whatsApp/webhookService.ts
Normal file
45
src/services/whatsApp/webhookService.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
import { makeRequest } from './apiHelpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cria um webhook na Evolution API para o usuário
|
||||||
|
*/
|
||||||
|
export const createEvolutionWebhook = async (userEmail: string): Promise<any> => {
|
||||||
|
try {
|
||||||
|
console.log(`Criando webhook para o usuário: ${userEmail}`);
|
||||||
|
|
||||||
|
// URL do endpoint - mantém o @ normal no email
|
||||||
|
const endpoint = `/webhook/set/${userEmail}`;
|
||||||
|
|
||||||
|
// No body, troca @ por _ no email
|
||||||
|
const emailWithUnderscore = userEmail.replace('@', '_');
|
||||||
|
|
||||||
|
const webhookBody = {
|
||||||
|
webhook: {
|
||||||
|
enabled: true,
|
||||||
|
url: `https://webhookn8n.innova1001.com.br/webhook/${emailWithUnderscore}`,
|
||||||
|
webhookByEvents: true,
|
||||||
|
webhookBase64: true,
|
||||||
|
events: [
|
||||||
|
"MESSAGES_UPSERT"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('Dados do webhook:', {
|
||||||
|
endpoint,
|
||||||
|
emailOriginal: userEmail,
|
||||||
|
emailComUnderscore: emailWithUnderscore,
|
||||||
|
webhookUrl: webhookBody.webhook.url
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await makeRequest(endpoint, 'POST', webhookBody);
|
||||||
|
|
||||||
|
console.log(`✅ Webhook criado com sucesso para ${userEmail}:`, response);
|
||||||
|
return response;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Erro ao criar webhook for ${userEmail}:`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -5,6 +5,7 @@
|
|||||||
export * from './whatsApp/instanceManagement';
|
export * from './whatsApp/instanceManagement';
|
||||||
export * from './whatsApp/instanceActions';
|
export * from './whatsApp/instanceActions';
|
||||||
export * from './whatsApp/localStorage';
|
export * from './whatsApp/localStorage';
|
||||||
|
export * from './whatsApp/webhookService';
|
||||||
|
|
||||||
// Export config values if needed by other parts of the app
|
// Export config values if needed by other parts of the app
|
||||||
export { SERVER_URL, API_KEY, STORAGE_KEY } from './whatsApp/config';
|
export { SERVER_URL, API_KEY, STORAGE_KEY } from './whatsApp/config';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user