From 707ef24572c296c20552745337eb914adce9937a Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 3 Jul 2026 10:08:41 -0500 Subject: [PATCH] =?UTF-8?q?configuracion:=20secci=C3=B3n=20perfil=20WhatsA?= =?UTF-8?q?pp=20Business=20(foto,=20about,=20direcci=C3=B3n,=20email,=20we?= =?UTF-8?q?bs,=20categor=C3=ADa)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - wa_profile.php: GET carga perfil desde Graph API, POST guardar campos, POST foto sube imagen - configuracion.php tab sesión: UI con foto de perfil editable, campos del negocio y botón guardar Co-Authored-By: Claude Sonnet 4.6 --- modules/turnero/api/wa_profile.php | 152 +++++++++++++++++++++++ modules/turnero/views/configuracion.php | 155 ++++++++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 modules/turnero/api/wa_profile.php diff --git a/modules/turnero/api/wa_profile.php b/modules/turnero/api/wa_profile.php new file mode 100644 index 0000000..5f43aa6 --- /dev/null +++ b/modules/turnero/api/wa_profile.php @@ -0,0 +1,152 @@ + true, + CURLOPT_TIMEOUT => 15, + ]); + $resp = curl_exec($ch); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $data = json_decode($resp, true); + if ($http !== 200 || isset($data['error'])) { + jsonError($data['error']['message'] ?? 'Error al leer perfil de WhatsApp', $http); + } + + $perfil = $data['data'][0] ?? $data; + jsonOk(['perfil' => $perfil]); +} + +// ── POST ──────────────────────────────────────────────────── +requireMethod('POST'); + +// Detectar si viene como multipart (foto) o JSON +$contentType = $_SERVER['CONTENT_TYPE'] ?? ''; +$esMultipart = str_contains($contentType, 'multipart/form-data'); + +if ($esMultipart) { + $accion = $_POST['accion'] ?? ''; +} else { + $datos = inputJson(); + $accion = $datos['accion'] ?? ''; +} + +// ── POST accion=foto ───────────────────────────────────────── +if ($accion === 'foto') { + if (empty($_FILES['foto']) || $_FILES['foto']['error'] !== UPLOAD_ERR_OK) { + jsonError('No se recibió imagen válida.'); + } + $file = $_FILES['foto']; + $mime = mime_content_type($file['tmp_name']); + $allowed = ['image/jpeg', 'image/png']; + if (!in_array($mime, $allowed, true)) jsonError('Solo se aceptan JPG o PNG.'); + if ($file['size'] > 5 * 1024 * 1024) jsonError('Imagen máxima: 5 MB.'); + + // 1. Subir media a WhatsApp + $uploadUrl = $apiBase . $phoneId . '/media'; + $ch = curl_init($uploadUrl); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token], + CURLOPT_POSTFIELDS => [ + 'messaging_product' => 'whatsapp', + 'type' => $mime, + 'file' => new CURLFile($file['tmp_name'], $mime, $file['name']), + ], + CURLOPT_TIMEOUT => 30, + ]); + $resp = curl_exec($ch); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $uploadData = json_decode($resp, true); + if ($http !== 200 || empty($uploadData['id'])) { + jsonError('Error al subir imagen: ' . ($uploadData['error']['message'] ?? $resp)); + } + $mediaHandle = $uploadData['id']; + + // 2. Aplicar como foto de perfil + $profileUrl = $apiBase . $phoneId . '/whatsapp_business_profile'; + $payload = json_encode([ + 'messaging_product' => 'whatsapp', + 'profile_picture_handle' => $mediaHandle, + ]); + $ch = curl_init($profileUrl); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => $payload, + CURLOPT_HTTPHEADER => [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json', + ], + CURLOPT_TIMEOUT => 15, + ]); + $resp2 = curl_exec($ch); + $http2 = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $r2 = json_decode($resp2, true); + if (isset($r2['error'])) jsonError('Error al aplicar foto: ' . $r2['error']['message']); + jsonOk([], 'Foto de perfil actualizada'); +} + +// ── POST accion=guardar ────────────────────────────────────── +if ($accion === 'guardar') { + $campos = ['about', 'description', 'address', 'email', 'vertical']; + $body = ['messaging_product' => 'whatsapp']; + + foreach ($campos as $c) { + $val = trim($datos[$c] ?? ''); + if ($val !== '') $body[$c] = $val; + } + // Websites: array de hasta 2 + $web = array_filter(array_map('trim', (array)($datos['websites'] ?? []))); + if ($web) $body['websites'] = array_values($web); + + $url = $apiBase . $phoneId . '/whatsapp_business_profile'; + $payload = json_encode($body); + $ch = curl_init($url); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => $payload, + CURLOPT_HTTPHEADER => [ + 'Authorization: Bearer ' . $token, + 'Content-Type: application/json', + ], + CURLOPT_TIMEOUT => 15, + ]); + $resp = curl_exec($ch); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $r = json_decode($resp, true); + if (isset($r['error'])) jsonError('Error de WhatsApp: ' . $r['error']['message']); + jsonOk([], 'Perfil de WhatsApp actualizado'); +} + +jsonError('Acción no reconocida.'); diff --git a/modules/turnero/views/configuracion.php b/modules/turnero/views/configuracion.php index 26f20e6..0433ba2 100644 --- a/modules/turnero/views/configuracion.php +++ b/modules/turnero/views/configuracion.php @@ -794,6 +794,87 @@ $tab = $_GET['tab'] ?? 'lugares'; + +
+

