This commit is contained in:
Lizandro Guarnizo
2026-02-21 11:24:15 -05:00
parent 26afa7f36b
commit 5dd48ba5c2
5 changed files with 378 additions and 59 deletions
+84 -20
View File
@@ -421,6 +421,8 @@ class WhatsAppService
/**
* Subir archivo multimedia a WhatsApp
* Intenta primero con PHP curl. Si falla por SSL/conexión (errno 35, 56, 77),
* reintenta usando el CLI curl vía exec (mismo workaround que para descargas).
*/
public function uploadMedia($filePath, $mimeType)
{
@@ -430,6 +432,7 @@ class WhatsAppService
$url = $this->apiUrl . $this->phoneNumberId . '/media';
// ── Intento 1: PHP curl con opciones SSL relajadas ──────────────────────
$ch = curl_init();
$postFields = [
@@ -439,43 +442,104 @@ class WhatsAppService
];
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
CURLOPT_HTTPHEADER => [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->token
],
CURLOPT_TIMEOUT => 300,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_TIMEOUT => 300,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
// Forzar TLS 1.2 (evita problemas de negociación SSL en algunos VPS)
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
$curlErrno = curl_errno($ch);
curl_close($ch);
// Log detallado para diagnóstico
error_log("WhatsAppService::uploadMedia - URL: {$url}, HTTP: {$httpCode}, curlErrno: {$curlErrno}, curlError: {$curlError}, tokenLen: " . strlen($this->token) . ", phoneId: {$this->phoneNumberId}");
error_log("WhatsAppService::uploadMedia (php-curl) - URL: {$url}, HTTP: {$httpCode}, errno: {$curlErrno}, error: {$curlError}");
if ($curlErrno !== 0) {
// Errores de capa SSL/red que se benefician del fallback CLI
$sslErrors = [35, 56, 77, 58, 59, 60]; // CURLE_SSL_CONNECT_ERROR, CURLE_RECV_ERROR, etc.
$needsFallback = ($curlErrno !== 0 && in_array($curlErrno, $sslErrors, true));
if (!$needsFallback && $curlErrno !== 0) {
throw new Exception("Error de conexión subiendo archivo (curl #{$curlErrno}): {$curlError}");
}
if ($httpCode !== 200 && $httpCode !== 201) {
throw new Exception("Error subiendo archivo (HTTP {$httpCode}): " . $response);
if (!$needsFallback) {
if ($httpCode !== 200 && $httpCode !== 201) {
throw new Exception("Error subiendo archivo (HTTP {$httpCode}): " . $response);
}
$result = json_decode($response, true);
if (!isset($result['id'])) {
throw new Exception("No se obtuvo ID del archivo subido: " . $response);
}
return $result;
}
$result = json_decode($response, true);
// ── Intento 2: CLI curl (usa GnuTLS / sistema, evita bug OpenSSL de PHP) ─
error_log("WhatsAppService::uploadMedia: PHP curl falló (errno {$curlErrno}), usando curl CLI...");
if (!function_exists('exec') || !@exec('echo 1')) {
throw new Exception("Error de conexión subiendo archivo (curl #{$curlErrno}): {$curlError} — fallback CLI no disponible");
}
// Archivo temporal para la respuesta del CLI
$tmpResponse = tempnam(sys_get_temp_dir(), 'wa_upload_');
$cmd = sprintf(
'curl --silent --show-error'
. ' --ipv4'
. ' --tlsv1.2'
. ' --max-time 300'
. ' -o %s'
. ' -w "%%{http_code}"'
. ' -X POST'
. ' -H %s'
. ' -F %s'
. ' -F %s'
. ' -F %s'
. ' %s'
. ' 2>&1',
escapeshellarg($tmpResponse),
escapeshellarg('Authorization: Bearer ' . $this->token),
escapeshellarg('messaging_product=whatsapp'),
escapeshellarg('type=' . $mimeType),
escapeshellarg('file=@' . $filePath . ';type=' . $mimeType),
escapeshellarg($url)
);
$cliHttpCode = null;
$cliOut = null;
@exec($cmd, $outputLines, $exitCode);
$cliHttpCode = trim(implode('', $outputLines));
$cliBody = @file_get_contents($tmpResponse);
@unlink($tmpResponse);
error_log("WhatsAppService::uploadMedia (curl-cli) - exit: {$exitCode}, http: {$cliHttpCode}, body: " . substr((string)$cliBody, 0, 300));
if ($exitCode !== 0) {
throw new Exception("Error de conexión subiendo archivo (curl CLI exit {$exitCode}): {$cliHttpCode}");
}
$cliCode = intval($cliHttpCode);
if ($cliCode !== 200 && $cliCode !== 201) {
throw new Exception("Error subiendo archivo via CLI (HTTP {$cliCode}): " . $cliBody);
}
$result = json_decode($cliBody, true);
if (!isset($result['id'])) {
throw new Exception("No se obtuvo ID del archivo subido: " . $response);
throw new Exception("No se obtuvo ID del archivo subido (CLI): " . $cliBody);
}
return $result; // Retorna el objeto completo con 'id'
return $result;
}
/**