apiUrl = config('services.whatsapp.api_url', 'https://whatsapp.golsystems.mx/api/send-whatsapp'); $this->orgId = config('services.whatsapp.org_id', 1); $this->token = config('services.whatsapp.token'); if (!$this->token) { throw new \Exception('El token de WhatsApp no está configurado. Agrega WHATSAPP_TOKEN en tu archivo .env'); } } /** * Enviar documento por WhatsApp usando plantilla facturas_pdv */ public function sendDocument( string $phoneNumber, string $documentUrl, string $filename, string $userEmail, string $ticket, string $customerName ): array { try { // Construir el mensaje de WhatsApp usando plantilla $whatsappMessage = json_encode([ 'messaging_product' => 'whatsapp', 'to' => $this->cleanPhoneNumber($phoneNumber), 'type' => 'template', 'template' => [ 'name' => 'facturas_pdv', 'language' => [ 'code' => 'es_MX', ], 'components' => [ [ 'type' => 'header', 'parameters' => [ [ 'type' => 'document', 'document' => [ 'filename' => $filename, 'link' => $documentUrl, ], ], ], ], [ 'type' => 'body', 'parameters' => [ [ 'type' => 'text', 'text' => $customerName, ], [ 'type' => 'text', 'text' => $ticket, ], ], ], ], ], ]); // Preparar payload completo $payload = [ 'message' => $whatsappMessage, 'email' => $userEmail, 'org_id' => $this->orgId, 'ticket' => $ticket, 'customer' => $customerName, ]; // Enviar petición HTTP con token Bearer $response = Http::timeout(30) ->withHeaders([ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Bearer ' . $this->token, ]) ->post($this->apiUrl, $payload); // Registrar en logs Log::channel('daily')->info('WhatsApp message sent', [ 'phone' => $phoneNumber, 'ticket' => $ticket, 'customer' => $customerName, 'status_code' => $response->status(), ]); if ($response->successful()) { return [ 'success' => true, 'message' => 'Mensaje enviado correctamente', 'data' => $response->json(), ]; } // Log detallado del error Log::channel('daily')->error('WhatsApp API error', [ 'phone' => $phoneNumber, 'status_code' => $response->status(), 'error_body' => $response->body(), ]); return [ 'success' => false, 'message' => 'Error al enviar el mensaje', 'error' => $response->body(), 'status_code' => $response->status(), ]; } catch (\Exception $e) { Log::channel('daily')->error('WhatsApp sending failed', [ 'phone' => $phoneNumber, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); return [ 'success' => false, 'message' => 'Error al conectar con el servicio de WhatsApp', 'error' => $e->getMessage(), ]; } } /** * Enviar factura por WhatsApp */ public function sendInvoice( string $phoneNumber, string $pdfUrl, ?string $xmlUrl, string $invoiceNumber, string $customerName ): array { // Enviar PDF $pdfResult = $this->sendDocument( phoneNumber: $phoneNumber, documentUrl: $pdfUrl, filename: "Factura_{$invoiceNumber}.pdf", userEmail: $this->email, ticket: $invoiceNumber, customerName: $customerName ); // Si hay XML y el PDF se envió correctamente, enviarlo también if ($xmlUrl && $pdfResult['success']) { $xmlResult = $this->sendDocument( phoneNumber: $phoneNumber, documentUrl: $xmlUrl, filename: "Factura_{$invoiceNumber}.xml", userEmail: $this->email, ticket: "{$invoiceNumber}_XML", customerName: $customerName ); return [ 'success' => $pdfResult['success'] && $xmlResult['success'], 'pdf' => $pdfResult, 'xml' => $xmlResult, ]; } return $pdfResult; } /** * Limpiar número de teléfono */ protected function cleanPhoneNumber(string $phone): string { // Eliminar todo excepto números $cleaned = preg_replace('/[^0-9]/', '', $phone); // Asegurar que tenga código de país (52 para México) if (strlen($cleaned) === 10) { $cleaned = '52' . $cleaned; } return $cleaned; } }