Skip to content

Пример использования API

В данном разделе представлен пример реализации интеграции на PHP


/**
 * Класс для работы с запросом с зашифрованными данными
 */
class CryptRequest
{
    /**
     * Путь до публичного ключа
     */
    private const PATH_TO_PUBLIC_KEY = '/path/to/public/key';

    /**
     * Данные для передачи в запросе
     *
     * @var ApplicationDto
     */
    private ApplicationDto $data;

    private PublicKey $rsaPublicKey;

    /**
     * Undocumented function
     *
     * @param string $aesKey Ключ симметричного шифрования
     * @param Encrypter $encrypter Экземпляр класса шифрования
     */
    public function __construct(
        private readonly string $aesKey,
        private readonly Encrypter $encrypter
    ) {
        $publicKey = file_get_contents(self::PATH_TO_PUBLIC_KEY);
        $this->rsaPublicKey = RSA::loadPublicKeyFormat('OpenSSH', $publicKey);
    }

    /**
     * Задать данные для отправки
     *
     * @param ApplicationDto $data
     * @return self
     */
    public function setData(ApplicationDto $data): self
    {
        $this->data = $data;
        return $this;
    }

    /**
     * Зашифровать данные симметричным ключом
     * Данные дополняются симметричным ключом, который шифруется
     * асимметричным ключом
     * Симметричный ключ кодируется в base64 после шифрования
     *
     * @return array<string, string>
     */
    private function getEncryptedData(): array
    {
        if (!isset($this->data)) {
            throw new \Exception('Нет данных для отправки');
        }

        $encryptedData = [];
        foreach ($this->data->toAssocArray() as $key => $value) {
            $encryptedData[$key] = $this->encrypter->encrypt($value);
        }

        $secret = $this->rsaPublicKey->encrypt($this->aesKey);
        $encryptedData['secret'] = base64_encode($secret);

        return $encryptedData;
    }

    /**
     * Отправка запроса по указанному адресу с зашифрованными данными
     *
     * @param string $url Адрес, куда отправляем запрос
     * @param string $bearerToken Токен авторизации
     * @return array<string, bool>
     */
    public function post(string $url, string $bearerToken): array
    {
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS => json_encode($this->getEncryptedData()),
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer {$bearerToken}",
                "Content-Type: application/json"
            ],
        ]);

        $response = curl_exec($curl);
        $error = curl_error($curl);
        curl_close($curl);

        return [$response, $error];
    }
}

/**
 * Класс для авторизации
 */
class Auth
{
    /**
     * @param string Адрес для авторизации без конечного назначения (БЕЗ /login /logout /refresh)
     */
    public function __construct(
        private readonly string $url
    ) {
    }

    /**
     * Авторизоваться. Получить токен для взаимодействия с сервисом по API
     *
     * @param string $login
     * @param string $password
     * @return array<string, bool>
     */
    public function login(string $login, string $password): array
    {
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL => $this->url . '/login',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS => json_encode([
                'login' => $login,
                'password' => $password,
            ]),
            CURLOPT_HTTPHEADER => [
                "Content-Type: application/json"
            ],
        ]);

        $response = curl_exec($curl);
        $error = curl_error($curl);
        curl_close($curl);

        return [$response, $error];
    }
}

/**
 * DTO класс данных для отправки запроса
 */
class ApplicationDto
{
    public string $file2;

    public function __construct(
        public string $name,
        public string $surname,
        public string $patronymic,
        public string $birthdate,
        public string $inn,
        public int $series,
        public int $number,
        public string $issueDate,
        public string $issuedWhom,
        public string $registrationAddress,
        public string $file1,
        public bool $consent
    ) {
    }

    public function toAssocArray(): array
    {
        $data = [
            'name' => $this->name,
            'surname' => $this->surname,
            'patronymic' => $this->patronymic,
            'birthdate' => $this->birthdate,
            'inn' => $this->inn,
            'series' => $this->series,
            'number' => $this->number,
            'issueDate' => $this->issueDate,
            'issuedWhom' => $this->issuedWhom,
            'registrationAddress' => $this->registrationAddress,
            'file1' => $this->file1,
            'consent' => $this->consent,
        ];

        if (isset($this->file2)) {
            $data['file2'] = $this->file2;
        }

        return $data;
    }
}

/**
 * ==================================
 * Порядок действий
 * ==================================
 */

// Авторизуемся, получаем токен для запросов
$auth = new Auth('https://domain_service/api/v1');
[$response, $error] = $auth->login('login', 'password');

if ($error) {
    throw new \Exception('Ошибка отправления запроса');
}

// Проверяем, получилось ли авторизоваться
// Если токена нет, значит авторизация не прошла
$response = (array) json_decode($response);
if (!isset($response['access_token'])) {
    die('Unauthorized');
}

$token = $response['access_token'];
* С токеном так же получаем:
* token_type - Тип токена
* expires_in - Время жизни токена, после он будет недействителен
*/
/**
/**
 * Указываем какой шифр будем использовать (доступен только aes-128-cbc)
 */
$cipher = 'aes-128-cbc';

/**
 * Указываем на какой адрес будет отправляться запрос
 */
$url = 'https://domain_service/api/v1/verification/data';

/**
 * Генерируем симметричный ключ по размеру указанного шифра
 */
$aesKey = Encrypter::generateKey($cipher);

/**
 * Создаём экземпляр класс шифрования
 */
$encrypter = new Encrypter($aesKey, $cipher);

/**
 * Создаём экземпляр класса запроса
 */
$cryptRequest = new CryptRequest($aesKey, $encrypter);

/**
 * Загрузим файл с изображением паспорта
 * Файлы должны быть закодированы в base64
 */
$passportFile = base64_encode(file_get_contents('/path/to/passport/file'));

/**
 * Создаём экземпляр данных запроса
 */
$application = new ApplicationDto(
    'Иван',
    'Петров',
    'Михайлович',
    '20.04.1984',
    '7707083893',
    1000,
    100000,
    '04.06.2009',
    'Московским УМВД №12',
    'Московская обл., р-н Митино, Село Новая Усадьба, ул. Пушкина, д. 21с1, к. 32',
    $passportFile,
    true,
);

/**
 * Если есть второе изображение пасспорта, то загружаем дополнительно
 */
$passportFile2 = base64_encode(file_get_contents('/path/to/passport/file/2'));
$application->file2 = $passportFile2;

/**
 * Задаём данные нашему запросу
 */
$cryptRequest->setData($application);

/**
 * Отправляем запрос
 */
[$response, $error] = $cryptRequest->post($url, $token);

if ($error) {
    throw new \Exception('Ошибка отправления запроса');
}

/**
 * В ответе находится следующая информация:
 * status - Статус выполнения запроса: успешно или с ошибкой
 * message - Описание статуса
 */
$response = (array) json_decode($response);

Примечания

  • Для данной реализации необходимо установить библиотеку: composer phpseclib/phpseclib