> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS SDK на Swift для верификации личности: мобильный KYC

> Didit: нативный iOS SDK на Swift для верификации личности, проверки живости и NFC-паспортов. $10 бесплатно в месяц, без контрактов.



Промпт для интеграции iOS SDK
        Скопировать промпт в буфер обмена



      
      

\<pre>

\`Integrate Didit identity verification into my iOS app using the native Swift SDK (DiditSDK 4.13.2).

\## Requirements
\- iOS 13.0+, Xcode 15.0+, Swift 5.9+
\- NFC chip reading requires iOS 15+ and a compatible device with NFC hardware
\- Since 4.0.0 the SDK ships in four variants; pick exactly one:
\- Core (DiditSDKCore): no NFC, no auto-detection, no OpenSSL, iOS 13.0+, smallest binary (manual capture only)
\- AutoDetection (DiditSDKAutoDetection): ML auto-capture, no NFC, no OpenSSL, iOS 13.0+
\- NFC (DiditSDKNFC): NFC passport reading, bundles OpenSSL 3.3.3, iOS 15.0+
\- All (DiditSDK — default): every feature, bundles OpenSSL 3.3.3, iOS 15.0+

\## Installation

\### Option A: Swift Package Manager (recommended)
1\. In Xcode: File > Add Package Dependencies
2\. Enter URL: https://github.com/didit-protocol/sdk-ios.git
3\. Select version 4.13.2 (or "Up to Next Major") and click Add Package
4\. Add exactly one library product for your variant:
\- All (NFC + auto-detection): product "DiditSDK"
\- Core (no NFC, no auto-detection): product "DiditSDKCore"
\- AutoDetection (auto-capture, no NFC): product "DiditSDKAutoDetection"
\- NFC (NFC, no auto-detection): product "DiditSDKNFC"

In Package.swift:
.package(url: "https://github.com/didit-protocol/sdk-ios.git", from: "4.13.2")
Then add one product, e.g. .product(name: "DiditSDK", package: "DiditSDK") or .product(name: "DiditSDKCore", package: "DiditSDK"). Your code always writes import DiditSDK regardless of variant.

\### Option B: CocoaPods (binary podspec — DiditSDK is not on the public Trunk)
podspec_url = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/DiditSDK.podspec'
\# Pick exactly one subspec:
\# All (NFC + auto-detection, iOS 15+):
platform :ios, '15.0'
pod 'DiditSDK/All', :podspec => podspec_url
\# Core (no NFC, no auto-detection, iOS 13+):        pod 'DiditSDK/Core', :podspec => podspec_url
\# AutoDetection (auto-capture, no NFC, iOS 13+):    pod 'DiditSDK/AutoDetection', :podspec => podspec_url
\# NFC (NFC, no auto-detection, iOS 15+):            pod 'DiditSDK/NFC', :podspec => podspec_url

Then run: pod install
Open the .xcworkspace (not .xcodeproj).

On Xcode 15+ if you hit rsync "Operation not permitted", set Build Setting ENABLE_USER_SCRIPT_SANDBOXING to No on the project (Debug and Release).

\## Required Permissions (Info.plist)
\- NSCameraUsageDescription (required) — Document scanning and face verification
\- NSMicrophoneUsageDescription (required) — Video recording for liveness checks
\- NSPhotoLibraryUsageDescription (required) — Upload documents from gallery
\- NFCReaderUsageDescription (only if using the NFC or All variant) — Read NFC chips in passports/IDs
\- NSLocationWhenInUseUsageDescription (optional) — Geolocation for fraud prevention

\## NFC Configuration (NFC or All variant only — skip for the Core or AutoDetection variants)
1\. Add "Near Field Communication Tag Reading" capability in Xcode > Signing & Capabilities
2\. Add ISO7816 identifiers to Info.plist:
com.apple.developer.nfc.readersession.iso7816.select-identifiers:
\["D23300000045737445494420763335", "A0000002471001", "A0000002472001", "00000000000000", "D392F000260100000001"]
(D392F000260100000001 is the Japan My Number Card's JPKI application: without it, iOS does not report that card to the SDK.)
3\. Add to entitlements file:
com.apple.developer.nfc.readersession.formats: ["TAG"]

\## Backend: Create Session (your server)
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "vendor_data": "user-id" }
Response: { "session_id": "uuid", "session_token": "short-token", "url": "https://verify.didit.me/session/short-token", "status": "Not Started" }
Send session_token to the iOS app (never expose DIDIT_API_KEY to the device).

\## SwiftUI Integration (recommended)
import SwiftUI
import DiditSDK

struct ContentView: View {
var body: some View {
    Button("Verify Identity") {
        // Option A: With session token from your backend (recommended)
        DiditSdk.shared.startVerification(token: "session-token-from-backend")

        // Option B: With workflow ID (SDK creates session internally — UniLink, vendorData only)
        // DiditSdk.shared.startVerification(workflowId: "your-workflow-id", vendorData: "user-id")
    }
    .diditVerification { result in
        switch result {
        case .completed(let session):
            // session.status: VerificationStatus = .approved | .pending | .declined
            if session.status == .approved { /* grant access */ }
        case .cancelled(let session):
            // User dismissed the flow; session may be nil if none was created
            \_ = session
        case .failed(let error, _):
            // VerificationError — show error.localizedDescription
            \_ = error
        }
    }
}
}

\## Programmatically dismissing the verification (3.6.0+)
Call DiditSdk.shared.dismiss() to end an active verification (e.g. on app backgrounding).
It dismisses the UI, resets state, and fires the .diditVerification handler with .cancelled(session:).
Do NOT toggle DiditSdk.shared.isPresented = false or call UIKit dismiss() on the topmost VC — that bypasses the completion pipeline.

\## Result Statuses (SDK enum / API string)
\- .approved / "Approved"  — user identity verified, grant access
\- .declined / "Declined"  — verification failed, show retry or contact support
\- .pending  / "In Review" — needs manual review by your compliance team

\## Full Verification Results
The SDK only returns the status. Full decision data (document fields, face match scores, AML hits, etc.) arrives via webhook to your backend.
Set up webhooks: https://docs.didit.me/integration/webhooks

\## Rate Limits (session creation)
\- 600 session-create requests / minute per x-api-key (see https://docs.didit.me/integration/rate-limiting)
\- On 429, retry honouring Retry-After / X-RateLimit-* headers

\## Environment Variables (backend only — never expose in the iOS app)
\- DIDIT_API_KEY — from Didit Console > API & Webhooks
\- DIDIT_WORKFLOW_ID — from Didit Console > Workflows

\## App Store Note
If you ship the NFC or All variant, Apple may request an NFC demo video during review. Request ours from [support@didit.me](mailto:support@didit.me).

\## Docs
\- iOS SDK: https://docs.didit.me/integration/native-sdks/ios-sdk
\- GitHub: https://github.com/didit-protocol/sdk-ios
\- Webhooks: https://docs.didit.me/integration/webhooks
\- API Reference: https://docs.didit.me/api-reference/overview`

