1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
sender.php
См. документацию.
1<?php
2
3namespace Bitrix\Seo\Analytics\Services\Helpers\Yandex;
4
5use Bitrix\Main\Error;
6use Bitrix\Main\Result;
7use Bitrix\Main\Type\Date;
8use Bitrix\Main\Data\Cache;
9use Bitrix\Main\Web\Json;
10use Bitrix\Main\SystemException;
11use Bitrix\Main\Localization\Loc;
12use Bitrix\Seo\Analytics\Services\AccountYandex;
13use Bitrix\Seo\Retargeting\AdsHttpClient;
14
15class Sender
16{
17 private AccountYandex $accountYandex;
18 private ?array $profile = null;
19 private ?string $currency = null;
20
21 public function __construct(AccountYandex $accountYandex)
22 {
23 $this->accountYandex = $accountYandex;
24 }
25
26 private function getProfile(): Result
27 {
28 $result = new Result();
29
30 if ($this->profile !== null)
31 {
32 $result->setData($this->profile);
33
34 return $result;
35 }
36
37 $profile = $this->accountYandex->getProfile();
38 if ($profile === null || empty($profile['NAME']))
39 {
40 $result->addError(new Error('Can not find user name for yandex account.'));
41
42 return $result;
43 }
44
45 $this->profile = $profile;
46 $result->setData($this->profile);
47
48 return $result;
49 }
50
51 private function getClient(array $headers = []): Result
52 {
53 $result = new Result();
54
55 $profile = $this->getProfile();
56 if (!$profile->isSuccess())
57 {
58 return $result->addErrors($profile->getErrors());
59 }
60
61 $client = clone $this->accountYandex->getRequest()->getClient();
62 $client->setHeader('Authorization', 'Bearer ' . $this->getAuthToken());
63 $client->setHeader('Client-Login', $profile->getData()['NAME']);
64
65 foreach ($headers as $name => $value)
66 {
67 $client->setHeader($name, $value);
68 }
69
70 return $result->setData(['client' => $client]);
71 }
72
73 private function getAuthToken()
74 {
75 return $this->accountYandex->getRequest()->getAuthAdapter()->getToken();
76 }
77
85 public function getDailyExpensesReport(Date $dateFrom, Date $dateTo): ResponseResult
86 {
87 $reportName = sprintf(
88 'AdsReport_%s',
89 md5($dateFrom->format('Y-m-d') . $dateTo->format('Y-m-d')),
90 );
91
92 $request = [
93 'params' => [
94 'SelectionCriteria' => [
95 'DateFrom' => $dateFrom->format('Y-m-d'),
96 'DateTo' => $dateTo->format('Y-m-d'),
97 ],
98 'FieldNames' => [
99 'Date',
100 'AdId',
101 'AdGroupId',
102 'AdGroupName',
103 'CampaignId',
104 'CampaignName',
105 'Impressions',
106 'Clicks',
107 'Cost',
108 'Conversions',
109 'AvgCpc',
110 ],
111 'ReportName' => $reportName,
112 'ReportType' => 'AD_PERFORMANCE_REPORT',
113 'DateRangeType' => 'CUSTOM_DATE',
114 'Format' => 'TSV',
115 'IncludeVAT' => 'YES',
116 'IncludeDiscount' => 'NO',
117 ],
118 ];
119
120 $headers = [
121 'returnMoneyInMicros' => 'false',
122 'skipReportHeader' => 'true',
123 ];
124
125 return $this->getEntityData('reports', $request, $headers);
126 }
127
134 public function getAds(array $campaignIds): ResponseResult
135 {
136 $request = [
137 'method' => 'get',
138 'params' => [
139 'SelectionCriteria' => [
140 'CampaignIds' => $campaignIds,
141 ],
142 'FieldNames' => [
143 'Id',
144 'CampaignId',
145 'Type',
146 ],
147 'TextAdFieldNames' => [
148 'Title',
149 'Href',
150 ],
151 'TextImageAdFieldNames' => [
152 'Href',
153 ],
154 ],
155 ];
156
157 return $this->getEntityData('ads', $request);
158 }
159
165 public function getCurrency(): ?string
166 {
167 if ($this->currency !== null)
168 {
169 return $this->currency;
170 }
171
172 // currency is global for an account, so we get it from the first campaign.
173 $cacheString = 'analytics_yandex_currency';
174 $cachePath = '/seo/analytics/yandex/';
175 $cacheTime = 3600;
176 $cache = Cache::createInstance();
177 $currency = null;
178 if ($cache->initCache($cacheTime, $cacheString, $cachePath))
179 {
180 $currency = $cache->getVars()['currency'];
181 }
182
183 if (!empty($currency))
184 {
185 $this->currency = (string)$currency;
186
187 return $this->currency;
188 }
189
190 $cache->clean($cacheString, $cachePath);
191
192 $request = [
193 'method' => 'get',
194 'params' => [
195 'SelectionCriteria' => new \stdClass(),
196 'FieldNames' => ['Currency'],
197 'Page' => [
198 'Limit' => 1,
199 ],
200 ],
201 ];
202
203 $response = $this->getEntityData('campaigns', $request);
204 if (!$response->isSuccess())
205 {
206 return null;
207 }
208
209 $response = $response->getResponse();
210
211 if (isset($response['result']['Campaigns']))
212 {
213 $firstCampaign = current($response['result']['Campaigns']);
214 $currency = $firstCampaign['Currency'] ?? null;
215 }
216
217 if (!$currency)
218 {
219 return null;
220 }
221
222 if ($cache->startDataCache($cacheTime))
223 {
224 $cache->endDataCache(['currency' => $currency]);
225 }
226
227 $this->currency = (string)$currency;
228
229 return $this->currency;
230 }
231
240 private function getEntityData(string $entityName, array $request, array $headers = []): ResponseResult
241 {
242 $result = new ResponseResult();
243
244 $clientResult = $this->getClient($headers);
245 if (!$clientResult->isSuccess())
246 {
247 return $result->addErrors($clientResult->getErrors());
248 }
249
251 $client = $clientResult->getData()['client'];
252
253 $sendResult = $this->send($client, $this->getYandexServerAddress($entityName), $request);
254 if (!$sendResult->isSuccess())
255 {
256 return $result->addErrors($sendResult->getErrors());
257 }
258
259 $response = $sendResult->getResponse();
260
261 if (!$response)
262 {
263 return $result->addError(new Error("Empty response for {$entityName}"));
264 }
265
266 if ($client->getHeaders()->getContentType() === 'application/json')
267 {
268 try
269 {
270 $response = Json::decode($response);
271 }
272 catch (\Exception $exception)
273 {
274 return $result->addError(new Error($exception->getMessage()));
275 }
276 }
277
278 if (isset($response['error']) && is_array($response['error']))
279 {
280 return $result->addError(self::getErrorByResponse($response['error']));
281 }
282
283 $result->setResponse($response);
284
285 return $result;
286 }
287
296 private function send(AdsHttpClient $client, string $url, array $request): ResponseResult
297 {
298 $result = new ResponseResult();
299
300 while (true)
301 {
302 $response = $client->post($url, Json::encode($request));
303
304 if ($client->getStatus() === 200)
305 {
306 $result->setResponse($response);
307
308 break;
309 }
310 else
311 {
312 $errorByHttpStatus = self::getErrorByHttpStatus($client->getStatus());
313 if ($errorByHttpStatus->getCode() === 201 || $errorByHttpStatus->getCode() === 202)
314 {
315 $retryIn = (int)($client->getHeaders()->get('retryIn') ?? 10);
316 sleep($retryIn);
317 }
318 else
319 {
320 $result->addError($errorByHttpStatus);
321
322 break;
323 }
324 }
325 }
326
327 return $result;
328 }
329
330 private function getYandexServerAddress(string $source): string
331 {
332 $url = 'https://api.direct.yandex.com/json/v5/';
333
334 match ($source)
335 {
336 'campaigns' => $url .= 'campaigns',
337 'reports' => $url .= 'reports',
338 'ads' => $url .= 'ads',
339 default => throw new SystemException("Unknown source {$source}"),
340 };
341
342 return $url;
343 }
344
345 public static function getErrorByHttpStatus(int $status): Error
346 {
347 // https://yandex.ru/dev/direct/doc/ru/php5-curl-stat2
348 $message = Loc::getMessage('SEO_ANALYTICS_SERVICE_HELPERS_YANDEX_SENDER_HTTP_ERROR_UNKNOWN');
349
350 if ($status === 201)
351 {
352 $message = Loc::getMessage('SEO_ANALYTICS_SERVICE_HELPERS_YANDEX_SENDER_HTTP_ERROR_201');
353 }
354 elseif ($status === 202)
355 {
356 $message = Loc::getMessage('SEO_ANALYTICS_SERVICE_HELPERS_YANDEX_SENDER_HTTP_ERROR_202');
357 }
358 elseif ($status === 400)
359 {
360 $message = Loc::getMessage('SEO_ANALYTICS_SERVICE_HELPERS_YANDEX_SENDER_HTTP_ERROR_400');
361 }
362 elseif ($status === 500)
363 {
364 $message = Loc::getMessage('SEO_ANALYTICS_SERVICE_HELPERS_YANDEX_SENDER_HTTP_ERROR_500');
365 }
366 elseif ($status === 502)
367 {
368 $message = Loc::getMessage('SEO_ANALYTICS_SERVICE_HELPERS_YANDEX_SENDER_HTTP_ERROR_502');
369 }
370
371 return new Error($message, $status);
372 }
373
374 private static function getErrorByResponse(array $error): Error
375 {
376 $message = 'Unknown error';
377 $code = 0;
378
379 if (isset($error['error_string']))
380 {
381 $message = $error['error_string'];
382
383 if (isset($error['error_detail']))
384 {
385 $message .= '; ' . $error['error_detail'];
386 }
387 }
388
389 if (isset($error['error_code']))
390 {
391 $code = (int)$error['error_code'];
392 }
393
394 return new Error($message, $code);
395 }
396}
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
Определения catalog_reindex.php:36
Определения result.php:20
Определения error.php:15
Определения date.php:9
format($format)
Определения date.php:110
__construct(AccountYandex $accountYandex)
Определения sender.php:21
static getErrorByHttpStatus(int $status)
Определения sender.php:345
getDailyExpensesReport(Date $dateFrom, Date $dateTo)
Определения sender.php:85
getAds(array $campaignIds)
Определения sender.php:134
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$status
Определения session.php:10
$name
Определения menu_edit.php:35
$message
Определения payment.php:8
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$currency
Определения template.php:266
$response
Определения result.php:21
$error
Определения subscription_card_product.php:20
$url
Определения iframe.php:7