Deploy: 2026-05-21 20:31:41
This commit is contained in:
@@ -137,6 +137,48 @@ class WhatsAppController extends BaseController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle message received events
|
||||||
|
if ($body['state'] === 'message_received') {
|
||||||
|
if (empty($body['message'])) {
|
||||||
|
$response->status(400)->json(['error' => 'Missing message payload']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$msgData = $body['message'];
|
||||||
|
|
||||||
|
// 1. Find or create the contact in the CRM
|
||||||
|
$contact = \App\Models\Contact::findByPhone($session['company_id'], $msgData['phone']);
|
||||||
|
if (!$contact) {
|
||||||
|
// Determine a fallback name
|
||||||
|
$contactName = !empty($msgData['name']) ? $msgData['name'] : 'WA-' . substr($msgData['phone'], -4);
|
||||||
|
\App\Models\Contact::createSecure([
|
||||||
|
'company_id' => $session['company_id'],
|
||||||
|
'name' => $contactName,
|
||||||
|
'phone' => $msgData['phone'],
|
||||||
|
'notes' => 'Auto-created via incoming WhatsApp message'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Log the incoming message in history log
|
||||||
|
\App\Models\MessageLog::logMessage([
|
||||||
|
'company_id' => $session['company_id'],
|
||||||
|
'session_id' => $session['id'],
|
||||||
|
'contact_phone' => $msgData['phone'],
|
||||||
|
'direction' => 'inbound',
|
||||||
|
'message_type' => 'text',
|
||||||
|
'message_body' => $msgData['body'],
|
||||||
|
'whatsapp_message_id' => $msgData['id'],
|
||||||
|
'status' => 'read'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 3. Placeholder for Phase 5 Gemini AI auto-reply
|
||||||
|
$this->triggerAutoReply($session, $msgData);
|
||||||
|
|
||||||
|
$response->json(['status' => 'success', 'message' => 'Incoming message logged']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle connection state sync
|
||||||
$updateData = [
|
$updateData = [
|
||||||
'status' => $body['state'] // 'waiting_qr', 'connected', 'disconnected'
|
'status' => $body['state'] // 'waiting_qr', 'connected', 'disconnected'
|
||||||
];
|
];
|
||||||
@@ -156,4 +198,12 @@ class WhatsAppController extends BaseController
|
|||||||
|
|
||||||
$response->json(['status' => 'success']);
|
$response->json(['status' => 'success']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placeholder to trigger Gemini AI Auto-Replies or Keyword rules (Phase 5)
|
||||||
|
*/
|
||||||
|
private function triggerAutoReply(array $session, array $msgData)
|
||||||
|
{
|
||||||
|
// To be implemented in Phase 5
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,46 @@ async function startSession(session_key, webhook_url) {
|
|||||||
|
|
||||||
sock.ev.on('creds.update', saveCreds);
|
sock.ev.on('creds.update', saveCreds);
|
||||||
|
|
||||||
|
// Listen for incoming messages
|
||||||
|
sock.ev.on('messages.upsert', async (m) => {
|
||||||
|
if (m.type !== 'notify') return;
|
||||||
|
|
||||||
|
for (const msg of m.messages) {
|
||||||
|
// Ignore messages sent by ourselves
|
||||||
|
if (msg.key.fromMe) continue;
|
||||||
|
|
||||||
|
const remoteJid = msg.key.remoteJid;
|
||||||
|
// Only process direct messages from individuals (ignore groups/broadcasts)
|
||||||
|
if (!remoteJid || !remoteJid.endsWith('@s.whatsapp.net')) continue;
|
||||||
|
|
||||||
|
// Extract text body
|
||||||
|
const body = msg.message?.conversation ||
|
||||||
|
msg.message?.extendedTextMessage?.text ||
|
||||||
|
msg.message?.imageMessage?.caption ||
|
||||||
|
msg.message?.videoMessage?.caption || '';
|
||||||
|
|
||||||
|
// For now, only process messages that have text content
|
||||||
|
if (!body) continue;
|
||||||
|
|
||||||
|
const senderPhone = remoteJid.split('@')[0];
|
||||||
|
const senderName = msg.pushName || '';
|
||||||
|
|
||||||
|
console.log(`[Message] Received from ${senderPhone}: ${body}`);
|
||||||
|
|
||||||
|
await sendWebhook(webhook_url, {
|
||||||
|
session_key,
|
||||||
|
state: 'message_received',
|
||||||
|
message: {
|
||||||
|
id: msg.key.id,
|
||||||
|
phone: senderPhone,
|
||||||
|
name: senderName,
|
||||||
|
body: body,
|
||||||
|
timestamp: msg.messageTimestamp
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
sock.ev.on('connection.update', async (update) => {
|
sock.ev.on('connection.update', async (update) => {
|
||||||
const { connection, lastDisconnect, qr } = update;
|
const { connection, lastDisconnect, qr } = update;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user