\</pre>



      
      

Вставьте в

Легковесный iOS SDK для верификации личности, управляемый на стороне сервера, с минимальной настройкой. **Последняя версия: 4.13.2.**> [card] [Репозиторий на GitHub](https://github.com/didit-protocol/sdk-ios)
>
> Просмотреть исходный код, релизы и полный журнал изменений на GitHub> [!NOTE]
>
> ### **Нативный SDK**: Это рекомендуемый подход для приложений iOS. Нативные SDK обеспечивают лучший пользовательский опыт, оптимизированную работу с камерой и полную поддержку NFC.***## Требования| Требование | Минимальная версия |
| - | - |
| iOS | 13.0+ |
| Xcode | 15.0+ |
| Swift | 5.9+ |### Совместимость версий iOS| Версия iOS | Доступные функции |
| - | - |
| iOS 13.0 - 14.x | Все функции, **кроме** чтения паспортов через NFC |
| iOS 15.0+ | Все функции, включая чтение паспортов через NFC |> [!NOTE]
>
> **Для биометрического согласия нужен нативный SDK 4.10.0 или новее.** Для людей, на которых распространяются законы штатов Иллинойс, Техас или Колорадо, Didit может запросить явное [биометрическое согласие](https://docs.didit.me/ru/getting-started/biometric-consent.md) перед первым захватом лица. iOS SDK версии 4.10.0 и новее показывают этот шаг. Более ранние версии не могут его показать: их сессии проходят как прежде, а решение фиксирует, что согласие не получено (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Обновитесь, если вы проверяете людей в этих штатах.***## УстановкаНачиная с `4.0.0`, SDK поставляется в нескольких вариантах, чтобы ваше приложение добавляло в бинарный файл только те функции, которые использует. Выберите ровно один вариант: один subspec CocoaPods и один библиотечный продукт SwiftPM.| Вариант | CocoaPods | Продукт SwiftPM | NFC | Автоопределение | OpenSSL | Минимальная версия iOS |
| - | - | - | :-: | :-: | - | - |
| **Core** | `DiditSDK/Core` | `DiditSDKCore` | – | ✓ | нет | iOS 13.0+ |
| **AutoDetection** (устарел) | `DiditSDK/AutoDetection` | `DiditSDKAutoDetection` | – | ✓ | нет | iOS 13.0+ |
| **NFC** | `DiditSDK/NFC` | `DiditSDKNFC` | ✓ | ✓ | `3.3.3`, встроен | iOS 15.0+ |
| **All** (по умолчанию) | `DiditSDK/All` | `DiditSDK` | ✓ | ✓ | `3.3.3`, встроен | iOS 15.0+ |- **Core**: наименьший размер, с автоматическим захватом документа и селфи на собственных легковесных детекторах Didit. Без `OpenSSL.xcframework` и без среды выполнения CoreNFC.
- **AutoDetection**: устарел начиная с 4.11.0 и полностью идентичен **Core**. Используйте **Core**.
- **NFC**: **Core** плюс считывание чипов NFC в паспортах и eID.
- **All**: все функции. Это вариант по умолчанию, если вы устанавливаете `DiditSDK` без указания subspec или продукта.Что каждый вариант добавляет в бандл приложения (arm64 Mach-O, измерено для `4.9.0`): **Core** \~11.1 МБ, **NFC** \~11.7 МБ плюс \~4 МБ OpenSSL, **AutoDetection** \~16.0 МБ, **All** \~16.6 МБ плюс OpenSSL.
Модели детекции загружаются во время выполнения и кешируются, поэтому они никогда не учитываются в размере загрузки вашего приложения.Начиная с `4.11.0`, автоматический захват работает на собственных легковесных детекторах Didit во всех вариантах. TensorFlow Lite больше не входит в состав SDK, а фреймворк стал меньше, потому что его переводы загружаются извне бинарного файла.Начиная с `4.6.0`, поставляемые фреймворки больше не содержат дескрипторов Swift ABI (метаданных сборки, которые Xcode копирует в каждое приложение, но никогда не читает) и обучающих видео, которые вариант не может воспроизвести. При обновлении с `4.5.4` или более ранней версии приложение уменьшится примерно на 7-8 МБ без каких-либо изменений в коде.
App Store сжимает бинарные файлы при доставке, поэтому стоимость загрузки по воздуху ниже. Точную разницу для каждого устройства смотрите в отчёте о размере приложения в App Store Connect.> [!NOTE]
>
> Варианты **NFC** и **All** содержат `OpenSSL.xcframework` (**OpenSSL 3.3.3**, поставляется как `OpenSSL-Universal 3.3.3001` через `NFCPassportReader`), который необходим для аутентификации чипа NFC и требует iOS 15.0+. Релизы **до 4.0.6 включительно** содержали OpenSSL `1.1.1s`; **4.0.7 и более поздние** поставляются с OpenSSL 3.3.3, собственным манифестом конфиденциальности и подписью кода. Всегда устанавливайте **4.0.7 или более позднюю** версию. Обратите внимание: обновление выравнивает версии OpenSSL, но не устраняет конфликты при встраивании. Если другая зависимость вашего приложения тоже встраивает `OpenSSL.framework` (то же имя файла, тот же bundle id `com.github.krzyzanowskim.OpenSSL`), две копии конфликтуют на этапе встраивания независимо от версии. Оставьте ровно одну копию: например, переопределите другой пакет по идентификатору SPM, чтобы использовать опубликованный Didit `OpenSSL.xcframework`, и тогда в бандле будет именно тот бинарный файл, с которым собран этот SDK. Варианты **Core** и **AutoDetection** не подключают OpenSSL вообще.`import DiditSDK` в коде вашего приложения одинаков независимо от того, какой вариант вы установили.### Swift Package Manager (рекомендуется)Добавьте пакет в проект через Xcode:1) Откройте **File > Add Package Dependencies**
2) Введите URL репозитория:```
https://github.com/didit-protocol/sdk-ios.git
```3) Выберите версию (или **Up to Next Major** начиная с `4.13.2`) и нажмите **Add Package**
4) Когда появится запрос на выбор продукта, выберите ровно один библиотечный продукт для вашего варианта (см. таблицу выше)Или в вашем `Package.swift`:```swift theme={null}
dependencies: [
    .package(url: "https://github.com/didit-protocol/sdk-ios.git", from: "4.13.2")
]
```Затем добавьте в таргет ровно один из этих продуктов:```swift theme={null}
// All (default — NFC + auto-detection)
.product(name: "DiditSDK", package: "DiditSDK")

// Core (no NFC, no auto-detection, no OpenSSL)
.product(name: "DiditSDKCore", package: "DiditSDK")

// AutoDetection (auto-capture, no NFC)
.product(name: "DiditSDKAutoDetection", package: "DiditSDK")

// NFC (NFC passport reading, no auto-detection)
.product(name: "DiditSDKNFC", package: "DiditSDK")
```> [!WARNING]
>
> **Swift Package Manager не проверяет минимум iOS 15 за вас.** `Package.swift` объявляет `platforms: [.iOS(.v13)]` для всего пакета, поэтому Xcode без возражений позволит добавить `DiditSDK` или `DiditSDKNFC` в таргет iOS 13 или 14. Однако оба продукта содержат `OpenSSL.xcframework` и читают чипы через `NFCPassportReader`, что требует **iOS 15.0+**. При использовании продукта `All` или `NFC` установите deployment target таргета на 15.0 самостоятельно. CocoaPods делает это автоматически через `deployment_target` subspec.### CocoaPods`DiditSDK` распространяется как бинарный podspec, размещённый в репозитории (в публичном CocoaPods Trunk его нет), поэтому нужно указать URL podspec. Выберите ровно один subspec:```ruby theme={null}
podspec_url = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/DiditSDK.podspec'

