tenantId = $tenantId; $this->loadConfig(); $this->baseUrl = $baseUrl ?? $this->getDefaultBaseUrl(); $this->client = new Client([ 'base_uri' => rtrim($this->baseUrl, '/') . '/', 'timeout' => $this->timeout, 'http_errors' => false, // Don't throw on 4xx/5xx 'headers' => [ 'Accept' => 'application/json', 'Content-Type' => 'application/json; charset=utf-8', ] ]); } /** * Load configuration from WhatsappConfig */ protected function loadConfig(): void { $whatsappConfigId = WhatsappConfig::getId($this->tenantId); $whatsappConfig = WhatsappConfig::find($whatsappConfigId); $this->config = $whatsappConfig->config ?? []; $this->apiToken = $this->config['api_token'] ?? ''; } /** * Get the default API base URL * Override this method or set via constructor/config */ protected function getDefaultBaseUrl(): string { // You can change this to read from a config file or constant return defined('ALEXR_WHATSAPP_API_URL') ? ALEXR_WHATSAPP_API_URL : 'https://your-api-domain.com'; } /** * Check if the service is properly configured */ public function isConfigured(): bool { return !empty($this->apiToken) && ($this->config['enabled'] ?? false); } /** * Get current configuration */ public function getConfig(): array { return $this->config; } /** * Get restaurant name from config */ public function getRestaurantName(): string { return $this->config['restaurant_name'] ?? ''; } /** * Get restaurant phone from config */ public function getRestaurantPhone(): string { return $this->config['phone'] ?? ''; } public function getDateFormat(): string { $date_format = $this->config['date_format'] ?? 'locale'; if ($date_format == 'locale') { $date_format = 'l j F Y'; } else { $date_formats = alexr_config('app.date_formats_carbon'); $date_format = $date_formats[ $date_format ] ?? 'l j F Y'; } return $date_format; } public function getTimeFormat(): string { return $this->config['time_format'] ?? ''; } /** * Send a WhatsApp message * * @param string $template Template name * @param string $language Language code (e.g., 'es', 'en') * @param string $phone Recipient phone number * @param string|null $bookingId Optional booking ID from WordPress * @param array $variables Template variables * @param bool $needsResponse Whether the message expects a response * @return WhatsappApiResponse */ public function sendMessage( string $template, string $language, string $phone, ?string $bookingId = null, array $variables = [], bool $needsResponse = false ): WhatsappApiResponse { if (!$this->isConfigured()) { return WhatsappApiResponse::error('service_not_configured', 'WhatsApp service is not configured'); } $variables['business_name'] = $this->getRestaurantName(); $date_formatted = evavel_date_createFromFormatTranslate('Y-m-d', $variables['date'], $language, $this->getDateFormat()); $variables['date'] = $date_formatted; $time_formatted = $this->toHour($variables['hour'], $this->getTimeFormat()); $variables['hour'] = $time_formatted; $payload = [ 'api_token' => $this->apiToken, 'template' => $template, 'language' => $language, 'phone' => alexr_clean_phone_number($phone), 'booking_id' => $bookingId, 'variables' => $variables, 'needs_response' => $needsResponse, ]; return $this->post('webhooks/wordpress/send-message', $payload); } /** * Get message status by UUID * * @param string $uuid Message UUID * @return WhatsappApiResponse */ public function getMessageStatus(string $uuid): WhatsappApiResponse { if (!$this->isConfigured()) { return WhatsappApiResponse::error('service_not_configured', 'WhatsApp service is not configured'); } return $this->get("webhooks/wordpress/message/{$uuid}"); } /** * Get available credits * * @return WhatsappApiResponse */ public function getCredits(): WhatsappApiResponse { if (!$this->isConfigured()) { return WhatsappApiResponse::error('service_not_configured', 'WhatsApp service is not configured'); } return $this->get('webhooks/wordpress/credits'); } /** * Get available templates * * @return WhatsappApiResponse */ public function getTemplates(): WhatsappApiResponse { if (!$this->isConfigured()) { return WhatsappApiResponse::error('service_not_configured', 'WhatsApp service is not configured'); } return $this->get('webhooks/wordpress/templates'); } /** * Make a GET request * * @param string $endpoint * @param array $query * @return WhatsappApiResponse */ protected function get(string $endpoint, array $query = []): WhatsappApiResponse { $query['api_token'] = $this->apiToken; try { $response = $this->client->get($endpoint, [ 'query' => $query ]); return $this->handleResponse($response); } catch (RequestException $e) { return $this->handleException($e); } catch (GuzzleException $e) { return WhatsappApiResponse::error('request_failed', $e->getMessage()); } } /** * Make a POST request * * @param string $endpoint * @param array $data * @return WhatsappApiResponse */ protected function post(string $endpoint, array $data = []): WhatsappApiResponse { try { $response = $this->client->post($endpoint, [ 'json' => $data ]); return $this->handleResponse($response); } catch (RequestException $e) { return $this->handleException($e); } catch (GuzzleException $e) { return WhatsappApiResponse::error('request_failed', $e->getMessage()); } } /** * Handle HTTP response * * @param \Psr\Http\Message\ResponseInterface $response * @return WhatsappApiResponse */ protected function handleResponse($response): WhatsappApiResponse { $statusCode = $response->getStatusCode(); $body = $response->getBody()->getContents(); $data = json_decode($body, true) ?? []; return new WhatsappApiResponse( success: $data['success'] ?? ($statusCode >= 200 && $statusCode < 300), statusCode: $statusCode, data: $data['data'] ?? [], error: $data['error'] ?? null, message: $data['message'] ?? null, raw: $data ); } /** * Handle request exception * * @param RequestException $e * @return WhatsappApiResponse */ protected function handleException(RequestException $e): WhatsappApiResponse { $response = $e->getResponse(); if ($response) { $body = $response->getBody()->getContents(); $data = json_decode($body, true) ?? []; return new WhatsappApiResponse( success: false, statusCode: $response->getStatusCode(), data: $data['data'] ?? [], error: $data['error'] ?? 'request_exception', message: $data['message'] ?? $e->getMessage(), raw: $data ); } return WhatsappApiResponse::error('connection_failed', $e->getMessage()); } /** * Set custom timeout * * @param int $seconds * @return self */ public function setTimeout(int $seconds): self { $this->timeout = $seconds; return $this; } /** * Create a new instance for a tenant * * @param int $tenantId * @param string|null $baseUrl * @return static */ public static function forTenant(int $tenantId, ?string $baseUrl = null): static { return new static($tenantId, $baseUrl); } }