diff --git a/api/upload_whatsapp_profile_photo.php b/api/upload_whatsapp_profile_photo.php index 6276557..9b0876f 100644 --- a/api/upload_whatsapp_profile_photo.php +++ b/api/upload_whatsapp_profile_photo.php @@ -1,10 +1,185 @@ false, 'error' => 'Método no permitido']); + exit; +} + +if (empty($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) { + $code = $_FILES['photo']['error'] ?? -1; + echo json_encode(['success' => false, 'error' => "No se recibió archivo válido (código {$code})"]); + exit; +} + +$file = $_FILES['photo']; + +// Validar tipo MIME +$allowedMimes = ['image/jpeg', 'image/png']; +$finfo = new finfo(FILEINFO_MIME_TYPE); +$mime = $finfo->file($file['tmp_name']); +if (!in_array($mime, $allowedMimes, true)) { + echo json_encode(['success' => false, 'error' => 'Solo se permiten imágenes JPG o PNG']); + exit; +} + +// Validar tamaño (máx 5 MB) +if ($file['size'] > 5 * 1024 * 1024) { + echo json_encode(['success' => false, 'error' => 'La imagen no puede superar 5 MB']); + exit; +} + +try { + $config = getWhatsAppConfigFromDB(); + $token = $config['token'] ?? ''; + $phoneId = $config['phone_number_id'] ?? ''; + + // Extraer versión de la API URL (ej. v22.0) + $apiUrl = rtrim($config['api_url'] ?: 'https://graph.facebook.com/v22.0/', '/'); + $apiVersion = 'v22.0'; + if (preg_match('#/(v\d+\.\d+)#', $apiUrl, $m)) { + $apiVersion = $m[1]; + } + + if (empty($token) || empty($phoneId)) { + echo json_encode(['success' => false, 'error' => 'Token o Phone Number ID no configurado']); + exit; + } + + $fileSize = $file['size']; + $fileName = basename($file['name']); + + // ── Paso 1: Crear sesión de upload ──────────────────────────────────────── + // POST https://graph.facebook.com/{version}/app/uploads + $sessionUrl = "https://graph.facebook.com/{$apiVersion}/app/uploads?" + . http_build_query([ + 'file_name' => $fileName, + 'file_length' => $fileSize, + 'file_type' => $mime, + 'access_token'=> $token, + ]); + + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => $sessionUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => '', + CURLOPT_TIMEOUT => 20, + CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, + CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2, + ]); + + $sessionResp = curl_exec($ch); + $sessionCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $sessionErr = curl_error($ch); + curl_close($ch); + + if ($sessionErr) throw new Exception("Error creando sesión de upload: {$sessionErr}"); + + $sessionData = json_decode($sessionResp, true); + if ($sessionCode !== 200 || empty($sessionData['id'])) { + $msg = $sessionData['error']['message'] ?? $sessionResp; + throw new Exception("Sesión upload error ({$sessionCode}): {$msg}"); + } + + $uploadSessionId = $sessionData['id']; + + // ── Paso 2: Subir el archivo binario ────────────────────────────────────── + // POST https://rupload.facebook.com/whatsapp-business-profile/{session_id} + $fileContent = file_get_contents($file['tmp_name']); + if ($fileContent === false) throw new Exception("No se pudo leer el archivo temporal"); + + $uploadUrl = "https://rupload.facebook.com/whatsapp-business-profile/{$uploadSessionId}"; + + $ch2 = curl_init(); + curl_setopt_array($ch2, [ + CURLOPT_URL => $uploadUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => $fileContent, + CURLOPT_HTTPHEADER => [ + "Authorization: OAuth {$token}", + "Content-Type: {$mime}", + "file_offset: 0", + ], + CURLOPT_TIMEOUT => 60, + CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, + CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2, + ]); + + $uploadResp = curl_exec($ch2); + $uploadCode = curl_getinfo($ch2, CURLINFO_HTTP_CODE); + $uploadErr = curl_error($ch2); + curl_close($ch2); + + if ($uploadErr) throw new Exception("Error subiendo archivo: {$uploadErr}"); + + $uploadData = json_decode($uploadResp, true); + if ($uploadCode !== 200 || empty($uploadData['h'])) { + $msg = $uploadData['error']['message'] ?? $uploadResp; + throw new Exception("Upload file error ({$uploadCode}): {$msg}"); + } + + $fileHandle = $uploadData['h']; // ej. "h:abc123..." + + // ── Paso 3: Aplicar la foto al perfil ───────────────────────────────────── + $profileUrl = "{$apiUrl}/{$phoneId}/whatsapp_business_profile"; + + $payload = [ + 'messaging_product' => 'whatsapp', + 'profile_picture_handle' => $fileHandle, + ]; + + $ch3 = curl_init(); + curl_setopt_array($ch3, [ + CURLOPT_URL => $profileUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode($payload), + CURLOPT_HTTPHEADER => [ + "Authorization: Bearer {$token}", + "Content-Type: application/json", + ], + CURLOPT_TIMEOUT => 20, + CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, + CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2, + ]); + + $profileResp = curl_exec($ch3); + $profileCode = curl_getinfo($ch3, CURLINFO_HTTP_CODE); + $profileErr = curl_error($ch3); + curl_close($ch3); + + if ($profileErr) throw new Exception("Error actualizando foto: {$profileErr}"); + + $profileData = json_decode($profileResp, true); + if ($profileCode !== 200) { + $msg = $profileData['error']['message'] ?? $profileResp; + throw new Exception("Profile photo error ({$profileCode}): {$msg}"); + } + + echo json_encode(['success' => true, 'message' => 'Foto de perfil actualizada correctamente']); + +} catch (Exception $e) { + error_log('[upload_whatsapp_profile_photo] ' . $e->getMessage()); + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} + + require_once '../config/config.php'; header('Content-Type: application/json; charset=utf-8');