# All (NFC + auto-detection, iOS 15.0+):
platform :ios, '15.0'
pod 'DiditSDK/All', :podspec => podspec_url

# Core (no NFC, no auto-detection, iOS 13.0+):
# pod 'DiditSDK/Core', :podspec => podspec_url

# AutoDetection (auto-capture, no NFC, iOS 13.0+):
# pod 'DiditSDK/AutoDetection', :podspec => podspec_url

# NFC (NFC passport reading, iOS 15.0+):
# pod 'DiditSDK/NFC', :podspec => podspec_url
````Core` и `AutoDetection` поддерживают iOS 13; `NFC` и `All` требуют iOS 15 из-за `NFCPassportReader`.Затем выполните:```bash theme={null}
pod install
```> [!NOTE]
>
> После `pod install` откройте сгенерированный `.xcworkspace`, а не `.xcodeproj`.> [!NOTE]
>
> **Ошибки rsync в Xcode 15+**: если во время сборки появляются ошибки rsync `Operation not permitted`, установите **Build Settings → User Script Sandboxing** (`ENABLE_USER_SCRIPT_SANDBOXING`) в значение **Нет** для проекта, и для Debug, и для Release.### Ручная установка (XCFramework)Каждый релиз публикует по одному XCFramework на каждый вариант. Скачайте архивы для вашего варианта со страницы [GitHub Releases](https://github.com/didit-protocol/sdk-ios/releases), затем перетащите папки `.xcframework` в Xcode и выставьте **Embed & Sign**.| Вариант | Файлы для загрузки |
| - | - |
| **Core** | `DiditSDK-Core.xcframework.zip` |
| **AutoDetection** | `DiditSDK-AutoDetection.xcframework.zip` |
| **NFC** | `DiditSDK-NFC.xcframework.zip` + `OpenSSL.xcframework.zip` |
| **All** | `DiditSDK.xcframework.zip` + `OpenSSL.xcframework.zip` |***## PermissionsДля работы SDK требуются следующие разрешения. Добавьте их в `Info.plist` вашего приложения:| Разрешение | Ключ Info.plist | Описание | Обязательно |
| - | - | - | - |
| Камера | `NSCameraUsageDescription` | Сканирование документов и проверка лица | ✅ Да |
| Микрофон | `NSMicrophoneUsageDescription` | Запись видео для проверки живости | ✅ Да |
| Медиатека | `NSPhotoLibraryUsageDescription` | Загрузка документов из галереи устройства | ✅ Да |
| NFC | `NFCReaderUsageDescription` | Считывание NFC-чипов в паспортах и ID-картах | ⚠️ Только полный SDK |
| Местоположение | `NSLocationWhenInUseUsageDescription` | Геолокация для предотвращения мошенничества | ❌ Необязательно |### Примеры записей Info.plist```xml theme={null}
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan your identity documents for verification.</string>