Perfil de WhatsApp Business

+
+ +
+ +
+ +
+ +
+
+
+
+ +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+ @@ -1179,6 +1260,80 @@ async function borrarTvVideo() { } catch(e) { toast('Error de conexión', 'error'); } } +async function cargarPerfilWA() { + try { + const res = await fetch(API + 'wa_profile.php'); + const json = await res.json(); + if (!json.ok) { toast(json.error || 'Error al cargar perfil', 'error'); return; } + const p = json.perfil || {}; + if (p.profile_picture_url) { + document.getElementById('wa-perfil-foto').src = p.profile_picture_url; + document.getElementById('wa-perfil-foto').style.display = ''; + document.getElementById('wa-perfil-foto-placeholder').style.display = 'none'; + } + document.getElementById('wa-perfil-about').textContent = p.about || '—'; + document.getElementById('wa-about').value = p.about || ''; + document.getElementById('wa-description').value = p.description || ''; + document.getElementById('wa-address').value = p.address || ''; + document.getElementById('wa-email').value = p.email || ''; + const webs = p.websites || []; + document.getElementById('wa-web1').value = webs[0] || ''; + document.getElementById('wa-web2').value = webs[1] || ''; + if (p.vertical) document.getElementById('wa-vertical').value = p.vertical; + toast('Perfil cargado'); + } catch (e) { toast('Error de conexión', 'error'); } +} + +async function guardarPerfilWA() { + const body = { + accion: 'guardar', + about: document.getElementById('wa-about').value.trim(), + description: document.getElementById('wa-description').value.trim(), + address: document.getElementById('wa-address').value.trim(), + email: document.getElementById('wa-email').value.trim(), + vertical: document.getElementById('wa-vertical').value, + websites: [document.getElementById('wa-web1').value.trim(), + document.getElementById('wa-web2').value.trim()].filter(Boolean), + }; + try { + const res = await fetch(API + 'wa_profile.php', { + method: 'POST', headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }); + const json = await res.json(); + if (!json.ok) { toast(json.error || 'Error', 'error'); return; } + toast('Perfil de WhatsApp actualizado'); + document.getElementById('wa-perfil-about').textContent = body.about || '—'; + } catch (e) { toast('Error de conexión', 'error'); } +} + +async function subirFotoPerfil(input) { + if (!input.files[0]) return; + const form = new FormData(); + form.append('accion', 'foto'); + form.append('foto', input.files[0]); + const btn = input.closest('label'); + const orig = btn.innerHTML; + btn.innerHTML = ''; + try { + const res = await fetch(API + 'wa_profile.php', { method: 'POST', body: form }); + const json = await res.json(); + if (!json.ok) { toast(json.error || 'Error al subir foto', 'error'); return; } + // Preview local + const reader = new FileReader(); + reader.onload = e => { + document.getElementById('wa-perfil-foto').src = e.target.result; + document.getElementById('wa-perfil-foto').style.display = ''; + document.getElementById('wa-perfil-foto-placeholder').style.display = 'none'; + }; + reader.readAsDataURL(input.files[0]); + toast('Foto de perfil actualizada'); + } catch (e) { toast('Error al subir foto', 'error'); } finally { + btn.innerHTML = orig; + input.value = ''; + } +} + async function guardarWhatsApp() { const template = document.getElementById('wa-template')?.value.trim(); const templateMuestra = document.getElementById('wa-template-muestra')?.value.trim();