PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.8
ووسلام – همگام سازی ووکامرس و باسلام v1.10.8
1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 1.8.6 All 53 releases
sync-basalam / includes / Services / Api / ApiResponseHandler.php

ApiResponseHandler.php in ووسلام – همگام سازی ووکامرس و باسلام 1.10.8, at includes/Services/Api/ApiResponseHandler.php

165 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SyncBasalam\Services\Api;
4
5 use SyncBasalam\Admin\Settings\SettingsConfig;
6 use SyncBasalam\Admin\Settings\SettingsManager;
7 use SyncBasalam\Jobs\Exceptions\RetryableException;
8 use SyncBasalam\Jobs\Exceptions\NonRetryableException;
9
10 defined('ABSPATH') || exit;
11
12 class ApiResponseHandler
13 {
14 public function handle($response, $url = ''): array
15 {
16 if (is_wp_error($response)) {
17 return $this->handleWpError($response, $url);
18 }
19
20 $body = wp_remote_retrieve_body($response);
21
22 $statusCodeRaw = wp_remote_retrieve_response_code($response);
23 $statusCode = is_numeric($statusCodeRaw) ? (int) $statusCodeRaw : 0;
24
25 return $this->handleHttpStatusCode($statusCode, $body, $url);
26 }
27
28
29 private function handleWpError(\WP_Error $response, string $url = ''): array
30 {
31 $errorMessage = $response->get_error_message();
32 $category = RequestStatusTracker::recordWpError($response, $url);
33 $reason = RequestStatusTracker::describeCategoryFa($category);
34
35 if ($category === 'blocked_http') {
36 throw new BlockedHttpRequestException(esc_html($reason . ' | جزئیات فنی: ' . $errorMessage));
37 }
38
39 if ($category === 'timeout') {
40 throw RetryableException::apiTimeout(esc_html($reason . ' | جزئیات فنی: ' . $errorMessage));
41 }
42
43 if (in_array($category, ['dns_error', 'ssl_error', 'connection_error', 'network_error'], true)) {
44 throw RetryableException::networkError(esc_html($reason . ' | جزئیات فنی: ' . $errorMessage));
45 }
46
47 throw RetryableException::temporary(esc_html($reason . ' | جزئیات فنی: ' . $errorMessage));
48 }
49
50 private function handleHttpStatusCode(int $statusCode, $body, $url): array
51 {
52 RequestStatusTracker::recordHttpStatus($statusCode, $url);
53
54 if ($statusCode === 0) {
55 throw new BlockedHttpRequestException(esc_html(RequestStatusTracker::describeHttpStatusFa(0)));
56 }
57
58 if (in_array($statusCode, [200, 201, 202], true)) {
59 return $this->successResponse($body, $statusCode);
60 }
61
62 if (in_array($statusCode, [408, 504], true)) {
63 throw RetryableException::apiTimeout(esc_html(RequestStatusTracker::describeHttpStatusFa($statusCode)));
64 }
65
66 if ($statusCode === 429) {
67 throw RetryableException::rateLimit(esc_html(RequestStatusTracker::describeHttpStatusFa(429)));
68 }
69
70 if (in_array($statusCode, [500, 502, 503], true)) {
71 throw RetryableException::serverError(esc_html(RequestStatusTracker::describeHttpStatusFa($statusCode)));
72 }
73
74 if ($statusCode === 401) {
75 if ($this->isBasalamDomain($url)) {
76 SettingsManager::updateSettings([
77 SettingsConfig::TOKEN => null,
78 SettingsConfig::REFRESH_TOKEN => null,
79 ]);
80 }
81 throw NonRetryableException::unauthorized(esc_html(RequestStatusTracker::describeHttpStatusFa(401)));
82 }
83
84 $clientErrors = [
85 400 => 'درخواست نا�
86 عتبر',
87 403 => 'دسترسی غیر�
88 جاز',
89 404 => '�
90 نبع �
91 ورد نظر یافت نشد',
92 422 => 'خطا در پردازش داده‌ها',
93 ];
94
95 if (isset($clientErrors[$statusCode])) {
96 $bodyMessage = $this->extractErrorMessageFromBody($body);
97 $base = $bodyMessage ?: $clientErrors[$statusCode];
98 $reason = RequestStatusTracker::describeHttpStatusFa($statusCode);
99 throw NonRetryableException::permanent(esc_html($base . $reason))
100 ->setResponseData($this->decodeBody($body));
101 }
102
103 // Unknown error - treat as retryable
104 throw RetryableException::temporary(esc_html(RequestStatusTracker::describeHttpStatusFa($statusCode)));
105 }
106
107 private function decodeBody($body): ?array
108 {
109 if (is_array($body)) return $body;
110
111 if (is_string($body) && $body !== '') {
112 $decoded = json_decode($body, true);
113 if (is_array($decoded)) return $decoded;
114 }
115
116 return null;
117 }
118
119 private function extractErrorMessageFromBody($body): ?string
120 {
121 if (empty($body)) return null;
122
123 if (is_string($body)) {
124 $decoded = json_decode($body, true);
125 if (is_array($decoded)) {
126 $body = $decoded;
127 }
128 }
129
130 if (is_array($body)) {
131 if (!empty($body['errors'][0]['message'])) return $body['errors'][0]['message'];
132 if (isset($body['messages'][0]['message'])) return $body['messages'][0]['message'];
133 if (isset($body['message'])) return $body['message'];
134 if (isset($body['error'])) return $body['error'];
135 }
136
137 return null;
138 }
139
140 private function isBasalamDomain(string $url): bool
141 {
142 $host = parse_url($url, PHP_URL_HOST);
143
144 if (!is_string($host) || $host === '') return false;
145
146
147 return $host === 'basalam.com' || substr(strtolower($host), -strlen('.basalam.com')) === '.basalam.com';
148 }
149
150 private function successResponse($body, int $statusCode): array
151 {
152 return [
153 'body' => $body,
154 'status_code' => $statusCode,
155 'success' => true
156 ];
157 }
158
159 public function handleTimeout(string $url): array
160 {
161 RequestStatusTracker::recordCategory('timeout', ['url' => $url]);
162 throw RetryableException::apiTimeout(esc_html(RequestStatusTracker::describeCategoryFa('timeout')));
163 }
164 }
165