<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required to record video for liveness verification.</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to upload document images.</string>

<key>NFCReaderUsageDescription</key>
<string>NFC access is required to read the chip in your identity document.</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access helps verify your identity and prevent fraud.</string>
```### Настройка NFCТребуется только при установке варианта **NFC** или **All**. Пропустите этот раздел, если вы установили вариант **Core** или **AutoDetection**.Чтобы включить считывание NFC для паспортов и ID-карт с чипами:1) **Добавьте возможность NFC** в Xcode:
   * Выберите цель → **Signing & Capabilities** → **+ Capability** → **Near Field Communication Tag Reading**

2) **Добавьте идентификаторы ISO7816** в `Info.plist`:```xml theme={null}
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>D23300000045737445494420763335</string>
    <string>A0000002471001</string>
    <string>A0000002472001</string>
    <string>00000000000000</string>
    <string>D392F000260100000001</string>
</array>
````D392F000260100000001` позволяет SDK считывать карту My Number Card (Япония) через [JPKI](https://docs.didit.me/ru/core-technology/nfc-verification/overview.md#карта-my-number-в-японии-jpki): без него iOS не передает карту в SDK. Считывание карт My Number Card пока не включено в продакшн-среде, а этот идентификатор не влияет на другие документы, поэтому его можно добавить уже сейчас.3) **Добавьте права** (в файл `.entitlements`):```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```> [!WARNING]
>
> **Ограничение симулятора (варианты NFC и All)**: эти варианты подключают CoreNFC, и начиная с Xcode 12 библиотека `libnfshared.dylib` отсутствует в симуляторах. Обходное решение см. в [этой ветке Stack Overflow](https://stackoverflow.com/questions/63915728/xcode12-corenfc-simulator-library-not-loaded). Это **не** относится к варианту **Core** или **AutoDetection**. Тестируйте функции NFC только на физических устройствах.> [!NOTE]
>
> ### **Проверка в App Store (варианты NFC и All)**: если вы установили вариант **NFC** или **All**, Apple может запросить демонстрационное видео во время проверки, поскольку код, связанный с NFC, входит в бинарный файл SDK, даже если ваш сценарий не использует NFC. Запросите наше демонстрационное видео с NFC, чтобы отправить его в Apple, по адресу [support@didit.me](mailto:support@didit.me). Это не относится к варианту **Core** или **AutoDetection**.***## Быстрый старт### Интеграция SwiftUI```swift theme={null}
import SwiftUI
import DiditSDK

