feat: WhatsApp — parámetros nombrados en template, API v25.0 e imagenUrl con soporte de URL externas

- Actualiza graph.facebook.com de v19.0 a v25.0
- Cambia parámetros posicionales a nombrados (parameter_name) en enviarTemplate para compatibilidad con plantillas avanzadas
- enviarPromocion ahora pasa nombre fallback 'estudiante' y claves explícitas
- imagenUrl() soporta imágenes con URL absoluta (http/https) además de rutas relativas de storage
- Agrega Log::info del payload completo antes del envío para facilitar debugging

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 20:44:13 -06:00
parent f246a709c4
commit a0c3194e88
3 changed files with 53 additions and 19 deletions
+8 -1
View File
@@ -23,7 +23,14 @@
"Bash(Select-String -Pattern \"entrega|Entrega\" -Context 0,0)",
"Bash(php -l app/Services/WhatsAppService.php)",
"Bash(php -l app/Http/Controllers/WhatsAppWebhookController.php)",
"Bash(php -l app/Http/Controllers/WhatsAppAnalyticsController.php)"
"Bash(php -l app/Http/Controllers/WhatsAppAnalyticsController.php)",
"Bash(Test-Path *)",
"Bash(git -C \"C:/Proyectos/SistemaEducativoLaravel\" status)",
"Bash(git -C \"C:/Proyectos/SistemaEducativoLaravel\" diff)",
"Bash(git *)",
"Bash(dir C:\\\\Proyectos\\\\SistemaEducativoLaravel\\\\public *)",
"Bash(findstr \"APP_URL\" \"C:\\\\Proyectos\\\\SistemaEducativoLaravel\\\\.env.example\")",
"Bash(findstr \"APP_URL\" \"C:\\\\Proyectos\\\\SistemaEducativoLaravel\\\\.env\")"
]
}
}
+7 -1
View File
@@ -34,6 +34,12 @@ class Promocion extends Model
public function imagenUrl(): ?string
{
return $this->imagen ? asset('storage/' . $this->imagen) : null;
if (!$this->imagen) return null;
if (str_starts_with($this->imagen, 'http')) {
return $this->imagen;
}
return asset('storage/' . $this->imagen);
}
}
+30 -9
View File
@@ -28,7 +28,7 @@ class WhatsAppService
$this->token = $token;
$this->phoneId = $phoneId;
$this->apiUrl = "https://graph.facebook.com/v19.0/{$this->phoneId}/messages";
$this->apiUrl = "https://graph.facebook.com/v25.0/{$this->phoneId}/messages";
}
public function enviarTemplate(string $telefono, string $templateName, array $parametros = [], ?string $imagenUrl = null): ?string
@@ -50,9 +50,28 @@ class WhatsAppService
if (!empty($parametros)) {
$components[] = [
'type' => 'body',
'parameters' => array_map(fn($p) => ['type' => 'text', 'text' => $p], $parametros),
'parameters' => array_map(fn($nombre, $valor) => [
'type' => 'text',
'text' => (string) $valor,
'parameter_name' => $nombre,
], array_keys($parametros), array_values($parametros)),
];
}
}
Log::info('WhatsApp payload', [
'url' => $this->apiUrl,
'body' => [
'messaging_product' => 'whatsapp',
'to' => $this->normalizarTelefono($telefono),
'type' => 'template',
'template' => [
'name' => $templateName,
'language' => ['code' => 'es_MX'],
'components' => $components,
],
]
]);
$response = Http::withToken($this->token)->post($this->apiUrl, [
'messaging_product' => 'whatsapp',
@@ -66,7 +85,7 @@ class WhatsAppService
]);
if ($response->failed()) {
Log::error('WhatsApp template error', ['telefono' => $telefono, 'response' => $response->json()]);
Log::error('WhatsApp template error', ['telefono' => $telefono, 'response' => $response->json(), 'body' => $response->body()]);
return null;
}
@@ -114,13 +133,15 @@ public function enviarPromocion(string $telefono, Promocion $promocion, string $
$telefono,
'promocion_laravel',
[
$nombre,
$promocion->fecha_inicio->locale('es')->isoFormat('D [de] MMMM'),
$promocion->fecha_fin->locale('es')->isoFormat('D [de] MMMM'),
$codigo,
'nombre' => $nombre ?: 'estudiante',
'fecha_inicio' => $promocion->fecha_inicio->locale('es')->isoFormat('D [de] MMMM'),
'fecha_fin' => $promocion->fecha_fin->locale('es')->isoFormat('D [de] MMMM'),
'codigo' => $codigo,
],
$promocion->imagenUrl()
);
);
if (!$mensajeId) {
throw new \RuntimeException('No se pudo enviar la plantilla');