base_url = untrailingslashit($base_url); } public function register_site(): array { $payload = [ 'domain' => wp_parse_url(home_url(), PHP_URL_HOST), 'wc_version' => defined('WC_VERSION') ? WC_VERSION : 'unknown', 'wp_version' => get_bloginfo('version'), 'locale' => get_locale(), 'plugin_version' => AIRF_VERSION, ]; $body = wp_json_encode($payload); $headers = ['Content-Type' => 'application/json']; // Sign re-registration requests to prove domain ownership $signing_secret = get_option(AIRF_OPTION_SIGNING_SECRET, ''); if ($signing_secret) { $headers['X-Signature'] = hash_hmac('sha256', $body, $signing_secret); } $response = wp_remote_post($this->base_url . '/api/register', [ 'headers' => $headers, 'body' => $body, 'timeout' => 25, ]); return $this->normalize_response($response); } /** * Step 1 of email-verified registration. * Sends a 6-digit verification code to the provided email address. * * @param string $email The recovery email chosen by the admin. */ public function register_init(string $email): array { $payload = [ 'domain' => wp_parse_url(home_url(), PHP_URL_HOST), 'admin_email' => $email, 'wc_version' => defined('WC_VERSION') ? WC_VERSION : 'unknown', 'wp_version' => get_bloginfo('version'), 'locale' => get_locale(), 'plugin_version' => AIRF_VERSION, ]; $response = wp_remote_post($this->base_url . '/api/register/init', [ 'headers' => ['Content-Type' => 'application/json'], 'body' => wp_json_encode($payload), 'timeout' => 25, ]); return $this->normalize_response($response); } /** * Step 2 of email-verified registration. * Submits the 6-digit code to complete registration or recovery. */ public function register_verify(string $code): array { $payload = [ 'domain' => wp_parse_url(home_url(), PHP_URL_HOST), 'code' => $code, 'wc_version' => defined('WC_VERSION') ? WC_VERSION : 'unknown', 'wp_version' => get_bloginfo('version'), 'locale' => get_locale(), 'plugin_version' => AIRF_VERSION, ]; $response = wp_remote_post($this->base_url . '/api/register/verify', [ 'headers' => ['Content-Type' => 'application/json'], 'body' => wp_json_encode($payload), 'timeout' => 25, ]); return $this->normalize_response($response); } public function get_plan_status(string $site_token): array { $response = wp_remote_get($this->base_url . '/api/plan-status', [ 'headers' => [ 'X-Site-Token' => $site_token, ], 'timeout' => 15, ]); return $this->normalize_response($response); } public function analyze_store(string $site_token, array $payload): array { $body = wp_json_encode($payload); $signing_secret = get_option(AIRF_OPTION_SIGNING_SECRET, ''); $signature = hash_hmac('sha256', $body, $signing_secret); $timeout = (int) apply_filters('airf_api_analyze_timeout', 240); if ($timeout < 25) { $timeout = 25; } $response = wp_remote_post($this->base_url . '/api/analyze', [ 'headers' => [ 'Content-Type' => 'application/json', 'X-Site-Token' => $site_token, 'X-Signature' => $signature, ], 'body' => $body, 'timeout' => $timeout, ]); return $this->normalize_response($response); } public function get_analysis_history(string $site_token, int $page = 1, int $per_page = 50): array { $url = $this->base_url . '/api/history?' . http_build_query([ 'page' => max(1, $page), 'per_page' => min(100, max(1, $per_page)), ]); $response = wp_remote_get($url, [ 'headers' => [ 'X-Site-Token' => $site_token, ], 'timeout' => 15, ]); return $this->normalize_response($response); } public function get_cached_analysis(string $site_token): array { $response = wp_remote_get($this->base_url . '/api/cached-analysis', [ 'headers' => [ 'X-Site-Token' => $site_token, ], 'timeout' => 15, ]); return $this->normalize_response($response); } public function get_customer_countries(string $site_token): array { $response = wp_remote_get($this->base_url . '/api/settings/countries', [ 'headers' => [ 'X-Site-Token' => $site_token, ], 'timeout' => $this->get_settings_request_timeout(), ]); return $this->normalize_response($response); } public function update_customer_countries(string $site_token, array $countries): array { $response = wp_remote_request($this->base_url . '/api/settings/countries', [ 'method' => 'PUT', 'headers' => [ 'Content-Type' => 'application/json', 'X-Site-Token' => $site_token, ], 'body' => wp_json_encode(['countries' => $countries]), 'timeout' => $this->get_settings_request_timeout(), ]); return $this->normalize_response($response); } private function get_settings_request_timeout(): int { return max(15, (int) apply_filters('airf_api_settings_request_timeout', 90)); } private function normalize_response($response): array { if (is_wp_error($response)) { return [ 'ok' => false, 'status' => 0, 'data' => null, 'message' => $response->get_error_message(), ]; } $status = wp_remote_retrieve_response_code($response); $raw_body = wp_remote_retrieve_body($response); $data = json_decode($raw_body, true); $message = null; if (is_array($data)) { if (isset($data['error']) && is_string($data['error']) && $data['error'] !== '') { $message = $data['error']; } elseif (isset($data['message']) && is_string($data['message']) && $data['message'] !== '') { $message = $data['message']; } } if ($message === null && $status >= 400) { $message = 'Request failed (' . $status . ').'; } $error_code = null; if (is_array($data) && isset($data['code']) && is_string($data['code'])) { $error_code = $data['code']; } return [ 'ok' => $status >= 200 && $status < 300, 'status' => $status, 'data' => is_array($data) ? $data : null, 'message' => $message, 'code' => $error_code, ]; } }