struct ContentView: View {
    var body: some View {
        Button("Verify Identity") {
            // Method 1: UniLink — no backend required
            DiditSdk.shared.startVerification(workflowId: "your-workflow-id")
            
            // Method 2: Backend Session — full parameter control
            // DiditSdk.shared.startVerification(token: "your-session-token")
        }
        .diditVerification { result in
            handleResult(result)
        }
    }
    
    private func handleResult(_ result: VerificationResult) {
        switch result {
        case .completed(let session):
            print("Completed: \(session.status)")
        case .cancelled(let session):
            print("Cancelled")
        case .failed(let error, _):
            print("Failed: \(error.localizedDescription)")
        }
    }
}
```### Интеграция UIKit```swift theme={null}
import UIKit
import DiditSDK

class VerificationViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Start verification when ready
        DiditSdk.shared.startVerification(token: "your-session-token")
    }
}
```***## Методы интеграцииSDK поддерживает два метода интеграции:### Метод 1: UniLink (самый простой)Бэкенд не требуется. SDK создает сессию напрямую, используя ваш ID сценария из [Didit Console](https://business.didit.me). Метод UniLink (`startVerification(workflowId:)`) поддерживает только `vendorData`; для любых других параметров сессии используйте Метод 2.> [!NOTE]
>
> Чтобы `vendorData` передавался в сессию через UniLink, включите опцию **Vendor Data** в [Didit Console](https://business.didit.me).```swift theme={null}
DiditSdk.shared.startVerification(
    workflowId: "your-workflow-id",
    vendorData: "user-123"
)
```### Метод 2: сессия на бэкенде (рекомендуется для продакшн-среды)Ваш бэкенд создает сессию через [Create Verification Session API](https://docs.didit.me/ru/sessions-api/create-session.md) (`POST /v3/session/`) с полной поддержкой параметров (`contact_details`, `expected_details`, `metadata`, `callback` и др.), затем передает `session_token` в SDK.```swift theme={null}
// Your backend creates a session and returns the token
let sessionToken = await yourBackend.createVerificationSession(userId: currentUser.id)

// Pass the token to the SDK
DiditSdk.shared.startVerification(token: sessionToken)
```Этот подход дает полный контроль над:- Связыванием сессий с вашими пользователями (`vendor_data`)
- Заданием контактных данных и ожидаемых данных для перекрестной проверки
- Заданием пользовательских метаданных
- Настройкой обратного вызова для каждой сессииЭти данные (контактные данные, ожидаемые данные, метаданные, обратный вызов) отправляются в [Create Verification Session API](https://docs.didit.me/ru/sessions-api/create-session.md).***## ConfigurationНастройте поведение SDK с помощью `DiditSdk.Configuration`:```swift theme={null}
let configuration = DiditSdk.Configuration(
    languageLocale: .spanish,      // Force Spanish language
    showLanguageSelector: true,    // Let the user change language
    fontFamily: "Avenir",          // Custom font (must be registered in your app)
    loggingEnabled: true,          // Enable debug logging
    showCloseButton: true,         // Show close (X) button on step screens
    showExitConfirmation: true,    // Show confirmation dialog when user taps close
    closeOnComplete: false         // Don't auto-dismiss on completion
)

