feat: menu navegable con submenus y descarga de reportes via api_report

- NormalBot: nueva funcion api_report para descargar PDF/Excel del ERP y enviarlo por WhatsApp
- NormalBot: resolveMenu() para referenciar menus por nombre en los flujos
- WhatsAppSender: uploadMedia() y sendDocument() para envio de documentos
- BotRouter: guarda respuestas en conversations para visibilidad en el chat
- Script apply-menus.php con estructura completa de menus y endpoints
This commit is contained in:
Lizandro Guarnizo
2026-06-27 11:30:08 -05:00
parent 454ee297e2
commit 51c187e47d
4 changed files with 316 additions and 2 deletions
+59
View File
@@ -67,6 +67,65 @@ class WhatsAppSender
]);
}
public static function uploadMedia(string $filePath, string $mimeType, string $phoneNumberId): array
{
$url = self::BASE_URL . '/' . self::API_VERSION . '/' . $phoneNumberId . '/media';
$token = env('WHATSAPP_ACCESS_TOKEN', '');
if ($token === '') {
return ['success' => false, 'error' => 'WHATSAPP_ACCESS_TOKEN no configurado'];
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'messaging_product' => 'whatsapp',
'file' => new \CURLFile($filePath, $mimeType, basename($filePath)),
],
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
$decoded = $response ? json_decode($response, true) : null;
unlink($filePath);
return [
'success' => $httpCode >= 200 && $httpCode < 300,
'http_code' => $httpCode,
'media_id' => $decoded['id'] ?? null,
'response' => $decoded ?? $response,
'error' => $error ?: null,
];
}
public static function sendDocument(string $to, string $mediaId, string $phoneNumberId, ?string $caption = null, ?string $filename = null): array
{
$document = ['id' => $mediaId];
if ($filename !== null) {
$document['filename'] = $filename;
}
if ($caption !== null) {
$document['caption'] = $caption;
}
return self::callApi($phoneNumberId, [
'messaging_product' => 'whatsapp',
'recipient_type' => 'individual',
'to' => $to,
'type' => 'document',
'document' => $document,
]);
}
private static function callApi(string $phoneNumberId, array $payload): array
{
$url = self::BASE_URL . '/' . self::API_VERSION . '/' . $phoneNumberId . '/messages';