/*
* В GET есть state, значит это бэк урл из ЕСИА после авторизации... обрабатываем
*/
elseif($_GET['state']) {
$arResult = [
'TYPE' => 'ESIA',
'ERROR' => false,
];
try {
// Проверяем state запроса и ответа
if(!$_GET['state'] == $_SESSION['oauth2.esia.state'])
throw new Exception('Идентификатор запроса авторизации недействителен');
/*
* Обмениваем code на токен и получаем данные
*/
# Токен
$sAccessToken = $this->getEsiaUserTokenByCode($_GET['code'], $_GET['state']);
# Запрашиваем данные по пользователю в ЕСИА
$arEsiaUserData = $this->getEsiaUserData($sAccessToken);
// Проверяем
if($arEsiaUserData['citizenship'] != 'RUS')
throw new Exception('Только граждане РФ могут авторизоваться через ЕСИА');
if(!$arEsiaUserData['trusted'])
throw new Exception('Ваша учетная запись в ЕСИА не подтверждена, подтвердите учетную запись и попробуйте еще раз');
if(!$arEsiaUserData['inn'])
throw new Exception('Для использования сервиса в ЕСИА должна быть указана информация о ИНН');
# Собираем контакты
$arContacts = [];
foreach($arEsiaUserData['contacts']['elements'] AS $arRow) {
if($arRow['vrfStu'] != 'VERIFIED')
continue;
$sType = '';
switch($arRow['type']) {
case 'EML': $sType = 'EMAIL'; break;
case 'MBT': $sType = 'PERSONAL_MOBILE'; break;
case 'PHN': $sType = 'PERSONAL_PHONE'; break;
}
if(!$sType)
continue;
$arContacts[$sType] = $arRow['value'];
}
// Проверяем Email
if(!$arContacts['EMAIL'])
throw new Exception('Для авторизации в сервисе необходимо указать в ЕСИА информацию о Email адресе');
# Собираем адреса
$arAddresses = [];
foreach($arEsiaUserData['addresses']['elements'] AS $arRow) {
$sType = '';
switch($arRow['type']) {
case 'PRG': $sType = 'ADDR_REG'; break;
case 'PLV': $sType = 'ADDR_ACTUAL'; break;
}
if(!$sType)
continue;
$arAddresses[$sType] = join(', ', array_diff([
$arRow['zipCode'],
$arRow['addressStr'],
$arRow['house']? "д. {$arRow['house']}":'',
$arRow['frame']? "корп. {$arRow['frame']}":'',
$arRow['building']? "стр. {$arRow['building']}":'',
$arRow['flat'] ? "кв. {$arRow['flat']}":'',
], ['']));
}
# Собираем паспорт
$arPassport = [];
foreach($arEsiaUserData['documents']['elements'] AS $arDoc) {
if($arDoc['vrfStu'] != 'VERIFIED' || $arDoc['type'] != 'RF_PASSPORT')
continue;
$arPassport = [
'SERIES' => $arDoc['series'],
'NUMBER' => $arDoc['number'],
'ISSUE_DATE' => $arDoc['issueDate'],
'ISSUE_CODE' => $arDoc['issueId'],
'ISSUE_NAME' => $arDoc['issuedBy'],
];
break;
}
// Проверяем паспорт
if(!$arPassport)
throw new Exception('Для использования сервиса в ЕСИА должна быть указана информация о паспорте');
# Получаем данные по организациям
$arOrgsId = [];
// Формируем список OID
foreach($arEsiaUserData['organizations']['elements'] AS $arOrg) {
$arOrgsId[] = $arOrg['oid'];
}
// Запрашиваем данные
$arEsiaUserOrgData = $this->getEsiaUserOrganizations(
[
'code' => $_GET['code'],
'state' => $_GET['state'],
],
$arOrgsId
);
// Дополняем массив пользователя
$arEsiaUserData['CONTACTS_DATA'] = $arContacts;
$arEsiaUserData['ADDRESSES_DATA'] = $arAddresses;
$arEsiaUserData['PASSPORT_DATA'] = $arPassport;
// Сохраняем информацию в сессию для обработки при авторизации/регистрации
$_SESSION['ESIA'] = [
'TOKEN' => $sAccessToken,
'USER' => $arEsiaUserData,
'ORGS' => $arEsiaUserOrgData,
];
// Редиректим на страницу с выбором учетной записи
$sUrl = $this->makeUrl('esia', $this->arUrlTemplates['esia']);
$sUrl .= (strpos($sUrl, '?') !== false?'&':'?').'choice=Y';
LocalRedirect($sUrl);
} catch (Exception $e) {
$arResult['ERROR'] = $e->getMessage();
}
public function getEsiaUserOrganizations($arAccess, $arOrgsId, $arScope = null) {
$arScope = $arScope && is_array($arScope)? $arScope : $this->arDefaultOrgScopes;
if(!$arOrgsId || !is_array($arOrgsId))
return [];
# Если нет токена, то получаем его по code и state
if(!$arAccess['access_token']) {
if(!$arAccess['code'] || !$arAccess['state'])
throw new Exception('Не переданы данные для получения токена доступа к организациям');
$arTokenScopes = [];
foreach($arOrgsId AS $iId) {
foreach($arScope AS $sScope)
$arTokenScopes[] = "http://esia.gosuslugi.ru/{$sScope}?org_oid={$iId}";
}
$arAccess['access_token'] = $this->getEsiaCredentialsTokenByCode($arAccess['code'], $arAccess['state'], $arTokenScopes);
}
# Получаем данные по орг.
$arOrganization = [];
foreach($arOrgsId AS $iId) {
// Выполняем запрос
$obHttpClient = new Bitrix\Main\Web\HttpClient();
$obHttpClient->setHeader('Content-Type', 'application/json', true);
$obHttpClient->setHeader('User-Agent', 'PHP-HttpClient', true);
$obHttpClient->setHeader('Authorization', "Bearer {$arAccess['access_token']}", true);
$mResponse = $obHttpClient->get($this->getEsiaDomain() . "/rs/orgs/{$iId}");
$arResponse = json_decode($mResponse, true);
// Проверяем
if($obHttpClient->getStatus() != 200 || !$arResponse) {
$arOrganization[$iId] = ['code' => 'SYS-000000', 'message' => 'Request.incorrectResponseFormat'];
continue;
}
// TODO - при необходимости получения доп инфы можно тут сделать доп подзапрос или использовать embed режим
unset($arResponse['stateFacts']);
$arOrganization[$iId] = $arResponse;
}
return $arOrganization;
}
/**
* @var array Массив со списком scope запрашиваемых у пользователя
*/
protected $arDefaultUserScopes = [
'fullname',
'birthdate',
'snils',
'inn',
'id_doc',
'email',
'mobile',
'usr_org',
'contacts',
];
/**
* @var array Массив со списком scope запрашиваемых по организации
*/
protected $arDefaultOrgScopes = [
'org_shortname',
'org_fullname',
'org_type',
'org_inn',
'org_ogrn',
'org_leg',
'org_agencyterrange',
'org_agencytype',
'org_ctts',
];
В ЕСИА при авторизации под пользователем не предлагается выбор под кем это делается, перед тем как перекинуть обратно на бэк урл.