DiditSdk.shared.startVerification(
    token: "your-session-token",
    configuration: configuration
)
```### Параметры конфигурации| Свойство | Тип | По умолчанию | Описание |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Локаль устройства | Принудительно выбрать определённый язык |
| `showLanguageSelector` | `Bool` | `false` | Показывать селектор языка в веб-стиле на приветственном экране |
| `fontFamily` | `String?` | Системный шрифт | Имя семейства пользовательского шрифта (шрифт должен быть зарегистрирован в вашем приложении через `UIAppFonts` в `Info.plist`) |
| `loggingEnabled` | `Bool` | `false` | Включить отладочное логирование SDK |
| `showCloseButton` | `Bool` | `true` | Показывать кнопку закрытия (X) на экранах шагов верификации |
| `showExitConfirmation` | `Bool` | `true` | Показывать диалог подтверждения, когда пользователь пытается выйти |
| `closeOnComplete` | `Bool` | `false` | Автоматически закрывать интерфейс верификации по завершении (аналог в Web SDK: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `.back` | Объектив, который используется при открытии экрана съёмки документа |
| `defaultLivenessCamera` | `CameraLens` | `.front` | Объектив, который используется при открытии экрана съёмки лица (проверка живости) |
| `showDocumentCameraSwitchButton` | `Bool` | `true` | Показывать переключатель камеры во время съёмки на экране документа |
| `showLivenessCameraSwitchButton` | `Bool` | `true` | Показывать переключатель камеры во время съёмки на экране съёмки лица |### Параметры камерыПараметры камеры совпадают с [параметрами камеры Web SDK](https://docs.didit.me/ru/integration/web-sdks/javascript-sdk.md#параметры-камеры).
Каждый объектив обозначается значением `.front` или `.back`.
Если на устройстве нет запрошенного объектива, SDK использует первую камеру, которая у него есть.
Переключатель камеры также скрыт на устройствах с одной камерой.
Установите параметр переключателя в `false`, чтобы зафиксировать пользователя на объективе по умолчанию для этого шага.```swift theme={null}
let configuration = DiditSdk.Configuration(
    defaultLivenessCamera: .back,
    showLivenessCameraSwitchButton: false
)
```> [!NOTE]
>
> **Оформление и цвета**: цвета, фоны и настройки вступительного экрана задаются в ваших [настройках White label](https://business.didit.me) в Didit Console, а не в конфигурации SDK. Так брендинг остаётся одинаковым на всех платформах.> [!NOTE]
>
> Параметры `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` и `closeOnComplete` совпадают с конфигурацией `DiditSdkConfiguration` в Web SDK. Параметры `languageLocale` и `fontFamily` есть только в мобильном SDK, потому что он отображает весь интерфейс верификации нативно (в отличие от Web SDK, который делегирует отображение размещённому фронтенду внутри iframe).***## Поддержка языковSDK поддерживает **54 языка**. Если язык не указан, SDK использует локаль устройства, а запасным вариантом служит английский.```swift theme={null}
// Use device locale (default)
let config = DiditSdk.Configuration()

// Force specific language
let config = DiditSdk.Configuration(languageLocale: .french)

// Let the user change language on the welcome screen
let config = DiditSdk.Configuration(showLanguageSelector: true)

