1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
apple.php
См. документацию.
1<?php
2
8
10
12{
13 public const ID = 'apple';
14 public const LOGIN_PREFIX = 'apple_';
15 private const CONTROLLER_URL = 'https://www.bitrix24.ru/controller';
16
17 protected $entityOAuth;
18
19 public function GetSettings()
20 {
21 return [
22 ['apple_client_id', Loc::getMessage('SOCSERV_APPLE_ID'), '', ['text', 40]],
23 ['apple_key_id', Loc::getMessage('SOCSERV_APPLE_KEY_ID'), '', ['text', 40]],
24 ['apple_team_id', Loc::getMessage('SOCSERV_APPLE_TEAM_ID'), '', ['text', 40]],
25 ['apple_key_pem', Loc::getMessage('SOCSERV_APPLE_KEY_PEM'), '', ['textarea', 10, 40]],
26 [
27 'note' => getMessage('SOCSERV_APPLE_SETT_NOTE_2'),
28 ],
29 ];
30 }
31
36 public function getEntityOAuth($code = false): CAppleInterface
37 {
38 if (!$this->entityOAuth)
39 {
40 $this->entityOAuth = new CAppleInterface();
41 }
42
43 if ($code !== false)
44 {
45 $this->entityOAuth->setCode($code);
46 }
47
48 return $this->entityOAuth;
49 }
50
51 public function GetFormHtml($arParams)
52 {
53 $phrase = ($arParams['FOR_INTRANET'])
54 ? GetMessage('SOCSERV_APPLE_NOTE_INTRANET')
55 : GetMessage('SOCSERV_APPLE_NOTE');
56
57 return $arParams['FOR_INTRANET']
58 ? array('ON_CLICK' => 'onclick="'.\CSocServApple::GetOnClickJs($arParams).'"')
59 : '<a href="javascript:void(0)" onclick="'.\CSocServApple::GetOnClickJs($arParams).'" class="bx-ss-button apple-button"></a><span class="bx-spacer"></span><span>' . $phrase . '</span>';
60 }
61
62 public function GetOnClickJs($arParams): string
63 {
64 $url = $this->getUrl($arParams);
65 $controllerUrl = \Bitrix\Main\Engine\UrlManager::getInstance()->create('socialservices.authflow.signinapple', [])->getUri();
66
67 return "top.location.href = '{$controllerUrl}&url=" . urlencode(CUtil::JSEscape($url)) . "'";
68 }
69
70 public function getUrl($arParams): string
71 {
72 global $APPLICATION;
73
74 if (defined('BX24_HOST_NAME') && IsModuleInstalled('bitrix24'))
75 {
76 $redirect_uri = static::CONTROLLER_URL . '/redirect.php';
77 $state = $this->getEntityOAuth()->GetRedirectURI() . '?check_key=' . \CSocServAuthManager::getUniqueKey() . '&state=';
78 $backurl = $APPLICATION->GetCurPageParam('', ['logout', 'auth_service_error', 'auth_service_id', 'backurl']);
79 $state .= urlencode('state=' . urlencode('backurl=' . urlencode($backurl) . (isset($arParams['BACKURL']) ? '&redirect_url=' . urlencode($arParams['BACKURL']) : '')));
80 }
81 else
82 {
83 $state = 'site_id=' . SITE_ID . '&backurl=' .
84 urlencode($APPLICATION->GetCurPageParam('check_key=' . \CSocServAuthManager::getUniqueKey(), ['logout', 'auth_service_error', 'auth_service_id', 'backurl'])) .
85 (isset($arParams['BACKURL']) ? '&redirect_url=' . urlencode($arParams['BACKURL']) : '');
86
87 $redirect_uri = $this->getEntityOAuth()->GetRedirectURI();
88 }
89
90 return $this->getEntityOAuth()->GetAuthUrl($redirect_uri, $state);
91 }
92
93 public function addScope($scope): CAppleInterface
94 {
95 return $this->getEntityOAuth()->addScope($scope);
96 }
97
98 public function prepareUser($arUser): array
99 {
100 $entityOAuth = $this->getEntityOAuth();
101 $arFields = [
102 'EXTERNAL_AUTH_ID' => self::ID,
103 'XML_ID' => $arUser['sub'],
104 'LOGIN' => self::LOGIN_PREFIX.$arUser['sub'],
105 'EMAIL' => $arUser['email'],
106 'OATOKEN' => $entityOAuth->getToken(),
107 'OATOKEN_EXPIRES' => $entityOAuth->getAccessTokenExpires(),
108 ];
109
110 if (isset($arUser['first_name']))
111 {
112 $arFields['NAME'] = $arUser['first_name'];
113 }
114
115 if (isset($arUser['last_name']))
116 {
117 $arFields['LAST_NAME'] = $arUser['last_name'];
118 }
119
120 if (SITE_ID != '')
121 {
122 $arFields['SITE_ID'] = SITE_ID;
123 }
124
125 return $arFields;
126 }
127
128 public static function CheckUniqueKey($bUnset = true): bool
129 {
130 $arState = array();
131
132 if (isset($_REQUEST['state']))
133 {
134 parse_str(html_entity_decode($_REQUEST['state']), $arState);
135
136 if (isset($arState['backurl']))
137 {
138 InitURLParam($arState['backurl']);
139 }
140 }
141
142 if (!isset($_REQUEST['check_key']) && isset($_REQUEST['backurl']))
143 {
144 InitURLParam($_REQUEST['backurl']);
145 }
146
147 $checkKey = '';
148 if (isset($_REQUEST['check_key']))
149 {
150 $checkKey = $_REQUEST['check_key'];
151 }
152 elseif (isset($arState['check_key']))
153 {
154 $checkKey = $arState['check_key'];
155 }
156
157 if ($_SESSION['UNIQUE_KEY'] !== '' && $checkKey !== '' && ($checkKey === $_SESSION['UNIQUE_KEY']))
158 {
159 if ($bUnset)
160 {
161 unset($_SESSION['UNIQUE_KEY']);
162 }
163
164 return true;
165 }
166 return false;
167 }
168
169 public function Authorize(): void
170 {
171 global $APPLICATION;
172 $APPLICATION->RestartBuffer();
173
174 $authError = SOCSERV_AUTHORISATION_ERROR;
175
176 if (
177 isset($_REQUEST['code']) && $_REQUEST['code'] <> ''
178 && self::CheckUniqueKey()
179 )
180 {
181 if (defined('BX24_HOST_NAME') && IsModuleInstalled('bitrix24'))
182 {
183 $redirect_uri = static::CONTROLLER_URL . '/redirect.php';
184 }
185 else
186 {
187 $redirect_uri = $this->getEntityOAuth()->GetRedirectURI();
188 }
189
190 $entityOAuth = $this->getEntityOAuth($_REQUEST['code']);
191 if ($entityOAuth->GetAccessToken($redirect_uri) !== false)
192 {
193 $arUser = $entityOAuth->getCurrentUser();
194 if (is_array($arUser) && isset($arUser["email"]))
195 {
196 $arFields = $this->prepareUser($arUser);
197 $authError = $this->AuthorizeUser($arFields);
198 }
199 }
200 }
201
202 $bSuccess = $authError === true;
203
204 $url = ($APPLICATION->GetCurDir() == "/login/") ? "" : $APPLICATION->GetCurDir();
205 $aRemove = array("logout", "auth_service_error", "auth_service_id", "code", "error_reason", "error", "error_description", "check_key", "current_fieldset");
206
207 if (isset($_REQUEST["state"]) && $bSuccess)
208 {
209 $arState = array();
210 parse_str(html_entity_decode($_REQUEST["state"]), $arState);
211
212 if (isset($arState['backurl']) || isset($arState['redirect_url']))
213 {
214 $url = !empty($arState['redirect_url']) ? $arState['redirect_url'] : $arState['backurl'];
215 if (substr($url, 0, 1) !== "#")
216 {
217 $parseUrl = parse_url($url);
218
219 $urlPath = $parseUrl["path"];
220 $arUrlQuery = explode('&', $parseUrl["query"]);
221
222 foreach ($arUrlQuery as $key => $value)
223 {
224 foreach ($aRemove as $param)
225 {
226 if (strpos($value, $param . "=") === 0)
227 {
228 unset($arUrlQuery[$key]);
229 break;
230 }
231 }
232 }
233
234 $url = (!empty($arUrlQuery)) ? $urlPath . '?' . implode("&", $arUrlQuery) : $urlPath;
235 }
236 }
237 }
238
239 if ($authError === SOCSERV_REGISTRATION_DENY)
240 {
241 $url = (preg_match("/\?/", $url)) ? $url . '&' : $url . '?';
242 $url .= 'auth_service_id=' . self::ID . '&auth_service_error=' . $authError;
243 }
244 elseif ($bSuccess !== true)
245 {
246 $url = (isset($urlPath)) ? $urlPath . '?auth_service_id=' . self::ID . '&auth_service_error=' . $authError : $GLOBALS['APPLICATION']->GetCurPageParam(('auth_service_id=' . self::ID . '&auth_service_error=' . $authError), $aRemove);
247 }
248
249 if (CModule::IncludeModule("socialnetwork") && strpos($url, "current_fieldset=") === false)
250 {
251 $url .= ((strpos($url, "?") === false) ? '?' : '&') . "current_fieldset=SOCSERV";
252 }
254 }
255
256 public function setUser($userId)
257 {
258 $this->getEntityOAuth()->setUser($userId);
259 }
260}
261
263{
264 const SERVICE_ID = "apple";
265
266 const AUTH_URL = 'https://appleid.apple.com/auth/authorize';
267 const TOKEN_URL = 'https://appleid.apple.com/auth/token';
268 private const PUBLIC_KEYS_URL = 'https://appleid.apple.com/auth/keys';
269
270 private const CLIENT_SECRET_EXPIRATION_TIME = 3600;
271 private const DECODE_ALGORITHM = 'RS256';
272 private const BITRIX_APP_BUNDLE_ID = 'com.bitrixsoft.cpmobile';
273
274 protected $userId = false;
275 protected $responseData = array();
276 protected $idToken;
277
278 protected $scope = [
279 'name', 'email'
280 ];
281
282 private $keyId;
283 private $teamId;
284 private $secretKey;
285
286 public function __construct($appID = false, $appSecret = false, $code = false)
287 {
288 if ($appID === false)
289 {
290 $appID = trim(\CSocServAuth::GetOption("apple_client_id"));
291 }
292
293 $this->keyId = trim(\CSocServAuth::GetOption('apple_key_id'));
294 $this->teamId = trim(\CSocServAuth::GetOption('apple_team_id'));
295 $this->secretKey = trim(\CSocServAuth::GetOption('apple_key_pem'));
296
297 parent::__construct($appID, $appSecret, $code);
298 }
299
300 public function GetRedirectURI(): string
301 {
302 return \CHTTP::URN2URI('/bitrix/tools/oauth/apple.php');
303 }
304
305 public function GetAuthUrl($redirect_uri, $state = ''): string
306 {
307 return self::AUTH_URL .
308 '?client_id=' . $this->appID .
309 '&redirect_uri=' . urlencode($redirect_uri) .
310 '&response_type=' . 'code' .
311 '&scope=' . $this->getScopeEncode() .
312 '&response_mode=' . 'form_post' .
313 ($state <> '' ? '&state=' . urlencode($state) : '');
314 }
315
316 public function getResult()
317 {
318 return $this->responseData;
319 }
320
321 public function GetAccessToken($redirect_uri = ''): bool
322 {
323 $token = $this->getStorageTokens();
324 if (is_array($token))
325 {
326 $this->access_token = $token['OATOKEN'];
327 $this->accessTokenExpires = $token['OATOKEN_EXPIRES'];
328
329 if (!$this->code)
330 {
331 if ($this->checkAccessToken())
332 {
333 return true;
334 }
335
336 if (isset($token['REFRESH_TOKEN']) && $this->getNewAccessToken($token['REFRESH_TOKEN'], $this->userId, true))
337 {
338 return true;
339 }
340 }
341
342 $this->deleteStorageTokens();
343 }
344
345 if ($this->code === false)
346 {
347 return false;
348 }
349
350 //case for sign in from Bitrix24 application on iOS device
351 $request = \Bitrix\Main\Context::getCurrent()->getRequest();
352 $requestData = $request->toArray();
353 if (
354 $requestData['service'] === self::SERVICE_ID
355 && (
356 $requestData['platform'] === 'ios'
357 || (empty($requestData['platform']) && mb_strpos($request->getUserAgent(), 'Darwin') !== false)
358 )
359 )
360 {
361 $this->appID = self::BITRIX_APP_BUNDLE_ID;
362 }
363
364 $query = [
365 'code' => $this->code,
366 'grant_type' => 'authorization_code',
367 'client_secret' => $this->getClientSecret(),
368 'client_id' => $this->appID,
369 'redirect_uri' => $redirect_uri,
370 ];
371
372 $httpClient = new HttpClient([
373 'socketTimeout' => $this->httpTimeout,
374 'streamTimeout' => $this->httpTimeout,
375 ]);
376
377 $result = $httpClient->post(self::TOKEN_URL, $query);
378 try
379 {
381 }
382 catch (\Bitrix\Main\ArgumentException $e)
383 {
384 $result = [];
385 }
386
387 if ((isset($result['access_token']) && $result['access_token'] <> ''))
388 {
389 $this->access_token = $result['access_token'];
390 $this->accessTokenExpires = time() + $result['expires_in'];
391 $this->refresh_token = $result['refresh_token'];
392 $this->idToken = $result['id_token'];
393
394 $_SESSION["OAUTH_DATA"] = [
395 "OATOKEN" => $this->access_token,
396 "OATOKEN_EXPIRES" => $this->accessTokenExpires,
397 "REFRESH_TOKEN" => $this->refresh_token,
398 "ID_TOKEN" => $this->idToken
399 ];
400 return true;
401 }
402
403 return false;
404 }
405
406 public function getNewAccessToken($refreshToken = false, $userId = 0, $save = false): bool
407 {
408 if (!$this->appID || !$this->appSecret)
409 {
410 return false;
411 }
412
413 if (!$refreshToken)
414 {
415 $refreshToken = $this->refresh_token;
416 }
417
418 $http = new HttpClient(array(
419 'socketTimeout' => $this->httpTimeout,
420 'streamTimeout' => $this->httpTimeout,
421 ));
422
423 $result = $http->post(static::TOKEN_URL, array(
424 'refresh_token' => $refreshToken,
425 'client_id' => $this->appID,
426 'client_secret' => $this->getClientSecret(),
427 'grant_type' => 'authorization_code',
428 ));
429
430 try
431 {
432 $arResult = Json::decode($result);
433 }
434 catch (\Bitrix\Main\ArgumentException $e)
435 {
436 $arResult = array();
437 }
438
439 if (!empty($arResult['access_token']))
440 {
441 $this->access_token = $arResult['access_token'];
442 $this->accessTokenExpires = $arResult['expires_in'] + time();
443 if ($save && (int)$userId > 0)
444 {
445 $dbSocservUser = \Bitrix\Socialservices\UserTable::getList(array(
446 'filter' => array(
447 '=EXTERNAL_AUTH_ID' => static::SERVICE_ID,
448 '=USER_ID' => $userId,
449 ),
450 'select' => array('ID')
451 ));
452 if ($arOauth = $dbSocservUser->fetch())
453 {
454 \Bitrix\Socialservices\UserTable::update($arOauth['ID'], array(
455 'OATOKEN' => $this->access_token,
456 'OATOKEN_EXPIRES' => $this->accessTokenExpires)
457 );
458 }
459 }
460
461 return true;
462 }
463
464 return false;
465 }
466
467 public function getCurrentUser()
468 {
469 if ($this->access_token === false || $this->idToken === false)
470 {
471 return false;
472 }
473
474 try
475 {
476 $user = $this->decodeIdentityToken($this->idToken);
477 }
478 catch (Exception $exception)
479 {
480 return false;
481 }
482
483 $user = (array)$user;
484
485 if (!empty($user['sub']) && isset($_REQUEST['user']))
486 {
487 $userData = json_decode($_REQUEST['user'], true);
488
489 if (!empty($userData))
490 {
491 $user['first_name'] = $userData['name']['firstName'];
492 $user['last_name'] = $userData['name']['lastName'];
493 }
494 }
495
496 return $user;
497 }
498
499 public function GetAppInfo(): array
500 {
501 $app = [
502 'id' => self::BITRIX_APP_BUNDLE_ID
503 ];
504
505 return $app;
506 }
507
508 public function getScopeEncode(): string
509 {
510 return implode(' ', array_map('urlencode', array_unique($this->getScope())));
511 }
512
513 private function getClientSecret(): string
514 {
515 return $this->generateSignedJWT($this->keyId, $this->teamId, $this->appID, $this->secretKey);
516 }
517
518 private function generateSignedJWT(string $keyId, string $teamId, string $clientId, string $secretKey)
519 {
520 $header = [
521 'alg' => 'ES256',
522 'kid' => $keyId
523 ];
524 $body = array(
525 'iss' => $teamId,
526 'iat' => time(),
527 'exp' => time() + self::CLIENT_SECRET_EXPIRATION_TIME,
528 'aud' => 'https://appleid.apple.com',
529 'sub' => $clientId
530 );
531
532 $privateKey = openssl_pkey_get_private($secretKey);
533 if (!$privateKey)
534 {
535 return false;
536 }
537
538 $payload = JWT::urlsafeB64Encode(json_encode($header)) . '.' . JWT::urlsafeB64Encode(json_encode($body));
539 $signature = '';
540 $signResult = openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
541 if (!$signResult)
542 {
543 return false;
544 }
545
546 $rawSignature = self::convertDERSignature($signature, 64);
547
548 return $payload . '.' . JWT::urlsafeB64Encode($rawSignature);
549 }
550
551 private static function convertDERSignature(string $der, int $partLength): string
552 {
553 $hex = unpack('H*', $der)[1];
554 if ('30' !== substr($hex, 0, 2))
555 { // SEQUENCE
556 throw new \RuntimeException();
557 }
558 if ('81' === substr($hex, 2, 2))
559 { // LENGTH > 128
560 $hex = substr($hex, 6);
561 }
562 else
563 {
564 $hex = substr($hex, 4);
565 }
566 if ('02' !== substr($hex, 0, 2))
567 { // INTEGER
568 throw new \RuntimeException();
569 }
570 $Rl = hexdec(substr($hex, 2, 2));
571 $R = self::retrievePositiveInteger(substr($hex, 4, $Rl * 2));
572 $R = str_pad($R, $partLength, '0', STR_PAD_LEFT);
573 $hex = substr($hex, 4 + $Rl * 2);
574 if ('02' !== substr($hex, 0, 2))
575 { // INTEGER
576 throw new \RuntimeException();
577 }
578 $Sl = hexdec(substr($hex, 2, 2));
579 $S = self::retrievePositiveInteger(substr($hex, 4, $Sl * 2));
580 $S = str_pad($S, $partLength, '0', STR_PAD_LEFT);
581
582 return pack('H*', $R . $S);
583 }
584
590 private static function retrievePositiveInteger(string $data): string
591 {
592 while ('00' === substr($data, 0, 2) && substr($data, 2, 2) > '7f')
593 {
594 $data = substr($data, 2);
595 }
596 return $data;
597 }
598
599 private function fetchPublicKey()
600 {
601 $publicKeyDetails = [];
602
603 $http = new HttpClient([
604 'socketTimeout' => $this->httpTimeout,
605 'streamTimeout' => $this->httpTimeout,
606 ]);
607 $publicKeys = $http->get(self::PUBLIC_KEYS_URL);
608
609 try
610 {
611 $decodedPublicKeys = json_decode($publicKeys, true);
612 }
613 catch (Exception $e)
614 {
615 return false;
616 }
617
618 if (!isset($decodedPublicKeys['keys']) || count($decodedPublicKeys['keys']) < 1)
619 {
620 return false;
621 }
622
623 $parsedPublicKeys = JWK::parseKeySet($decodedPublicKeys['keys']);
624
625 foreach ($parsedPublicKeys as $keyId => $publicKey)
626 {
627 $details = openssl_pkey_get_details($publicKey);
628 $publicKeyDetails[$keyId] = $details['key'];
629 }
630
631 return $publicKeyDetails;
632 }
633
634 private function decodeIdentityToken(string $identityToken)
635 {
636 $payload = '';
637
638 $publicKeys = $this->fetchPublicKey();
639 if (is_array($publicKeys))
640 {
641 $payload = JWT::decode($identityToken, $publicKeys, [self::DECODE_ALGORITHM]);
642 }
643
644 return $payload;
645 }
646
647}
$arParams
Определения access_dialog.php:21
global $APPLICATION
Определения include.php:80
$arResult
Определения generate_coupon.php:16
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
Определения catalog_reindex.php:36
static getInstance()
Определения urlmanager.php:28
Определения jwk.php:18
Определения jwt.php:23
Определения json.php:9
static decode($data)
Определения json.php:50
Определения apple.php:263
__construct($appID=false, $appSecret=false, $code=false)
Определения apple.php:286
getNewAccessToken($refreshToken=false, $userId=0, $save=false)
Определения apple.php:406
const TOKEN_URL
Определения apple.php:267
$scope
Определения apple.php:278
const AUTH_URL
Определения apple.php:266
getScopeEncode()
Определения apple.php:508
GetRedirectURI()
Определения apple.php:300
GetAuthUrl($redirect_uri, $state='')
Определения apple.php:305
const SERVICE_ID
Определения apple.php:264
$userId
Определения apple.php:274
GetAppInfo()
Определения apple.php:499
$responseData
Определения apple.php:275
GetAccessToken($redirect_uri='')
Определения apple.php:321
getResult()
Определения apple.php:316
$idToken
Определения apple.php:276
getCurrentUser()
Определения apple.php:467
Определения apple.php:12
const ID
Определения apple.php:13
static CheckUniqueKey($bUnset=true)
Определения apple.php:128
Authorize()
Определения apple.php:169
GetSettings()
Определения apple.php:19
$entityOAuth
Определения apple.php:17
prepareUser($arUser)
Определения apple.php:98
addScope($scope)
Определения apple.php:93
getEntityOAuth($code=false)
Определения apple.php:36
getUrl($arParams)
Определения apple.php:70
setUser($userId)
Определения apple.php:256
const LOGIN_PREFIX
Определения apple.php:14
GetFormHtml($arParams)
Определения apple.php:51
GetOnClickJs($arParams)
Определения apple.php:62
Определения authmanager.php:985
AuthorizeUser($socservUserFields, $bSave=false)
Определения authmanager.php:1395
static GetOption($opt)
Определения authmanager.php:1339
$userId
Определения authmanager.php:991
getStorageTokens()
Определения oauthtransport.php:116
addScope($scope)
Определения oauthtransport.php:82
deleteStorageTokens()
Определения oauthtransport.php:134
$accessTokenExpires
Определения oauthtransport.php:10
checkAccessToken()
Определения oauthtransport.php:153
$arFields
Определения dblapprove.php:5
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$_REQUEST["admin_mnu_menu_id"]
Определения get_menu.php:8
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$save
Определения iblock_catalog_edit.php:365
$app
Определения proxy.php:8
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$backurl
Определения mail_auth.php:15
InitURLParam($url=false)
Определения tools.php:4443
IsModuleInstalled($module_id)
Определения tools.php:5301
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
LocalRedirect($url, $skip_security_check=false, $status="302 Found")
Определения tools.php:4005
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$clientId
Определения seo_client.php:18
const SOCSERV_REGISTRATION_DENY
Определения include.php:4
const SOCSERV_AUTHORISATION_ERROR
Определения include.php:3
const SITE_ID
Определения sonet_set_content_view.php:12
$GLOBALS['_____370096793']
Определения update_client.php:1
$url
Определения iframe.php:7