api_base_url = Aiflab_Chatweb_Config::API_BASE_URL; $this->api_version = Aiflab_Chatweb_Config::API_VERSION; $this->timeout = Aiflab_Chatweb_Config::API_TIMEOUT; $this->api_key = Aiflab_Chatweb_Config::get_setting('api_key', ''); } /** * Get API endpoint URL */ private function get_endpoint_url($endpoint) { return trailingslashit($this->api_base_url) . trailingslashit($this->api_version) . ltrim($endpoint, '/'); } /** * Make HTTP request to API */ private function make_request($method, $endpoint, $data = array(), $headers = array()) { $url = $this->get_endpoint_url($endpoint); // Generate unique request ID for tracking $request_id = uniqid('req_'); // Start timer for duration tracking $start_time = microtime(true); // Default headers $default_headers = array( 'Content-Type' => 'application/json', 'User-Agent' => 'ChatWeb-WordPress-Plugin/' . AIFLAB_CHATWEB_PLUGIN_VERSION ); // Merge headers $headers = array_merge($default_headers, $headers); // Prepare request arguments $args = array( 'method' => $method, 'timeout' => $this->timeout, 'headers' => $headers, 'sslverify' => true ); // Add data to request $request_body = null; if (!empty($data)) { if ($method === 'GET') { $url = add_query_arg($data, $url); } else { $request_body = json_encode($data); $args['body'] = $request_body; } } // Make the request $response = wp_remote_request($url, $args); // Calculate duration $duration_ms = round((microtime(true) - $start_time) * 1000); // Prepare log data $log_data = array( 'method' => $method, 'url' => $url, 'request_headers' => $headers, 'request_body' => $request_body, 'duration_ms' => $duration_ms ); // Handle errors if (is_wp_error($response)) { $error_message = $response->get_error_message(); // Log error $log_data['response_status'] = 0; $log_data['response_body'] = json_encode(array('error' => $error_message)); Aiflab_Chatweb_Debug_Logger::log($log_data); return array( 'success' => false, 'error' => $error_message, 'data' => null, 'request_id' => $request_id ); } // Get response data $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $response_headers = wp_remote_retrieve_headers($response)->getAll(); // Log successful request $log_data['response_status'] = $response_code; $log_data['response_headers'] = $response_headers; $log_data['response_body'] = $response_body; Aiflab_Chatweb_Debug_Logger::log($log_data); // Parse JSON response $parsed_response = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { $error_msg = 'Invalid JSON response: ' . json_last_error_msg(); return array( 'success' => false, 'error' => $error_msg, 'data' => null, 'raw_response' => $response_body, 'request_id' => $request_id ); } // Check if request was successful $success = $response_code >= 200 && $response_code < 300; // Extract data and error message $data = null; $error = null; if (isset($parsed_response['_data'])) { $data = $parsed_response['_data']; } elseif (isset($parsed_response['data'])) { $data = $parsed_response['data']; } if (!$success) { if (isset($parsed_response['_messages'])) { $error = is_array($parsed_response['_messages']) ? implode(', ', $parsed_response['_messages']) : $parsed_response['_messages']; } elseif (isset($parsed_response['error'])) { $error = $parsed_response['error']; } elseif (isset($parsed_response['message'])) { $error = $parsed_response['message']; } else { $error = 'API request failed with status code ' . $response_code; } } return array( 'success' => $success, 'status_code' => $response_code, 'data' => $data, 'error' => $error, 'raw_response' => $parsed_response, 'request_id' => $request_id ); } /** * Test API key connection * * @param string $api_key API key to test * @return array API response */ public function test_api_key($api_key = null) { if (!$api_key) { $api_key = $this->api_key; } if (empty($api_key)) { return array( 'success' => false, 'error' => 'API key is required', 'data' => null ); } $headers = array( 'Authorization' => 'Api-Key ' . $api_key ); return $this->make_request('GET', 'test', array(), $headers); } /** * Get embed code * * @param array $params Parameters for embed code (deprecated, not used) * @return array API response * @deprecated This method now uses the new endpoint /extension/websites/embed * Consider using get_website_embed() directly for better clarity */ public function get_embed_code($params = array()) { // Redirect to new endpoint method for consistency // This maintains backward compatibility while using the new endpoint return $this->get_website_embed(); } /** * Get dashboard data * * @param array $params Parameters for dashboard data * @return array API response */ public function get_dashboard_data($params = array()) { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required. Please configure your API key in settings.', 'data' => null ); } $headers = array( 'Authorization' => 'Api-Key ' . $this->api_key ); return $this->make_request('GET', 'dashboard/data', $params, $headers); } /** * Get user profile * * @return array API response */ public function get_user_profile() { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required. Please configure your API key in settings.', 'data' => null ); } $headers = array( 'Authorization' => 'Api-Key ' . $this->api_key ); return $this->make_request('GET', 'user/profile', array(), $headers); } /** * Check if API key is configured * * @return bool */ public function has_api_key() { return !empty($this->api_key); } /** * Get current API key * * @return string */ public function get_api_key() { return $this->api_key; } /** * Set API key * * @param string $api_key */ public function set_api_key($api_key) { $this->api_key = $api_key; } /** * Make API request to ChatWeb API * * @param string $endpoint API endpoint * @param array $data Request data * @param string $method HTTP method (GET, POST, PUT, DELETE) * @return array Response from API */ public function request($endpoint, $data = array(), $method = 'GET') { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required. Please configure your API key in settings.', 'data' => null ); } // Start timer for duration tracking $start_time = microtime(true); $url = trailingslashit($this->api_base_url) . ltrim($endpoint, '/'); $headers = array( 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Api-Key ' . $this->api_key, 'User-Agent' => 'ChatWeb-WordPress-Plugin/' . AIFLAB_CHATWEB_PLUGIN_VERSION ); // Prepare request arguments $args = array( 'method' => $method, 'timeout' => $this->timeout, 'headers' => $headers, 'sslverify' => true ); // Add data to request $request_body = null; if (!empty($data)) { if ($method === 'GET') { $url = add_query_arg($data, $url); } else { $request_body = json_encode($data); $args['body'] = $request_body; } } // Make the request $response = wp_remote_request($url, $args); // Calculate duration $duration_ms = round((microtime(true) - $start_time) * 1000); // Prepare log data $log_data = array( 'method' => $method, 'url' => $url, 'request_headers' => $headers, 'request_body' => $request_body, 'duration_ms' => $duration_ms ); // Handle errors if (is_wp_error($response)) { $error_message = $response->get_error_message(); // Log error $log_data['response_status'] = 0; $log_data['response_body'] = json_encode(array('error' => $error_message)); Aiflab_Chatweb_Debug_Logger::log($log_data); return array( 'success' => false, 'error' => $error_message, 'data' => null ); } $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $response_headers = wp_remote_retrieve_headers($response)->getAll(); // Log successful request $log_data['response_status'] = $response_code; $log_data['response_headers'] = $response_headers; $log_data['response_body'] = $response_body; Aiflab_Chatweb_Debug_Logger::log($log_data); // Parse JSON response $parsed_response = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { return array( 'success' => false, 'error' => 'Invalid JSON response: ' . json_last_error_msg(), 'data' => null, 'raw_response' => $response_body ); } // Check if request was successful $success = $response_code >= 200 && $response_code < 300; // Extract data and error message $data = null; $error = null; if (isset($parsed_response['_data'])) { $data = $parsed_response['_data']; } elseif (isset($parsed_response['data'])) { $data = $parsed_response['data']; } if (!$success) { if (isset($parsed_response['_messages'])) { $error = is_array($parsed_response['_messages']) ? implode(', ', $parsed_response['_messages']) : $parsed_response['_messages']; } elseif (isset($parsed_response['error'])) { $error = $parsed_response['error']; } elseif (isset($parsed_response['message'])) { $error = $parsed_response['message']; } else { $error = 'API request failed with status code ' . $response_code; } } return array( 'success' => $success, 'status_code' => $response_code, 'data' => $data, 'error' => $error, 'raw_response' => $parsed_response ); } /** * Sync product with ChatWeb API * * @param array $product_data Product data to sync * @return array Response from API */ public function sync_product($product_data) { // Log product sync attempt $this->log_product_sync_attempt($product_data); // Make API request $response = $this->request(Aiflab_Chatweb_Config::API_VERSION . '/extension/products/sync', $product_data, 'POST'); // Log response $this->log_product_sync_response($product_data, $response); return $response; } /** * Log product sync attempt * * @param array $product_data */ private function log_product_sync_attempt($product_data) { $log_data = array( 'time' => current_time('mysql'), 'product_id' => isset($product_data['source_product_id']) ? $product_data['source_product_id'] : (isset($product_data['external_id']) ? $product_data['external_id'] : 'unknown'), 'product_name' => isset($product_data['name']) ? $product_data['name'] : 'unknown', 'action' => 'sync_attempt', 'request_data' => $product_data ); // Write to log but don't interrupt process if it fails // $this->write_to_sync_log($log_data); } /** * Log product sync response * * @param array $product_data * @param array $response */ private function log_product_sync_response($product_data, $response) { $log_data = array( 'time' => current_time('mysql'), 'product_id' => isset($product_data['source_product_id']) ? $product_data['source_product_id'] : (isset($product_data['external_id']) ? $product_data['external_id'] : 'unknown'), 'product_name' => isset($product_data['name']) ? $product_data['name'] : 'unknown', 'action' => 'sync_response', 'success' => isset($response['success']) ? $response['success'] : false, 'status_code' => isset($response['status_code']) ? $response['status_code'] : 0, 'error' => isset($response['error']) ? $response['error'] : null, 'response_data' => $response ); // Write to log but don't interrupt process if it fails // $this->write_to_sync_log($log_data); } /** * Write to sync log file * * @param array $log_data * @return bool Success or failure */ private function write_to_sync_log($log_data) { try { // Get upload directory $upload_dir = wp_upload_dir(); // Check if upload directory is writable if (isset($upload_dir['error']) && $upload_dir['error'] !== false) { return false; } $logs_dir = $upload_dir['basedir'] . '/chatweb-logs'; // Try to create logs directory if it doesn't exist if (!file_exists($logs_dir)) { $dir_created = wp_mkdir_p($logs_dir); if (!$dir_created) { return false; } // Create .htaccess to protect logs $htaccess_file = $logs_dir . '/.htaccess'; $htaccess_content = "Order deny,allow\nDeny from all"; $htaccess_written = @file_put_contents($htaccess_file, $htaccess_content); // Create index.php to prevent directory listing $index_file = $logs_dir . '/index.php'; $index_content = ' $log_data['time'], 'product_id' => $log_data['product_id'], 'product_name' => $log_data['product_name'], 'action' => $log_data['action'] ); if (isset($log_data['success'])) { $summary_data['success'] = $log_data['success']; } if (isset($log_data['status_code'])) { $summary_data['status_code'] = $log_data['status_code']; } if (isset($log_data['error'])) { $summary_data['error'] = $log_data['error']; } // Format summary log entry $summary_log_entry = json_encode($summary_data) . "\n"; // Append to summary log file @file_put_contents($summary_log_file, $summary_log_entry, FILE_APPEND); return true; } catch (Exception $e) { // Catch any unexpected exceptions to prevent disrupting the main process return false; } } /** * Log embed code operations for debugging * * @param string $log_type Type of log entry * @param mixed $log_data Data to log * @return bool Success or failure */ public function log_embed_code_response($log_type, $log_data) { try { // Get upload directory $upload_dir = wp_upload_dir(); // Check if upload directory is writable if (isset($upload_dir['error']) && $upload_dir['error'] !== false) { return false; } $logs_dir = $upload_dir['basedir'] . '/chatweb-logs'; // Try to create logs directory if it doesn't exist if (!file_exists($logs_dir)) { $dir_created = wp_mkdir_p($logs_dir); if (!$dir_created) { return false; } // Create .htaccess to protect logs $htaccess_file = $logs_dir . '/.htaccess'; $htaccess_content = "Order deny,allow\nDeny from all"; @file_put_contents($htaccess_file, $htaccess_content); // Create index.php to prevent directory listing $index_file = $logs_dir . '/index.php'; $index_content = ' gmdate('Y-m-d H:i:s'), 'type' => $log_type, 'data' => $log_data ); // Write to log file with pretty print $log_line = json_encode($log_entry, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n---\n"; $bytes_written = @file_put_contents($log_file, $log_line, FILE_APPEND); return $bytes_written !== false; } catch (Exception $e) { // Catch any unexpected exceptions to prevent disrupting the main process return false; } } /** * Get website embed code * * @return array API response */ public function get_website_embed() { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required', 'data' => null ); } $headers = array( 'Authorization' => 'Api-Key ' . $this->api_key, 'Content-Type' => 'application/json', 'Accept' => 'application/json' ); // Sử dụng đúng endpoint $url = $this->get_endpoint_url('extension/websites/embed'); // Make the request $args = array( 'method' => 'GET', 'timeout' => $this->timeout, 'headers' => $headers, 'sslverify' => true ); $response = wp_remote_request($url, $args); // Handle errors if (is_wp_error($response)) { $error_message = $response->get_error_message(); return array( 'success' => false, 'error' => $error_message, 'data' => null ); } // Get response data $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); // Parse JSON response $parsed_response = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { $error_msg = 'Invalid JSON response: ' . json_last_error_msg(); return array( 'success' => false, 'error' => $error_msg, 'data' => null, 'raw_response' => $response_body ); } // Determine if request was successful based on _success field $success = isset($parsed_response['_success']) ? $parsed_response['_success'] : ($response_code >= 200 && $response_code < 300); // Log parsed response for debugging $this->log_embed_code_response('parsed_response', $parsed_response); if ($success) { // Extract data from _data field $data = []; if (isset($parsed_response['_data'])) { $data = $parsed_response['_data']; // If embed_code exists in _data, save it if (isset($data['embed_code'])) { $embed_code = $data['embed_code']; // Log embed code from API $this->log_embed_code_response('embed_code_from_api', array( 'embed_code' => $embed_code, 'length' => strlen($embed_code), 'has_script_tag' => strpos($embed_code, ' strpos($embed_code, 'data-token') !== false )); // Lưu embed code vào cài đặt với error handling try { $result = Aiflab_Chatweb_Config::set_embed_code($embed_code); // Log save result $this->log_embed_code_response('set_embed_code_result', array( 'save_result' => $result, 'embed_code_length' => strlen($embed_code) )); } catch (Exception $e) { // Log exception $this->log_embed_code_response('set_embed_code_exception', array( 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() )); $result = false; } catch (Error $e) { // Log fatal error $this->log_embed_code_response('set_embed_code_error', array( 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() )); $result = false; } // Kiểm tra lại xem embed code đã được lưu chưa try { $saved_embed_code = Aiflab_Chatweb_Config::get_embed_code(); // Log verification result $this->log_embed_code_response('saved_embed_code_verification', array( 'saved_embed_code' => $saved_embed_code, 'saved_length' => strlen($saved_embed_code), 'matches_original' => ($saved_embed_code === $embed_code), 'is_empty' => empty($saved_embed_code), 'has_script_tag' => strpos($saved_embed_code, ' strpos($saved_embed_code, 'data-token') !== false )); // Also check database directly global $wpdb; $db_embed_code = $wpdb->get_var($wpdb->prepare( "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", 'aiflab_chatweb_embed_code' )); $db_embed_code_b64 = $wpdb->get_var($wpdb->prepare( "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", 'aiflab_chatweb_embed_code_b64' )); $this->log_embed_code_response('database_check', array( 'aiflab_embed_code_exists' => !empty($db_embed_code), 'aiflab_embed_code_length' => strlen($db_embed_code ?: ''), 'aiflab_embed_code_b64_exists' => !empty($db_embed_code_b64), 'aiflab_embed_code_b64_length' => strlen($db_embed_code_b64 ?: ''), 'db_embed_code_matches' => ($db_embed_code === $embed_code) )); } catch (Exception $e) { $this->log_embed_code_response('get_embed_code_exception', array( 'error' => $e->getMessage() )); } } } return array( 'success' => true, 'data' => $data, 'http_code' => $response_code ); } else { // Extract error message $error = 'Unknown error'; if (isset($parsed_response['_messages'])) { $error = is_array($parsed_response['_messages']) ? implode(', ', $parsed_response['_messages']) : $parsed_response['_messages']; } elseif (isset($parsed_response['error'])) { $error = $parsed_response['error']; } elseif (isset($parsed_response['message'])) { $error = $parsed_response['message']; } return array( 'success' => false, 'error' => $error, 'data' => null, 'http_code' => $response_code, 'response' => $parsed_response ); } } /** * Activate website (only needed once per API key) * * Handles both success (200) and "already active" (400) responses as OK * * @return array API response */ public function activate_website() { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required', 'data' => null ); } $headers = array( 'Authorization' => 'Api-Key ' . $this->api_key, 'Content-Type' => 'application/json', 'Accept' => 'application/json' ); $url = $this->get_endpoint_url('extension/websites/active'); $args = array( 'method' => 'POST', 'timeout' => $this->timeout, 'headers' => $headers, 'sslverify' => true, 'body' => json_encode(array()) ); $response = wp_remote_request($url, $args); if (is_wp_error($response)) { return array( 'success' => false, 'error' => $response->get_error_message(), 'data' => null ); } $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $parsed = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { return array( 'success' => false, 'error' => 'Invalid JSON response', 'data' => null ); } // Check if request was successful $is_success = isset($parsed['_success']) ? $parsed['_success'] : ($response_code >= 200 && $response_code < 300); // Handle "Website is already active." (400) as success case $is_already_active = (!$is_success && isset($parsed['_messages'][0]) && strpos($parsed['_messages'][0], 'already active') !== false); $messages = isset($parsed['_messages']) ? $parsed['_messages'] : array(); // Both success and already-active are OK to proceed if ($is_success || $is_already_active) { return array( 'success' => true, 'data' => $parsed['_data'] ?? null, 'messages' => $messages, 'http_code' => $response_code, 'already_active' => $is_already_active ); } // Real error case $error = !empty($messages) ? implode(', ', $messages) : 'Website activation failed'; return array( 'success' => false, 'error' => $error, 'data' => null, 'http_code' => $response_code ); } /** * Check if current API key needs activation * * @return bool True if activation is needed */ public function needs_activation() { if (empty($this->api_key)) { return false; } $current_hash = md5($this->api_key); $activated_hash = Aiflab_Chatweb_Config::get_setting('activated_api_key_hash', ''); return $current_hash !== $activated_hash; } /** * Mark current API key as activated * * @return bool True if successfully marked */ public function mark_as_activated() { if (!empty($this->api_key)) { $hash = md5($this->api_key); return Aiflab_Chatweb_Config::update_setting('activated_api_key_hash', $hash); } return false; } /** * Upload a file to API endpoint using multipart/form-data * * @param string $endpoint API endpoint * @param string $file_path Absolute path to file * @param string $field_name Form field name for file (default: 'file') * @return array API response */ public function upload_file($endpoint, $file_path, $field_name = 'file') { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required', 'data' => null ); } if (!file_exists($file_path)) { return array( 'success' => false, 'error' => 'File not found: ' . $file_path, 'data' => null ); } // Start timer for duration tracking $start_time = microtime(true); $url = $this->get_endpoint_url($endpoint); // Generate unique boundary $boundary = wp_generate_password(24, false); // Read file content $file_content = file_get_contents($file_path); $file_name = basename($file_path); // Determine content type based on file extension $file_extension = pathinfo($file_path, PATHINFO_EXTENSION); $content_type = ($file_extension === 'json') ? 'application/json' : 'application/octet-stream'; // Build multipart body $body = "--{$boundary}\r\n"; $body .= "Content-Disposition: form-data; name=\"{$field_name}\"; filename=\"{$file_name}\"\r\n"; $body .= "Content-Type: {$content_type}\r\n\r\n"; $body .= $file_content . "\r\n"; $body .= "--{$boundary}--\r\n"; $headers = array( 'Authorization' => 'Api-Key ' . $this->api_key, 'Content-Type' => 'multipart/form-data; boundary=' . $boundary, 'Accept' => 'application/json' ); // Make request $response = wp_remote_post($url, array( 'headers' => $headers, 'body' => $body, 'timeout' => 60, 'sslverify' => true )); // Calculate duration $duration_ms = round((microtime(true) - $start_time) * 1000); // Prepare log data (don't log file content, just file info) $log_data = array( 'method' => 'POST', 'url' => $url, 'request_headers' => $headers, 'request_body' => json_encode(array( 'file_name' => $file_name, 'file_size' => strlen($file_content), 'content_type' => $content_type )), 'duration_ms' => $duration_ms ); // Handle WP errors if (is_wp_error($response)) { $log_data['response_status'] = 0; $log_data['response_body'] = json_encode(array('error' => $response->get_error_message())); Aiflab_Chatweb_Debug_Logger::log($log_data); return array( 'success' => false, 'error' => $response->get_error_message(), 'data' => null ); } // Parse response $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $response_headers = wp_remote_retrieve_headers($response)->getAll(); // Log the request $log_data['response_status'] = $response_code; $log_data['response_headers'] = $response_headers; $log_data['response_body'] = $response_body; Aiflab_Chatweb_Debug_Logger::log($log_data); $parsed = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { return array( 'success' => false, 'error' => 'Invalid JSON response', 'data' => null, 'raw_response' => $response_body ); } // Check success - HTTP 2xx is considered successful // Handle both old format (_success, _data, _messages) and new format (message) $success = isset($parsed['_success']) ? $parsed['_success'] : ($response_code >= 200 && $response_code < 300); if ($success) { // Get message from either format $message = null; if (isset($parsed['message'])) { $message = $parsed['message']; } elseif (isset($parsed['_messages'])) { $message = is_array($parsed['_messages']) ? implode(', ', $parsed['_messages']) : $parsed['_messages']; } return array( 'success' => true, 'data' => $parsed['_data'] ?? $parsed['data'] ?? null, 'message' => $message, 'messages' => $parsed['_messages'] ?? array(), 'http_code' => $response_code ); } // Error case $error = 'Upload failed'; if (isset($parsed['_messages'])) { $error = is_array($parsed['_messages']) ? implode(', ', $parsed['_messages']) : $parsed['_messages']; } elseif (isset($parsed['message'])) { $error = $parsed['message']; } elseif (isset($parsed['error'])) { $error = $parsed['error']; } return array( 'success' => false, 'error' => $error, 'data' => null, 'http_code' => $response_code ); } /** * Delete product from ChatWeb API * * @param int $product_id WooCommerce product ID * @return array API response */ public function delete_product($product_id) { if (empty($this->api_key)) { return array( 'success' => false, 'error' => 'API key is required. Please configure your API key in settings.', 'data' => null ); } // Start timer for duration tracking $start_time = microtime(true); // Prepare API endpoint (without api/v1 prefix - get_endpoint_url adds it) $endpoint = 'extension/products/woocommerce/' . $product_id; // Prepare headers $headers = array( 'Authorization' => 'Api-Key ' . $this->api_key, 'Accept' => 'application/json' ); // Make DELETE request $url = $this->get_endpoint_url($endpoint); $args = array( 'method' => 'DELETE', 'timeout' => $this->timeout, 'headers' => $headers, 'sslverify' => true ); // Make the request $response = wp_remote_request($url, $args); // Calculate duration $duration_ms = round((microtime(true) - $start_time) * 1000); // Prepare log data $log_data = array( 'method' => 'DELETE', 'url' => $url, 'request_headers' => $headers, 'request_body' => json_encode(array('product_id' => $product_id)), 'duration_ms' => $duration_ms ); // Handle errors if (is_wp_error($response)) { $error_message = $response->get_error_message(); // Log error $log_data['response_status'] = 0; $log_data['response_body'] = json_encode(array('error' => $error_message)); Aiflab_Chatweb_Debug_Logger::log($log_data); return array( 'success' => false, 'error' => $error_message, 'data' => null ); } // Get response data $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $response_headers = wp_remote_retrieve_headers($response)->getAll(); // Log the request $log_data['response_status'] = $response_code; $log_data['response_headers'] = $response_headers; $log_data['response_body'] = $response_body; Aiflab_Chatweb_Debug_Logger::log($log_data); // Parse JSON response $parsed_response = json_decode($response_body, true); if (json_last_error() !== JSON_ERROR_NONE) { return array( 'success' => false, 'error' => 'Invalid JSON response', 'data' => null, 'raw_response' => $response_body ); } // Check if request was successful $success = $response_code >= 200 && $response_code < 300; // Get error message from response $error = null; if (!$success) { if (isset($parsed_response['_messages'])) { $error = is_array($parsed_response['_messages']) ? implode(', ', $parsed_response['_messages']) : $parsed_response['_messages']; } elseif (isset($parsed_response['message'])) { $error = $parsed_response['message']; } else { $error = 'API request failed with status code ' . $response_code; } } return array( 'success' => $success, 'status_code' => $response_code, 'data' => $parsed_response['_data'] ?? $parsed_response['data'] ?? null, 'message' => $parsed_response['message'] ?? null, 'error' => $error ); } }