// Detect device locale programmatically
let deviceLanguage = SupportedLanguage.fromDeviceLocale()
```**[Все поддерживаемые языки →](https://docs.didit.me/ru/integration/supported-languages.md)*****## Расширенные параметры сессииДля расширенных параметров сессии (`contact_details`, `expected_details`, `metadata`, `callback`) используйте метод **Backend Session**. Ваш бэкенд вызывает [API создания сессии верификации](https://docs.didit.me/ru/sessions-api/create-session.md) с полным набором параметров, а затем передаёт `session_token` в SDK.***## Обработка результатовПеречисление `VerificationResult` содержит результат верификации:### Варианты результата| Вариант | Описание |
| - | - |
| `.completed(session:)` | Процесс верификации завершён (результат смотрите в `session.status`) |
| `.cancelled(session:)` | Пользователь отменил процесс верификации |
| `.failed(error:session:)` | Во время верификации произошла ошибка |### Свойства SessionData| Свойство | Тип | Описание |
| - | - | - |
| `sessionId` | `String` | Уникальный идентификатор сессии |
| `status` | `VerificationStatus` | `.approved`, `.pending` или `.declined` |
| `country` | `String?` | Код страны (ISO 3166-1 alpha-3) |
| `documentType` | `String?` | Тип документа, использованный для верификации |### Типы ошибок| Ошибка | Описание |
| - | - |
| `.sessionExpired` | Срок действия сессии истёк |
| `.networkError` | Проблема с сетевым подключением |
| `.cameraAccessDenied` | Не предоставлено разрешение на доступ к камере |
| `.unknown(String)` | Другая ошибка с сообщением |### Потеря соединенияЕсли устройство теряет соединение во время верификации, SDK показывает поверх процесса экран «Нет подключения к интернету» вместо того, чтобы оставлять шаг в состоянии загрузки.
SDK продолжает проверять соединение в фоновом режиме и сам закрывает экран, как только Didit снова становится доступен. Пользователь продолжает с того шага, на котором находился.
На экране есть кнопки **Повторить попытку** и, если `showCloseButton` равен `true` (по умолчанию), **Выйти из верификации**.
Выход завершает верификацию с результатом `.failed(error: .networkError, session:)`, поэтому ваше приложение узнаёт, что пользователь ушёл из-за соединения.### Полный пример обработки результата```swift theme={null}
.diditVerification { result in
    switch result {
    case .completed(let session):
        switch session.status {
        case .approved:
            print("✅ Approved! Session: \(session.sessionId)")
            // User is verified - grant access
            
        case .pending:
            print("⏳ Under review. Session: \(session.sessionId)")
            // Show "verification in progress" UI
            
        case .declined:
            print("❌ Declined. Session: \(session.sessionId)")
            // Handle declined verification
        }
        
    case .cancelled(let session):
        if let session = session {
            print("🚫 Cancelled session: \(session.sessionId)")
        }
        // User chose to cancel - maybe show retry option
        
    case .failed(let error, let session):
        print("⚠️ Error: \(error.localizedDescription)")
        // Handle error - show retry or contact support
    }
}
```***## Программное закрытие верификации> [!NOTE]
>
> Доступно в DiditSDK **3.6.0+**.Приложение-хост может программно завершить активную верификацию с помощью `DiditSdk.shared.dismiss()`. Это рекомендуемый способ остановить верификацию, когда хосту нужно взять управление экраном, например при переходе приложения в фон.```swift theme={null}
DiditSdk.shared.dismiss()
````dismiss()` проходит обычный конвейер завершения SDK: он закрывает показанный интерфейс, сбрасывает внутреннее состояние и вызывает обработчик `.diditVerification` с `.cancelled(session:)`, содержащим текущий `sessionId`, если сессия была создана. Если верификация не активна, вызов ничего не делает.### Пример: закрытие при переходе приложения в фон```swift theme={null}
NotificationCenter.default.addObserver(
    forName: UIApplication.didEnterBackgroundNotification,
    object: nil,
    queue: .main
) { _ in
    DiditSdk.shared.dismiss()
}
```> [!WARNING]
>
> **Не** устанавливайте `DiditSdk.shared.isPresented = false` для закрытия: флаг запускает показ только по фронту нарастания, а установка значения `false` ничего не делает. Также не поддерживается вызов `dismiss(animated:)` из UIKit для контроллера верхнего уровня: он обходит конвейер завершения SDK, поэтому обработчик `.diditVerification` не будет вызван.***## Наблюдение за состоянием SDKМожно отслеживать состояние SDK для собственного интерфейса загрузки:```swift theme={null}
struct CustomView: View {
    @ObservedObject private var sdk = DiditSdk.shared
    
    var body: some View {
        VStack {
            switch sdk.state {
            case .idle:
                Text("Ready to verify")
            case .creatingSession:
                ProgressView("Creating session...")
            case .loading:
                ProgressView("Loading...")
            case .ready:
                Text("Verification in progress")
            case .error(let message):
                Text("Error: \(message)")
            }
        }
    }
}
```***## Сквозной пример (сессия на бэкенде → iOS SDK → результат)Этот подход готов к продакшну. Бэкенд создаёт сессию, iOS-приложение получает `session_token`, а SDK запускает процесс.### 1. Бэкенд: создание сессии```ts theme={null}
// Node.js / Express example. Run on your server. NEVER ship DIDIT_API_KEY to the device.
import express from "express";

