cambios importantes

This commit is contained in:
Lizandro Guarnizo
2026-06-12 12:18:21 -05:00
parent efebec3c1b
commit bc422e0a1c
20 changed files with 5348 additions and 99 deletions
+98 -10
View File
@@ -12,6 +12,9 @@ class WpWebhook
/** Payload crudo del webhook actual, compartido entre métodos. */
private static string $currentRaw = '';
/** Empresa identificada para el webhook actual. */
private static ?array $currentCompany = null;
// ─── GET: Verificación Meta ───────────────────────────────────────────────
/**
@@ -85,6 +88,8 @@ class WpWebhook
return;
}
self::resolveCompany($payload);
$entries = $payload['entry'] ?? [];
foreach ($entries as $entry) {
$changes = $entry['changes'] ?? [];
@@ -106,6 +111,57 @@ class WpWebhook
self::saveRawEvent($raw);
}
private static function resolveCompany(array $payload): void
{
$phoneNumberId = '';
foreach ($payload['entry'] ?? [] as $entry) {
foreach ($entry['changes'] ?? [] as $change) {
$metadata = $change['value']['metadata'] ?? [];
if (!empty($metadata['phone_number_id'])) {
$phoneNumberId = $metadata['phone_number_id'];
break 2;
}
}
}
if ($phoneNumberId === '') {
self::log('WARN', 'No se pudo identificar phone_number_id en el payload');
return;
}
self::$currentCompany = CompanyRepository::findByPhoneNumberId($phoneNumberId);
if (self::$currentCompany === null) {
self::log('WARN', "No hay empresa configurada para phone_number_id: {$phoneNumberId}");
} else {
self::log('INFO', "Mensaje enrutado a empresa: " . (self::$currentCompany['name'] ?? '?'));
}
}
// ─── Reenvío a empresa ────────────────────────────────────────────────────
private static function forwardToCompany(array $context, string $content, ?string $mediaId = null): void
{
if (self::$currentCompany === null) {
return;
}
$messageData = array_merge($context, [
'content' => $content,
'media_id' => $mediaId,
'raw_payload' => self::$currentRaw,
]);
$result = CompanyApiClient::forwardMessage(self::$currentCompany, $messageData);
if ($result['success']) {
self::log('INFO', "Mensaje reenviado a empresa: " . (self::$currentCompany['name'] ?? '?'));
} else {
self::log('ERROR', "Fallo reenvío a empresa: " . ($result['error'] ?? json_encode($result)));
}
}
// ─── Mensajes entrantes ───────────────────────────────────────────────────
private static function handleMessages(array $value): void
@@ -169,9 +225,11 @@ class WpWebhook
self::log('MSG', "[TEXT] {$ctx['from']} ({$ctx['name']}): $body");
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'text', $body);
self::saveConversation($ctx, $body);
self::forwardToCompany($ctx, $body);
// ─── Aquí conectas con tu lógica de bot ──────────────────────────────
// Ejemplo: BotHandler::process($ctx, $body);
if (self::$currentCompany !== null) {
BotRouter::route(self::$currentCompany, $ctx, $body, 'text');
}
}
private static function handleMedia(array $msg, array $ctx, string $type): void
@@ -184,6 +242,7 @@ class WpWebhook
self::log('MSG', "[" . strtoupper($type) . "] {$ctx['from']} | id=$mediaId mime=$mime caption=$caption");
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], $type, $preview);
self::saveConversation($ctx, $preview, $mediaId);
self::forwardToCompany($ctx, $preview, $mediaId);
}
private static function handleLocation(array $msg, array $ctx): void
@@ -195,6 +254,7 @@ class WpWebhook
self::log('MSG', "[LOCATION] {$ctx['from']} | lat=$lat lng=$lng name=$name");
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'location', $preview);
self::saveConversation($ctx, $preview);
self::forwardToCompany($ctx, $preview);
}
private static function handleInteractive(array $msg, array $ctx): void
@@ -208,9 +268,15 @@ class WpWebhook
$reply = [];
}
$preview = $iType . ': ' . json_encode($reply);
$replyId = $reply['id'] ?? '';
self::log('MSG', "[INTERACTIVE/$iType] {$ctx['from']} | reply=" . json_encode($reply));
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'interactive', $preview);
self::saveConversation($ctx, $preview);
self::forwardToCompany($ctx, $preview);
if (self::$currentCompany !== null && $replyId !== '') {
BotRouter::route(self::$currentCompany, $ctx, $replyId, 'interactive');
}
}
private static function handleButton(array $msg, array $ctx): void
@@ -218,9 +284,15 @@ class WpWebhook
$text = $msg['button']['text'] ?? '';
$payload = $msg['button']['payload'] ?? '';
$preview = "$text | $payload";
$replyId = $payload ?: $text;
self::log('MSG', "[BUTTON] {$ctx['from']} | text=$text payload=$payload");
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'button', $preview);
self::saveConversation($ctx, $preview);
self::forwardToCompany($ctx, $preview);
if (self::$currentCompany !== null && $replyId !== '') {
BotRouter::route(self::$currentCompany, $ctx, $replyId, 'button');
}
}
private static function handleReaction(array $msg, array $ctx): void
@@ -231,6 +303,7 @@ class WpWebhook
self::log('MSG', "[REACTION] {$ctx['from']} ({$ctx['name']}) | emoji=$emoji msg=$reactTo");
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'reaction', $preview);
self::saveConversation($ctx, $preview);
self::forwardToCompany($ctx, $preview);
}
// ─── Estados de mensajes enviados ────────────────────────────────────────
@@ -251,6 +324,17 @@ class WpWebhook
self::log('INFO', "[STATUS:$status] msg=$id recipient=$recipient ts=$ts");
}
self::saveWebhookLog('statuses', $recipient, '', $status, "msg_id:$id");
if (self::$currentCompany !== null) {
$statusData = [
'message_id' => $id,
'status' => $status,
'recipient' => $recipient,
'timestamp' => $ts,
'errors' => $s['errors'] ?? null,
];
CompanyApiClient::forwardStatus(self::$currentCompany, $statusData);
}
}
}
@@ -286,12 +370,14 @@ class WpWebhook
private static function saveConversation(array $ctx, string $content, ?string $mediaId = null): void
{
try {
$companyId = self::$currentCompany['id'] ?? null;
$stmt = db()->prepare("
INSERT IGNORE INTO conversations
(message_id, phone_number, contact_name, direction, message_type, content, media_id, timestamp)
VALUES (?, ?, ?, 'inbound', ?, ?, ?, ?)
(company_id, message_id, phone_number, contact_name, direction, message_type, content, media_id, timestamp)
VALUES (?, ?, ?, ?, 'inbound', ?, ?, ?, ?)
");
$stmt->execute([
$companyId,
$ctx['message_id'],
$ctx['from'],
$ctx['name'],
@@ -312,11 +398,12 @@ class WpWebhook
private static function saveNotification(int $referenceId, string $phone, string $preview): void
{
try {
$companyId = self::$currentCompany['id'] ?? null;
$stmt = db()->prepare("
INSERT INTO notifications (type, reference_id, phone_number, message)
VALUES ('new_message', ?, ?, ?)
INSERT INTO notifications (company_id, type, reference_id, phone_number, message)
VALUES (?, 'new_message', ?, ?, ?)
");
$stmt->execute([$referenceId, $phone, mb_substr($preview, 0, 255)]);
$stmt->execute([$companyId, $referenceId, $phone, mb_substr($preview, 0, 255)]);
} catch (\PDOException $e) {
self::log('ERROR', 'DB saveNotification: ' . $e->getMessage());
}
@@ -330,12 +417,13 @@ class WpWebhook
string $preview
): void {
try {
$companyId = self::$currentCompany['id'] ?? null;
$stmt = db()->prepare("
INSERT INTO webhook_logs
(event_field, from_number, contact_name, message_type, message_preview, raw_payload)
VALUES (?, ?, ?, ?, ?, ?)
(company_id, event_field, from_number, contact_name, message_type, message_preview, raw_payload)
VALUES (?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([$field, $from, $name, $type, mb_substr($preview, 0, 500), self::$currentRaw]);
$stmt->execute([$companyId, $field, $from, $name, $type, mb_substr($preview, 0, 500), self::$currentRaw]);
} catch (\PDOException $e) {
self::log('ERROR', 'DB saveWebhookLog: ' . $e->getMessage());
}