isConfigured()) { // El servicio no está habilitado o falta el API token error_log('WhatsApp service not configured for tenant: ' . $tenantId); return; } // Enviar mensaje $response = $service->sendMessage( template: 'booking_confirmation', // Nombre del template language: 'es', // Idioma phone: $phone, // Teléfono destino bookingId: (string) $bookingId, // ID de la reserva (opcional) variables: [ // Variables del template 'customer_name' => 'Juan García', 'date' => '15/01/2025', 'time' => '20:30', 'guests' => '4', 'restaurant_name' => $service->getRestaurantName() ], needsResponse: true // Espera respuesta del cliente ); if ($response->isSuccess()) { $messageUuid = $response->getMessageUuid(); $creditsRemaining = $response->getCreditsRemaining(); // Guardar el UUID para seguimiento update_post_meta($bookingId, '_whatsapp_message_uuid', $messageUuid); error_log("Mensaje enviado correctamente. UUID: {$messageUuid}"); error_log("Créditos restantes: {$creditsRemaining}"); } else { // Manejar error $errorCode = $response->error; $errorMessage = $response->getErrorMessage(); if ($response->isInsufficientCredits()) { // Sin créditos suficientes error_log("Sin créditos suficientes para enviar mensaje"); } elseif ($response->isUnauthorized()) { // Token inválido error_log("API token inválido"); } elseif ($response->isTemplateNotFound()) { // Template no existe error_log("Template no encontrado"); } else { error_log("Error enviando mensaje: {$errorMessage}"); } } } // ============================================================================ // EJEMPLO 2: Consultar estado de un mensaje // ============================================================================ function consultarEstadoMensaje(int $tenantId, string $messageUuid): array { $service = WhatsappApiService::forTenant($tenantId); $response = $service->getMessageStatus($messageUuid); if ($response->isSuccess()) { return [ 'status' => $response->getStatus(), // 'queued', 'sent', 'delivered', 'read', 'failed' 'sent_at' => $response->get('sent_at'), 'delivered_at' => $response->get('delivered_at'), 'read_at' => $response->get('read_at'), 'has_response' => $response->hasResponse(), 'error' => $response->get('error_message') ]; } return [ 'status' => 'unknown', 'error' => $response->getErrorMessage() ]; } // ============================================================================ // EJEMPLO 3: Consultar créditos disponibles // ============================================================================ function obtenerCreditosDisponibles(int $tenantId): array { $service = WhatsappApiService::forTenant($tenantId); $response = $service->getCredits(); if ($response->isSuccess()) { return [ 'credits_available' => $response->getCreditsAvailable(), 'messages_sent_today' => $response->get('messages_sent_today'), 'messages_delivered_today' => $response->get('messages_delivered_today'), 'credits_used_this_month' => $response->get('credits_used_this_month') ]; } return [ 'credits_available' => 0, 'error' => $response->getErrorMessage() ]; } // ============================================================================ // EJEMPLO 4: Listar templates disponibles // ============================================================================ function obtenerTemplatesDisponibles(int $tenantId): array { $service = WhatsappApiService::forTenant($tenantId); $response = $service->getTemplates(); if ($response->isSuccess()) { // Devuelve array de templates con: name, language, category, has_buttons, variables_example return $response->getTemplates(); } return []; } // ============================================================================ // EJEMPLO 5: Uso con try/catch y excepciones // ============================================================================ function enviarMensajeConExcepciones(int $tenantId, array $messageData): void { try { $service = WhatsappApiService::forTenant($tenantId); if (!$service->isConfigured()) { throw WhatsappApiException::serviceNotConfigured(); } $response = $service->sendMessage( template: $messageData['template'], language: $messageData['language'], phone: $messageData['phone'], bookingId: $messageData['booking_id'] ?? null, variables: $messageData['variables'] ?? [] ); if ($response->isFailed()) { throw WhatsappApiException::fromResponse($response); } // Mensaje enviado correctamente do_action('alexr_whatsapp_message_sent', $response->getMessageUuid(), $messageData); } catch (WhatsappApiException $e) { error_log(sprintf( "WhatsApp API Error [%s]: %s", $e->getErrorCode(), $e->getMessage() )); // Notificar al admin si es un error de créditos if ($e->getErrorCode() === 'insufficient_credits') { do_action('alexr_whatsapp_insufficient_credits', $e->getContext()); } } catch (\Exception $e) { error_log("Unexpected error: " . $e->getMessage()); } } // ============================================================================ // EJEMPLO 6: Integración con hooks de WordPress // ============================================================================ // Hook cuando se crea una reserva add_action('alexr_booking_created', function($booking) { $tenantId = $booking->restaurant_id; $service = WhatsappApiService::forTenant($tenantId); if (!$service->isConfigured()) { return; } $response = $service->sendMessage( template: 'booking_confirmation', language: $booking->language ?? 'es', phone: $booking->phone, bookingId: (string) $booking->id, variables: [ 'customer_name' => $booking->name, 'date' => $booking->date_formatted, 'time' => $booking->time_formatted, 'guests' => (string) $booking->party, ] ); if ($response->isSuccess()) { // Guardar UUID del mensaje en la reserva $booking->updateMeta('whatsapp_confirmation_uuid', $response->getMessageUuid()); } }); // ============================================================================ // EJEMPLO 7: Verificar créditos antes de enviar múltiples mensajes // ============================================================================ function enviarMensajesEnLote(int $tenantId, array $messages): array { $service = WhatsappApiService::forTenant($tenantId); // Primero verificar créditos $creditsResponse = $service->getCredits(); if ($creditsResponse->isFailed()) { return ['error' => 'Could not check credits']; } $availableCredits = $creditsResponse->getCreditsAvailable(); $messagesCount = count($messages); if ($availableCredits < $messagesCount) { return [ 'error' => 'insufficient_credits', 'available' => $availableCredits, 'needed' => $messagesCount ]; } // Enviar mensajes $results = []; foreach ($messages as $msg) { $response = $service->sendMessage( template: $msg['template'], language: $msg['language'], phone: $msg['phone'], bookingId: $msg['booking_id'] ?? null, variables: $msg['variables'] ?? [] ); $results[] = [ 'phone' => $msg['phone'], 'success' => $response->isSuccess(), 'uuid' => $response->getMessageUuid(), 'error' => $response->isFailed() ? $response->getErrorMessage() : null ]; } return ['results' => $results]; }