const app = express();
app.use(express.json());

app.post("/api/verification/start", async (req, res) => {
  const response = await fetch("https://verification.didit.me/v3/session/", {
    method: "POST",
    headers: {
      "x-api-key": process.env.DIDIT_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: req.body.userId, // your stable user id
    }),
  });

  if (!response.ok) {
    return res.status(500).json({ error: `Didit ${response.status}` });
  }

  const { session_id, session_token } = await response.json();
  // Persist session_id <-> userId so you can match the webhook later.
  res.json({ session_id, session_token });
});
```### 2. iOS: обмен токеном и запуск SDK```swift theme={null}
import SwiftUI
import DiditSDK

struct VerifyButton: View {
    let userId: String
    @State private var error: String?

    var body: some View {
        Button("Verify Identity") {
            Task { await start() }
        }
        .diditVerification { result in
            switch result {
            case .completed(let session) where session.status == .approved:
                // Optimistically reflect success in the UI; rely on the webhook
                // delivered to your backend as the source of truth.
                break
            case .completed(let session):
                print("Terminal status: \(session.status.rawValue)")
            case .cancelled:
                print("User cancelled")
            case .failed(let err, _):
                error = err.localizedDescription
            }
        }
    }

    private func start() async {
        do {
            var req = URLRequest(url: URL(string: "https://your-backend.example.com/api/verification/start")!)
            req.httpMethod = "POST"
            req.setValue("application/json", forHTTPHeaderField: "Content-Type")
            req.httpBody = try JSONEncoder().encode(["userId": userId])

            let (data, _) = try await URLSession.shared.data(for: req)
            struct Payload: Decodable { let session_token: String }
            let payload = try JSONDecoder().decode(Payload.self, from: data)

            await MainActor.run {
                DiditSdk.shared.startVerification(token: payload.session_token)
            }
        } catch {
            self.error = error.localizedDescription
        }
    }
}
```### 3. Бэкенд: получение итогового решения через webhookРезультат SDK удобен для обратной связи в интерфейсе, но официальное решение приходит через webhook. Подробности о проверке HMAC см. в [руководстве по webhook](https://docs.didit.me/ru/integration/webhooks.md).```ts theme={null}
app.post("/api/webhooks/didit", express.raw({ type: "application/json" }), (req, res) => {
  // 1. Verify the X-Signature header (see Webhooks docs)
  // 2. Parse the body
  const event = JSON.parse(req.body.toString());
  if (event.webhook_type === "status.updated") {
    // event.session_id, event.status ("Approved" | "Declined" | "In Review" | ...)
    // Look up the user by session_id and update their verification state.
  }
  res.sendStatus(200);
});
```***## Полный пример на SwiftUI```swift theme={null}
import SwiftUI
import DiditSDK

struct HomeView: View {
    @State private var resultMessage: String?
    @State private var isVerified = false
    
    var body: some View {
        VStack(spacing: 24) {
            if isVerified {
                Image(systemName: "checkmark.circle.fill")
                    .font(.system(size: 64))
                    .foregroundColor(.green)
                Text("Identity Verified")
                    .font(.title2)
            } else {
                Button("Verify Identity") {
                    startVerification()
                }
                .font(.headline)
                .padding(.horizontal, 32)
                .padding(.vertical, 16)
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(12)
            }
            
            if let message = resultMessage {
                Text(message)
                    .foregroundColor(.secondary)
                    .multilineTextAlignment(.center)
                    .padding()
            }
        }
        .diditVerification { result in
            handleResult(result)
        }
    }
    
    private func startVerification() {
        let config = DiditSdk.Configuration(
            languageLocale: .english
        )
        
        // Method 1: UniLink — no backend required
        DiditSdk.shared.startVerification(
            workflowId: "your-workflow-id",
            vendorData: "user-123",
            configuration: config
        )
        
        // Method 2: Backend Session — full parameter control
        // DiditSdk.shared.startVerification(
        //     token: "your-session-token",
        //     configuration: config
        // )
    }
    
    private func handleResult(_ result: VerificationResult) {
        switch result {
        case .completed(let session):
            if session.status == .approved {
                isVerified = true
            }
            resultMessage = """
                Status: \(session.status.rawValue)
                Session: \(session.sessionId)
                Country: \(session.country ?? "N/A")
                Document: \(session.documentType ?? "N/A")
                """
                
        case .cancelled(let session):
            resultMessage = "Cancelled - Session: \(session?.sessionId ?? "unknown")"
            
        case .failed(let error, _):
            resultMessage = "Failed: \(error.localizedDescription)"
        }
    }
}
```***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.