В рамках одного из проектов команда PHP-разработки DD Planet столкнулась со сложностью в процессе интеграции с ЕСИА. Была необходимость получать данные по юридическим организациям, которые числятся за пользователем, в документации Госуслуг не было достоверного описания, и нам удалось найти неочевидное решение этой задачи.

Введение

Мы не будем описывать каждый шаг, который делали по документации, но расскажем о конкретном решении, которое нашли для получения данных по организациям пользователя.

В статье часто будет использоваться фраза «формировать запрос» — под ней мы понимаем формирование URL, по которому необходимо переадресовать пользователя. В этом URL зашифрованы все данные для ЕСИА, по которым она определяет, что это за запрос. 

Также много внимания уделим составу scope. Scope — это область доступа, т. е. запрашиваемые права. Подробнее о формировании запросов можно прочесть в документации в пунктах B.2.1, B.2.2, B.2.3, B.2.4.

Задача и поиск решения

В рамках задачи нужно было авторизовать пользователя через Госуслуги и сразу же получить информацию по всем его организациям: ИНН, короткое название и полное название.

Авторизовать пользователя через ЕСИА не составило труда, но вот с получением информации о его организациях вышла совсем другая история.

Неочевидным был момент о том, что сначала мы должны получить данные только о пользователе и максимум — список ID его организаций, а затем делать отдельный запрос на каждую организацию.

Изначально мы пытались получить данные по пользователю и его организациям в одном запросе, указав все поля в scope, но это не работало. Как же получить данные по организациям? 

С этим вопросом мы обратились к интернету и не нашли ничего, кроме одиноких топиков на форумах, так и оставшихся без ответа. Только в одном был комментарий, говорящий, что нельзя получить поля организации вместе с полями пользователя в одном запросе.

Значит ли это, что на получение данных об организации нужно формировать отдельный запрос? Короткий ответ: да.

Описание решения

В документации в разделе B.3.2 и B.4 указаны параметры, которые необходимо запрашивать для получения информации о пользователе и организациях, среди них есть usr_org (список организаций пользователя).

Делаем запрос на авторизацию пользователя, запросив следующие поля:

$scope = ['openid', 'fullname', 'inn', 'email', 'usr_org'];
$scope = implode(', ', $scope);

И получаем в usr_org лишь параметр oid (внутренний ID организации ЕСИА). В следующем пункте документации видим поля, которые могут вернуться при запросе организации, и дальше лишь одно предложение о необычном формате запроса:

Пример scope:

scope=“http://esia.gosuslugi.ru/org_emps?org_oid=1000000357

Как оказалось позднее, для организаций scope с нужными полями должен выглядеть так:

$scope = [
	'openid', 
	'http://esia.gosuslugi.ru/org_inn?org_oid=' . $oid, 
	'http://esia.gosuslugi.ru/org_shortname?org_oid=' . $oid, 
	'http://esia.gosuslugi.ru/org_fullname?org_oid=' . $oid
];
$scope = implode(', ', $scope);

Где $oid — это уникальный ID организации в ЕСИА.

При таком запросе мы получаем ИНН организации, короткое название и полное название.

В одном запросе можно получить данные только об одной организации. Это значит, что нельзя передать в scope параметры с разными oid, это должен быть один oid для всех параметров организации.

Схема работы будет такая:

Шаг 1. Пользователь нажимает кнопку «Авторизоваться через госуслуги».

Шаг 2. Мы формируем заголовки и необходимые параметры для передачи запроса в ЕСИА, пользователя редиректит на необходимую страницу авторизации Госуслуг.

На этом моменте наш scope = [‘openid', 'fullname', 'inn', 'email', 'usr_org'];

Шаг 3. Пользователь вводит свои данные.

Шаг 4. ЕСИА авторизует его и возвращает на наш сервис данные о его авторизации (те поля, которые мы запросили в scope для пользователя [‘openid', 'fullname', 'inn', 'email', 'usr_org']).

Шаг 5. Мы смотрим, есть ли данные в usr_org. Если да, то формируем следующий запрос на получение каждой организации отдельно. Если у пользователя 10 организаций, то будет 10 разных запросов к ЕСИА.Теперь наш scope выглядит так:

$scope = [ 
	'openid', 
	'http://esia.gosuslugi.ru/org_inn?org_oid=' . $oid, 
	'http://esia.gosuslugi.ru/org_shortname?org_oid=' . $oid,
	'http://esia.gosuslugi.ru/org_fullname?org_oid=' . $oid
];
$scope = implode(', ', $scope);

Где $oid — это уникальный ID организации в ЕСИА (массив с этими параметрами пришел нам в usr_org с данными пользователя).Сформировав запрос, мы редиректим пользователя на другую страницу Госуслуг (каждый URL страницы Госуслуг формируется исходя из передаваемых данных, подробнее можно увидеть в документации).

Для пользователя этот переход выглядит так:

  • он видит страницу авторизации на Госуслугах, вводит свои данные;

  • затем его перекидывает на страницу Госуслуг, на которой задается вопрос «Вы уверены, что хотите предоставить сервису данные о своей организации?». Этот вопрос задается столько раз, сколько организаций есть у пользователя.

Шаг 6. На каждый вопрос «Вы уверены, что хотите предоставить сервису данные о своей организации?» пользователь должен нажать «Да», после чего ЕСИА передаёт на наш сервис информацию по запрошенной организации, а мы сохраняем ее.

Так как у пользователя может быть несколько организаций, после получения информации по одной из них, мы должны проверить, остались ли еще недополученные организации. Если да, то сформировать ссылку на страницу Госуслуг по разрешению доступа к следующей организации.

Итог

Мы реализовали сохранение данных по организациям через работу в сессиями. При получении данных о пользователе после его авторизации через Госуслуги сохраняем в переменную сессии, возвращенные ID организаций, и при получении данных по каждой из них удаляем ID полученной организации из массива, сохраненного в сессию. И только после того, как этот массив станет пустым (что означает, что мы получили все данные по всем организациям), перенаправляем пользователя на страницу его личного кабинета. А сами детальные данные по каждой организации сохраняем в базу данных.

Мы могли бы предоставить полный работающий код, но в статье описали именно решение сложности, с которой столкнулись. Судя по ответам на форумах, многие разработчики встречались с подобной проблемой. Надеемся, описание решения поможет другим быстро настроить автоматическое получение данных об организациях пользователей. 

Комментарии (1)


  1. a_nick
    26.01.2022 13:10
    +3

    Алена, документацию надо читать внимательней. По вашей же ссылке на документацию ЕСИА, раздел B.4 , стр. 201-203 даже с примерами.

    /rs/prns/{prn_oid}/roles - все организации с их данными одним запросом.