myDSS SDK iOS
Термины и определения
Тип | Описание |
---|---|
DSSUser | Объект, содержащий всю необходимую информацию для выполнения действий от имени пользователя. Содержит, в том числе, информацию для доступа к экземпляру DSS (url, корневой сертификат и пр.), "вектор аутентификации" для подтверждения действий и пр. С точки зрения DSS данный объект является устройством, подключенным к учетной записи пользователя DSS |
DSSDevice | Объект, содержащий информацию об устройствах, подключенных к той же учетной записи, что и объект DSSUser. Данный объект не содержит "вектор аутентификации" и не может использоваться для подтверждения операций или выполнения других действий |
DSSOperation | Операция DSS, для которой требуется подтверждение/отклонение. Операция может содержать несколько документов. При подтверждении/отклонении операции все содержащиеся в ней документы будут подписаны/отклонены. Операция создается на сервере DSS |
DSSOperation.DSSDocument | Документ, входящий в операцию, либо обрабатываемый самостоятельно |
Document Description | "Сниппет" документа, сформированный сервером DSS на основе шаблона для сниппета и содержания документа |
Document Preview | Визуализированный в человеко-читаемую форму документ, сформированный сервером DSS на основе шаблона для визуализации и содержания документа |
Document RawPDF | "Сырое" содержание документа (например, текстового файла), преобразованное в формат PDF |
DSSCertificate | Сертификат, привязанный к ключу подписи в учетной записи на DSS |
Установка
Для работы с библиотекой необходимы
Xcode 11
и версии новее.
- Скачайте и распакуйте архив из репозитория
- Добавьте фреймворк
myDSSSDK.xcframework
в основной проект вProject Settins -> [Target Name] -> General
в секцииFrameworks, Libraries and Embedded Content
- Дополнительные файлы (
config.ini
иRndmBioViewControllerIPhone.xib
) добавьте в проект и прикрепите к приложению вProject Settins -> [Target Name] -> Build Phases
в секцииCopy Bundle Resources
.
Сертификаты
Для взаимодействия с серверами в ресурсы приложения нужно поместить сертификаты. Они должны лежать в директории root-certs
в формате PEM.
/root-certs
/dev // Директория для сертификатов для взаимодействия с тестовым сервером
cert_1.crt
cert_2.crt
...
cert_N.crt
/prod // Директория для сертификатов для взаимодействия с продакшн-сервером
cert_1.crt
cert_2.crt
...
cert_N.crt
Одновременно может быть использован только один сертификат. Он указывается при инициализации библиотеки:
myDSS.initialize(rootCertificateType: .development)
// или
myDSS.initialize(rootCertificateType: .production)
Инициализация
Инициализировать библиотеку нужно перед вызовом внутренних функций SDK. Можно выставить уровень логирования и указать тип корневого сертификата.
import UIKit
import myDSSSDK
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Установка уровня логирования и инициализация библиотеки
#if DEBUG
myDSS.setLogLevel([.debug, .keys])
myDSS.initialize(rootCertificateType: .development)
#else
myDSS.initialize(rootCertificateType: .production)
#endif
...
}
}
Структура
Основные классы для работы:
- DSSUsersManager: Создаёт и управляет учётными записями пользователя на устройстве
- DSSOperationsManager: Получает информацию и подписывает операции и документы
- DSSCertificatesManager: Управляет сертификатами пользователей
- DSSDevicesManager: Управляет устройствами, привязанными к учётной записи
- DSSPolicyManager: Получает информацию о сервере DSS
Начало работы
Перед тем, как начать подписывать документы и операции, нужно создать пользователя. Есть 3 способа это сделать:
- Создать онлайн с подтверждением
- Создать с использованием QR-кода
- Создать онлайн с привязкой к другому устройству
Создание пользователя онлайн с подтверждением
DSSUsersManager.createDSSUser(
serviceURL: serverURL, // Адрес сервера DSS
name: name, // Имя для сохранения учетной записи
pushNotificationsData: data, // Данные для отправки пуш-уведомлений
deviceName: deviceName, // Отображаемое дружественное имя устройства
externalId: externalId, // Внешний идентификатор
alias: alias, // Человекочитаемый идентификатор устройства
requirePassword: requirePwd // Требуется ли установка пароля
) { result in
// Обрабатываем результат
switch result {
case let .success(user): ... // Пользователь создан и сохранён в хранилище
case let .failure(error): ...
}
}
Пользователь создан и сохранён в хранилище, его статус — .installed
. Теперь нужно дождаться, когда его статус на сервере DSS сменится на .notVerified
. Чтобы проверить текущий статус:
DSSUsersManager.updateStatus(
user: user
) { result in
switch result {
case let .success(user): // Сведения о пользователе обновлены
if user.state == .notVerified { // Проверяем статус
...
}
case let .failure(error): ...
}
}
Как только статус пользователя станет .notVerified
, мы сможем его верифицировать:
DSSUsersManager.acceptAccountChanges(
user: user
) { result in
switch result {
case let .success(user): ... // Пользователь подтверждён
case let .failure(error): ...
}
}
При верификации может потребоваться QR-код. Это зависит от настроек политики сервера.
Теперь статус пользователя .active
, с ним можно работать дальше.
Создание с использованием QR-кода
DSSUsersManager.createDSSUserWithInitQR(
name: name, // Имя для сохранения учетной записи
pushNotificationsData: data, // Данные для отправки пуш-уведомлений
deviceName: deviceName, // Отображаемое дружественное имя устройства
externalId: externalId, // Внешний идентификатор
alias: alias, // Человекочитаемый идентификатор устройства
requirePassword: true // Требуется ли установка пароля
) { result in
switch result {
case let .success(user): ... // Пользователь создан и сохранён в хранилище
case let .failure(error): ...
}
}
При создании пользователя данным способом потребуется отсканировать QR-код, сгенерированый сервером. После создания статус пользователя — .active
, с ним можно работать дальше.
Создание пользователя онлайн с привязкой к другому устройству
Данный способ применяется, когда уже есть устройство с подтверждённым пользователем и нужно привязать новое устройство. Потребуется передать идентификатор данного пользователя на новое устройство.
Получить идентификатор можно у экземпляра пользователя:
// Идентификатор подтверждённого пользователя, к которому привязываем новое устройство
let uid = user.dssUserID
На новом устройстве вызываем метод:
DSSUsersManager.createDSSUserWithApproval(
serviceURL: serverURL, // Адрес сервера DSS
uid: uid, // Идентификатор пользователя, к которому привязываем устройство
name: name, // Имя для сохранения учетной записи
pushNotificationsData: data, // Данные для отправки пуш-уведомлений
deviceName: deviceName, // Отображаемое дружественное имя устройства
externalID: externalID, // Внешний идентификатор
alias: alias, // Человекочитаемый идентификатор устройства
requirePassword: true // Требуется ли установка пароля
) { result in
switch result {
case let .success(newUser): ... // Пользователь создан и сохранён в хранилище
case let .failure(error): ...
}
}
Мы создали нового пользователя, его статус — .approveRequired
, требуется подтверждение с основного устройства. На экране отобразится QR-код, который нужно отсканировать основным устройством.
На основном устройстве вызываем метод processAwaitingDevice
:
DSSDevicesManager.processAwaitingDevice(
user: user // Пользователь к которому привязываем устройство
) { result in
switch result {
case .success: ... // Новое устройство подтверждено/отклонено
case let .failure(error): ...
}
}
Далее, на новом устройстве проверяем статус:
DSSUsersManager.checkApprovalStatus(
user: newUser
) { result in
switch result {
case let .success(approvedUser): ... // Пользователь добавлен
case let .failure(error): ... // Пользователь отклонён/не обработан
}
}
Теперь новое устройство подтверждено, статус пользователя — .active
и с ним можно работать на новом устройстве.
Получение списка пользователей и устройств
Пользователи, установленные на устройстве
let users = DSSUsersManager.users
Связанные устройства (в том числе и ожидающие подтверждения)
DSSDevicesManager.listDevices(
user: user
) { result in
switch result {
case let .success(devices): ...
case let .failure(error): ...
}
}
Работа с операциями
Получение списка операций
DSSOperationsManager.getOperationsList(
user: user, // Пользователь, для которого проверяются операции
operationType: nil, // Фильтр операций по типу
operationID: nil // Фильтр по идентификатору
) { result in
switch result {
case let .success(operations): ... // Получен список операций
case let .failure(error): ...
}
}
Подтверждение операции
DSSOperationsManager.confirmOperation(
operation: operation, // Операция для подтверждения
user: user, // Пользователь, подтверждающий операцию
signMode: .online // Способ подтверждения. В данном случае — online
) { result in
switch result {
case let .success(approveRequest): ... // Операция подтверждена, вернули
case let .failure(error): ...
}
}
Работа с документами
Загрузка документов
DSSOperationsManager.uploadDocument(
documentContent: documentData, // Бинарные данные документа
title: documentTitle, // Заголовок документа
snippetTemplate: documentSnippet, // HTML-сниппет документа
previewTemplate: documentPreview, // HTML-превью документа
user: user // Пользователь-владелец документа
) { result in
switch result {
case let .success(documentID): // Вернётся идентификатор документа
case let .failure(error): ...
}
}
Подпись документов
DSSOperationsManager.signDocuments(
documentsIDs: confirmedDocuments, // Документы для подписания
user: user, // Пользователь, подписывающий документы
signParams: signParams // Параметры подписанияы
) { result in
switch result {
case let .success(signingResults): // Вернутся результаты подписания
case let .failure(error): ...
}
}
Дополнительная информация
Параметры подписания
Для параметров подписания нужно получить параметры сервера подписания и идентификатор сертификата:
// Получаем параметры сервера подписания
DSSPolicyManager.getDSSSignServerParams(
user: user // Пользователь, запрашивающий параметры сервера подписания
) { result in
switch result {
case let .success(signServerParams): ... // Вернутся параметры сервера подписания
case let .failure(error): ...
}
}
...
// Получаем сертификат
DSSCertificatesManager.listCertificates(
user: user // Пользователь, запрашивающий сертификаты
) { result in
switch result {
case let .success(certificates): ... // Вернутся сертификаты и запросы на сертификаты
case let .failure(error): ...
}
}
...
// Выбираем сертификат, например, первый в списке. Запросы на сертификат игнорируем
let certificate: DSSCertificate = certificates.first(where: {
$0.type == .certificate
})
...
// Формируем параметры подписания
let processingTemplateId = signServerParams.processingTemplates.first.id
let certificateId = certificate.dssCertificateId
let signParams = DSSSignParams(
signTemplateId: processingTemplateId,
certId: certificateId,
pinCode: "")
)
Создание запроса на сертификат
// Получаем параметры сервера подписания
DSSPolicyManager.getDSSSignServerParams(
user: user // Пользователь, запрашивающий параметры сервера подписания
) { result in
switch result {
case let .success(signServerParams): ... // Вернутся параметры сервера подписания
case let .failure(error): ...
}
}
...
// Подготавливаем параметры. Значения даны для примера
let policyId = signServerParams.caPolicies.first(where: { $0.caType == .DSSOutOfBandEnroll }).id
let templateId = policy.ekuTemplates.first?.value.first
let testDN = ["2.5.4.3": "Test"]
// Создаём запрос на сертификат
DSSCertificatesManager.createCertificate(
user: user, // Пользователь, создающий запрос на сертификат
dn: testDN, // Различительное имя субъекта
templateId: templateId, // Идентификатор шаблона сертификата
caId: policyId // Идентификатор обработчика УЦ
) { result in
switch result {
case let .success(certRequest): ... // Вернётся запрос на сертификат
case let .failure(error): ...
}
}
Проверка состояния сертификатов и запросов
DSSCertificatesManager.listCertificates(
user: user // Пользователь, запрашивающий информацию
) { result in
switch result {
case let .success(certificates): ... // Вернётся массив сертификатов и запросов
case let .failure(error): ...
}
}
// Отфильтруем выпущеные сертификаты
let activeCertificates = certificates.filter {
$0.type == .certificate && $0.dssCertificateId != nil
}
Персонализация UI
За внешний вид UI отвечает структура Appearance
. Она позволяет изменить внешний вид кнопок, фоновых элементов и изображений.
/// Статический класс для хранения данных об внешнем виде UI
struct Appearance {
/// Картинки в интерфейсе
var images: Images
/// Внешний вид фоновых элементов
var views: Views
/// Внешний вид кнопок
var buttons: Buttons
/// Внешний вид надписей
var labels: Labels
/// Внешний вид контроллеров навигации
var navigationControllers: NavigationControllers
}
Пример:
/// Изменяем только цвет основных кнопок
myDSS.appearance.buttons.primary.backgroundColor = .red
/// Изменяем весь стиль основных кнопок:
myDSS.appearance.buttons.primary =
ButtonAppearance(
titleFont: .systemFont(ofSize: 16, weight: .medium),
titleColor: .init(named: "button_primary_title"),
titleColorPressed: .init(named: "button_primary_title_pressed"),
titleColorDisabled: .init(named: "button_primary_title_disabled"),
backgroundColor: .init(named: "button_primary_bg"),
backgroundColorPressed: .init(named: "button_primary_bg_pressed"),
backgroundColorDisabled: .init(named: "button_primary_bg_disabled"),
cornerRadius: 25
)