> ## 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.

# حزمة React Native للتحقق من الهوية: التحقق عبر الجوال

> حزمة KYC من Didit لـ React Native وExpo مع TypeScript وNFC لجوازات السفر. من $0.33 لكل فحص كامل، و$10 مجاناً شهرياً، بلا عقود.



موجّه تكامل SDK لـ React Native
        نسخ الموجّه إلى الحافظة



      
      

\<pre>

\`Integrate Didit identity verification into my React Native app using the native SDK.

\## Requirements
\- React Native 0.76+ (New Architecture / TurboModules)
\- Node.js 20+, TypeScript 5+
\- iOS 13.0+ (NFC requires iOS 15+)
\- Android API 24+ (Android 7.0), Kotlin 1.9+, Java 17+
\- New Architecture (TurboModules) only - package is published as @didit-protocol/sdk-react-native v4.x (latest 4.13.2)

\## Installation

\### Expo (recommended)
npx expo install @didit-protocol/sdk-react-native

Add to app.json (NFC is enabled by default):
\{
"expo": {
"plugins": ["@didit-protocol/sdk-react-native"]
}
}

To opt out of NFC dependencies:
\{
"expo": {
"plugins": [["@didit-protocol/sdk-react-native", { "iosNfcEnabled": false, "androidNfcEnabled": false }]]
}
}

The config plugin automatically adds the Didit Maven repo (Android), the DiditSDK podspec (iOS),
and BouncyCastle packaging rules for Android. This SDK requires a development build — it does not work in Expo Go.
The plugin does not edit Info.plist: add the iOS permission keys and, for NFC, the ISO7816 select identifiers
(including D392F000260100000001 for the Japan My Number Card) under expo.ios.infoPlist in app.json.

\### React Native CLI
npm install @didit-protocol/sdk-react-native

iOS — add this block to ios/Podfile inside the app target (NFC-aware; pins to iOS 15 when NFC is on):
didit_sdk_ios_nfc_enabled = ENV.fetch('DIDIT_SDK_IOS_NFC_ENABLED', 'true').downcase != 'false'
didit_sdk_ios_pod = didit_sdk_ios_nfc_enabled ? 'DiditSDK' : 'DiditSDK/Core'
pod didit_sdk_ios_pod, :podspec => 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/DiditSDK.podspec'
The tag in that URL must equal diditNativeSdkVersions.ios in the package (4.13.2); do not use 'main', because the package requires that exact version and every pod install fails when the URL resolves to a different one.
Then: cd ios && bundle exec pod install

Android — add to settings.gradle (dependencyResolutionManagement.repositories):
maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
To disable NFC, add diditSdkAndroidNfcEnabled=false to android/gradle.properties.

\## 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 React Native app (never expose DIDIT_API_KEY to the device).

\## Integration
import { startVerification, VerificationStatus } from '@didit-protocol/sdk-react-native';

// Option A: With session token from your backend (recommended)
const result = await startVerification('session-token-from-backend');

// Option B: With workflow ID (SDK creates session internally)
const result = await startVerificationWithWorkflow('your-workflow-id', {
vendorData: 'user-123',
});

// Handle result
switch (result.type) {
case 'completed':
if (result.session.status === VerificationStatus.Approved) { /* grant access */ }
break;
case 'cancelled':
// User dismissed the verification flow
break;
case 'failed':
// SDK error — show result.error.message
break;
}

\## Result Statuses (VerificationStatus enum)
\- VerificationStatus.Approved — user identity verified, grant access
\- VerificationStatus.Declined — verification failed, show retry or contact support
\- VerificationStatus.Pending  — 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 app)
\- DIDIT_API_KEY — from Didit Console > API & Webhooks
\- DIDIT_WORKFLOW_ID — from Didit Console > Workflows

\## Docs
\- React Native SDK: https://docs.didit.me/integration/native-sdks/react-native-sdk
\- GitHub: https://github.com/didit-protocol/sdk-react-native
\- npm: https://www.npmjs.com/package/@didit-protocol/sdk-react-native
\- Webhooks: https://docs.didit.me/integration/webhooks
\- API Reference: https://docs.didit.me/api-reference/overview`

\</pre>



      
      

الصق في

SDK متعدد المنصات لـ React Native يغلّف حزمتي SDK الأصليتين لنظامي iOS وAndroid، ويوفر واجهة TypeScript موحدة للتحقق من الهوية.> [card] [مستودع GitHub](https://github.com/didit-protocol/sdk-react-native)
>
> اطّلع على الكود المصدري والأمثلة على GitHub> [card] [حزمة npm](https://www.npmjs.com/package/@didit-protocol/sdk-react-native)
>
> @didit-protocol/sdk-react-native> [!NOTE]
>
> ### **SDK الأصلي**: هذا هو النهج الموصى به لتطبيقات React Native وExpo. يغلّف حزمتي SDK الأصليتين لنظامي iOS وAndroid لتجربة مستخدم أفضل، ومعالجة محسّنة للكاميرا، ودعم كامل لـNFC.***## المتطلبات| المتطلب | الإصدار الأدنى |
| - | - |
| React Native | 0.76+ (البنية الجديدة / TurboModules) |
| Node.js | 20+ |
| TypeScript | 5+ |### متطلبات المنصة| المنصة | الإصدار الأدنى | ملاحظات |
| - | - | - |
| iOS | 13.0+ | قراءة جواز السفر عبر NFC تتطلب iOS 15.0+ |
| Android | API 24+ (7.0) | Kotlin 1.9+، Java 17+ |> [!NOTE]
>
> **تتطلب الموافقة البيومترية الإصدار 4.10.0 من SDK الأصلي أو إصدار أحدث.** بالنسبة للأشخاص الخاضعين لقوانين إلينوي أو تكساس أو كولورادو، يمكن لـ Didit أن تطلب [الموافقة البيومترية](https://docs.didit.me/ar/getting-started/biometric-consent.md) الصريحة قبل أول التقاط للوجه. تعرض إصدارات React Native SDK التي تثبّت حزمتي SDK الأصليتين لنظامَي iOS وAndroid على الإصدار 4.10.0 أو أحدث هذه الخطوة. الإصدارات الأقدم لا يمكنها عرض هذه الخطوة: تعمل جلساتها كما كانت من قبل، ويُبلغ القرار بأن الموافقة لم يتم جمعها (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). قم بالترقية إذا كنت تتحقق من هوية أشخاص في تلك الولايات.***## التثبيت### Expo (موصى به)```bash theme={null}
npx expo install @didit-protocol/sdk-react-native
```ثم أضِف إضافة الإعداد (config plugin) إلى `app.json` (أو `app.config.js`). يتم تفعيل NFC افتراضياً:```json theme={null}
{
  "expo": {
    "plugins": ["@didit-protocol/sdk-react-native"]
  }
}
```تقوم الإضافة تلقائياً بإعداد المنصتين:- **Android:** تضيف مستودع Didit Maven إلى Gradle، وتضبط خاصية Gradle ‏`diditSdkAndroidNfcEnabled`، وتطبّق قواعد تبعيات BouncyCastle والتغليف.
- **iOS:** تضيف ملف podspec الخاص بـ DiditSDK إلى Podfile (مثبَّتاً على iOS 15 عند تفعيل NFC).لا تعدّل الإضافة ملف `Info.plist`. أضِف [مفاتيح أذونات iOS](#ios)، وفي حال NFC أضِف أيضاً معرّفات أمر SELECT وفق ISO7816 ضمن `ios.infoPlist` في الملف نفسه. يتيح `D392F000260100000001` لـ SDK قراءة بطاقة My Number اليابانية عبر [JPKI](https://docs.didit.me/ar/core-technology/nfc-verification/overview.md#بطاقة-ماي-نمبر-اليابانية-jpki):```json theme={null}
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NFCReaderUsageDescription": "NFC is used to read passport chip data for identity verification.",
        "com.apple.developer.nfc.readersession.iso7816.select-identifiers": [
          "D23300000045737445494420763335",
          "A0000002471001",
          "A0000002472001",
          "00000000000000",
          "D392F000260100000001"
        ]
      }
    }
  }
}
```#### تعطيل تبعيات NFCلبناء التطبيق بدون دعم NFC (ملف ثنائي أصغر، ولا يتطلب إمكانات NFC)، مرّر خيارات الإضافة:```json theme={null}
{
  "expo": {
    "plugins": [
      [
        "@didit-protocol/sdk-react-native",
        { "iosNfcEnabled": false, "androidNfcEnabled": false }
      ]
    ]
  }
}
```عند تعطيل NFC، لا تحتاج إلى قدرة NFC في iOS، ولا إلى استحقاقات NFC، ولا إلى إعدادات التزويد المرتبطة بـ NFC.> [!WARNING]
>
> يستخدم SDK هذا وحدات أصلية (الكاميرا وNFC) غير متاحة في **Expo Go**. يجب استخدام [نسخة التطوير (development build)](https://docs.expo.dev/develop/development-builds/introduction/) أو تشغيل `npx expo prebuild` لإنشاء المشاريع الأصلية.### React Native CLI```bash theme={null}
npm install @didit-protocol/sdk-react-native
# or
yarn add @didit-protocol/sdk-react-native
```#### إعداد iOSأضِف pod الخاص بـ DiditSDK إلى `Podfile` (فهو غير موجود في CocoaPods trunk). يأخذ الكود أدناه بعين الاعتبار متغير البيئة `DIDIT_SDK_IOS_NFC_ENABLED` حتى تتمكن من تبديل النسخة الفرعية بدون NFC (`DiditSDK/Core`) وقت التثبيت:```ruby theme={null}
# In your ios/Podfile — at the top, before the target block:
didit_sdk_ios_nfc_enabled = ENV.fetch('DIDIT_SDK_IOS_NFC_ENABLED', 'true').downcase != 'false'

def max_ios_version(*versions)
  versions.map(&:to_s).max_by { |version| Gem::Version.new(version) }
end

platform :ios, didit_sdk_ios_nfc_enabled ? max_ios_version(min_ios_version_supported, '15.0') : min_ios_version_supported

# Inside your app target:
didit_sdk_ios_pod = didit_sdk_ios_nfc_enabled ? 'DiditSDK' : 'DiditSDK/Core'
pod didit_sdk_ios_pod, :podspec => 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/DiditSDK.podspec'
```> [!WARNING]
>
> يجب أن يطابق الوسم (tag) في رابط podspec القيمة `diditNativeSdkVersions.ios` في إصدار الحزمة المثبَّت.
> يثبّت React Native `4.13.2` إصدار iOS الأصلي `4.13.2` وإصدار Android الأصلي `4.13.2`. لا توجّه podspec إلى `main`: فالحزمة تعتمد على إصدار iOS الأصلي المحدد بدقة، لذلك بمجرد أن يتقدم `main` يرى CocoaPods متطلبين غير متوافقين لـ `DiditSDK` ويفشل كل `pod install`. تشتق إضافة إعداد Expo هذا الرابط لك تلقائياً، أما مسار React Native CLI المباشر فهو وحده ما يحتاج إلى كتابته يدوياً.ثم ثبّت الاعتماديات:```bash theme={null}
cd ios
bundle exec pod install
```لإعادة البناء بدون تبعيات NFC، نظّف CocoaPods وأعد التشغيل مع ضبط متغير البيئة:```bash theme={null}
cd ios
rm -rf Pods Podfile.lock
DIDIT_SDK_IOS_NFC_ENABLED=false bundle exec pod install
```#### إعداد Androidأضِف مستودع Didit Maven إلى `settings.gradle` على مستوى المشروع:```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```أضِف ما يلي إلى `android/app/build.gradle` الخاص بتطبيقك (داخل كتلة `android { ... }`) لحل تعارضات الفئات المكررة في BouncyCastle وتكرار `MANIFEST.MF` في OSGI التي قد تسببها التبعيات الانتقالية لـ DiditSDK:```groovy theme={null}
android {
    configurations.configureEach {
        exclude group: 'org.bouncycastle', module: 'bcprov-jdk15to18'
        exclude group: 'org.bouncycastle', module: 'bcutil-jdk15to18'
        exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15to18'
        exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
    }
    packaging {
        resources {
            pickFirsts += ['org/bouncycastle/**']
            excludes += 'META-INF/versions/9/OSGI-INF/MANIFEST.MF'
        }
    }
}
```لبناء التطبيق بدون تبعيات NFC في Android (يستخدم الحزمة `me.didit:didit-sdk-core` بدلاً من `me.didit:didit-sdk`)، أضِف هذا إلى `android/gradle.properties`:```properties theme={null}
diditSdkAndroidNfcEnabled=false
```احذف هذه الخاصية، أو اضبطها على `true`، لاستخدام Android SDK الكامل مع NFC.***## الأذونات### iOSأضف المفاتيح التالية إلى ملف `Info.plist` الخاص بتطبيقك. سيؤدي غياب مفاتيح الخصوصية المطلوبة في iOS إلى أن ينهي iOS التطبيق فور وصول SDK إلى هذا المورد المحمي.| الإذن | مفتاح Info.plist | الوصف | مطلوب |
| - | - | - | - |
| الكاميرا | `NSCameraUsageDescription` | مسح المستندات والتحقق من الوجه | نعم |
| الميكروفون | `NSMicrophoneUsageDescription` | تسجيل فيديو الكشف عن الحيوية | نعم |
| مكتبة الصور | `NSPhotoLibraryUsageDescription` | رفع صور المستندات | نعم |
| الموقع | `NSLocationWhenInUseUsageDescription` | الموقع الجغرافي لمنع الاحتيال | نعم |
| NFC | `NFCReaderUsageDescription` | قراءة شرائح NFC في جوازات السفر وبطاقات الهوية | في حال استخدام NFC |```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 is used to read passport chip data for identity verification.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access is used to detect your country for identity verification.</string>
```#### إعداد NFCلتفعيل قراءة NFC لجوازات السفر وبطاقات الهوية التي تحتوي على شرائح: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 اليابانية عبر [JPKI](https://docs.didit.me/ar/core-technology/nfc-verification/overview.md#بطاقة-ماي-نمبر-اليابانية-jpki). بدونه لا يُبلغ iOS SDK بوجود البطاقة. قراءة بطاقة My Number غير مفعّلة في الإنتاج بعد، ولا يؤثر المعرّف في المستندات الأخرى، لذا يمكنك إضافته الآن.3) **أضف ملف الاستحقاقات** مع تفعيل قراءة علامات NFC:```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```تأكد من أن ملف تعريف التوفير يتضمن إمكانية NFC Tag Reading. لا يحتاج إعداد NFC هذا إذا كان NFC معطّلاً.### Androidتُعلَن الأذونات التالية في ملف `AndroidManifest.xml` الخاص بـ SDK وتُدمج تلقائياً:| الإذن | الوصف | مطلوب |
| - | - | - |
| `INTERNET` | الوصول إلى الشبكة للتواصل مع واجهة API | نعم |
| `ACCESS_NETWORK_STATE` | رصد توفر الشبكة | نعم |
| `CAMERA` | مسح المستندات والتحقق من الوجه | نعم |
| `NFC` | قراءة شرائح NFC في جوازات السفر وبطاقات الهوية | في حال استخدام NFC |تُعلَن ميزتا الكاميرا وNFC في الجهاز على أنهما اختياريتان (`android:required="false"`)، فيمكن تثبيت تطبيقك على أجهزة لا تتوفر فيها هذه الميزات.***## البدء السريع```tsx theme={null}
import { startVerification, VerificationStatus } from '@didit-protocol/sdk-react-native';

// Start verification with a session token from your backend
const result = await startVerification('your-session-token');

switch (result.type) {
  case 'completed':
    if (result.session.status === VerificationStatus.Approved) {
      console.log('Identity verified!');
    }
    break;
  case 'cancelled':
    console.log('User cancelled');
    break;
  case 'failed':
    console.log('Error:', result.error.message);
    break;
}
```***## طرق التكامليدعم SDK طريقتين للتكامل:### الطريقة 1: token الجلسة (موصى بها للإنتاج)أنشئ جلسة على الخادم الخاص بك باستخدام [واجهة Create Verification Session API](https://docs.didit.me/ar/sessions-api/create-session.md)، ثم مرّر token إلى SDK:```tsx theme={null}
import { startVerification } from '@didit-protocol/sdk-react-native';

// Your backend creates a session and returns the token
const sessionToken = await yourBackend.createVerificationSession(userId);

// Pass the token to the SDK
const result = await startVerification(sessionToken);
```يمنحك هذا الأسلوب تحكماً كاملاً في:- ربط الجلسات بالمستخدمين لديك (`vendor_data`)
- ضبط البيانات الوصفية المخصصة
- إعداد عمليات الاستدعاء الخاصة بكل جلسة### الطريقة 2: معرّف سير العمل (تكامل أبسط)للتكاملات الأبسط، يمكن لـ SDK إنشاء الجلسات مباشرةً باستخدام معرّف سير العمل الخاص بك:```tsx theme={null}
import { startVerificationWithWorkflow } from '@didit-protocol/sdk-react-native';

const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  contactDetails: { email: 'user@example.com' },
  config: { loggingEnabled: true },
});
```***## الإعداداتخصّص سلوك SDK بتمرير كائن `DiditConfig`:```tsx theme={null}
const result = await startVerification('your-session-token', {
  languageCode: 'es',           // Force Spanish language
  showLanguageSelector: true,   // Let the user change language
  fontFamily: 'Avenir',         // Custom font (must be registered natively)
  loggingEnabled: true,         // Enable debug logging
  showCloseButton: true,        // Show close (X) button on step screens
  showExitConfirmation: true,   // Confirm before exit
  closeOnComplete: false,       // Auto-dismiss UI on completion
});
```بالنسبة إلى `startVerificationWithWorkflow`، مرّر الإعدادات داخل `options.config`:```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  config: {
    languageCode: 'es',
    showLanguageSelector: true,
    loggingEnabled: true,
    showCloseButton: true,
    showExitConfirmation: true,
  },
});
```### خيارات الإعداد| الخاصية | النوع | الافتراضي | الوصف |
| - | - | - | - |
| `languageCode` | `string` | لغة الجهاز | رمز اللغة وفق ISO 639-1 (مثل `"en"` و`"fr"` و`"ar"`) |
| `showLanguageSelector` | `boolean` | `false` | عرض مُحدِّد اللغة بالأسلوب المعتمد على الويب في شاشة الترحيب |
| `fontFamily` | `string` | الخط الافتراضي للنظام | اسم عائلة خط مخصص (يجب تسجيله في النظام الأصلي) |
| `loggingEnabled` | `boolean` | `false` | تفعيل تسجيل التصحيح في SDK |
| `showCloseButton` | `boolean` | `true` | عرض زر الإغلاق (X) في شاشات خطوات التحقق |
| `showExitConfirmation` | `boolean` | `true` | عرض نافذة تأكيد عند محاولة المستخدم الخروج |
| `closeOnComplete` | `boolean` | `false` | إغلاق واجهة التحقق تلقائياً عند الاكتمال |
| `defaultDocumentCamera` | `CameraLens?` | الافتراضي الأصلي (`CameraLens.Back`) | العدسة المستخدمة عند فتح شاشة التقاط المستند |
| `defaultLivenessCamera` | `CameraLens?` | الافتراضي الأصلي (`CameraLens.Front`) | العدسة المستخدمة عند فتح شاشة التقاط الوجه (الكشف عن الحيوية) |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | عرض زر تبديل الكاميرا أثناء الالتقاط في شاشة التقاط المستند |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | عرض زر تبديل الكاميرا أثناء الالتقاط في شاشة التقاط الوجه |### خيارات الكاميراتتوافق خيارات الكاميرا مع [خيارات كاميرا Web SDK](https://docs.didit.me/ar/integration/web-sdks/javascript-sdk.md#خيارات-الكاميرا).
كل عدسة هي إما `CameraLens.Front` أو `CameraLens.Back`.
إذا لم تتوفر على الجهاز العدسة المطلوبة، يستخدم SDK أول كاميرا متاحة لديه.
يُخفى زر تبديل الكاميرا أيضاً على الأجهزة التي تحتوي على كاميرا واحدة فقط.
اضبط خيار التبديل على `false` لتقييد المستخدم بالعدسة الافتراضية لتلك الخطوة.```tsx theme={null}
import { startVerification, CameraLens } from '@didit-protocol/sdk-react-native';

await startVerification('your-session-token', {
  defaultLivenessCamera: CameraLens.Back,
  showLivenessCameraSwitchButton: false,
});
```> [!NOTE]
>
> **السمات والألوان**: تُضبط الألوان والخلفيات وإعدادات شاشة المقدمة عبر [إعدادات العلامة البيضاء](https://business.didit.me) في وحدة تحكم Didit، وليس في إعدادات SDK. يضمن ذلك هوية بصرية متسقة عبر جميع المنصات.***## دعم اللغاتيدعم SDK **54 لغة**. إذا لم تُحدَّد لغة، يستخدم SDK لغة الجهاز مع الإنجليزية كلغة احتياطية.```tsx theme={null}
// Use device locale (default)
await startVerification(token);

// Force specific language
await startVerification(token, { languageCode: 'fr' });

// Let the user change language on the welcome screen
await startVerification(token, { showLanguageSelector: true });
```**[عرض جميع اللغات المدعومة ←](https://docs.didit.me/ar/integration/supported-languages.md)*****## الخيارات المتقدمةهذه الخيارات متاحة فقط مع `startVerificationWithWorkflow`، حيث ينشئ SDK الجلسة نيابةً عنك.### بيانات الاتصال (التعبئة المسبقة والإشعارات)قدّم بيانات الاتصال لتعبئة نماذج التحقق مسبقاً وتفعيل إشعارات البريد الإلكتروني:```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  contactDetails: {
    email: 'user@example.com',
    sendNotificationEmails: true,  // Send status update emails
    emailLang: 'en',               // Email language (ISO 639-1)
    phone: '+14155552671',         // E.164 format
  },
});
```### التفاصيل المتوقعة (التحقق المتبادل)قدّم تفاصيل المستخدم المتوقعة للتحقق المتبادل التلقائي مع البيانات المستخرجة من المستند:```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  expectedDetails: {
    firstName: 'John',
    lastName: 'Doe',
    dateOfBirth: '1990-05-15',     // YYYY-MM-DD format
    gender: 'M',
    nationality: 'USA',            // ISO 3166-1 alpha-3
    country: 'USA',
    address: '1 Market St, San Francisco, CA',
    identificationNumber: 'A1234567',
    ipAddress: '203.0.113.42',
    portraitImage: 'https://...',  // URL or base64 reference image
  },
});
```جميع حقول `ExpectedDetails` اختيارية. راجع [`src/types.ts`](https://github.com/didit-protocol/sdk-react-native/blob/main/src/types.ts) للاطلاع على النوع الكامل.### البيانات الوصفية المخصصةخزّن بيانات JSON وصفية مخصصة مع الجلسة (لا تُعرض للمستخدم):```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  metadata: '{"internalId": "abc123", "source": "mobile-app"}',
});
```***## معالجة النتائجتُرجع الدالتان `startVerification` و`startVerificationWithWorkflow` كلتاهما قيمة `Promise<VerificationResult>`. النتيجة من نوع اتحاد مميَّز، لذا استخدم الحقل `type` لتحديد النتيجة.### حالات النتيجة| الحالة | الوصف |
| - | - |
| `completed` | اكتمل مسار التحقق (تحقق من `session.status` للحصول على النتيجة) |
| `cancelled` | ألغى المستخدم مسار التحقق |
| `failed` | حدث خطأ أثناء التحقق |### خصائص SessionData| الخاصية | النوع | الوصف |
| - | - | - |
| `sessionId` | `string` | معرّف الجلسة الفريد |
| `status` | `VerificationStatus` | `Approved` أو `Pending` أو `Declined` |### أنواع الأخطاء| الخطأ | الوصف |
| - | - |
| `sessionExpired` | انتهت صلاحية الجلسة |
| `networkError` | مشكلة في الاتصال بالشبكة |
| `cameraAccessDenied` | لم يُمنح إذن الكاميرا |
| `notInitialized` | لم تتم تهيئة SDK (Android فقط) |
| `apiError` | فشل طلب API |
| `unknown` | خطأ آخر مع رسالة |### انقطاع الاتصالإذا فقد الجهاز اتصاله أثناء التحقق، يعرض SDK شاشة "لا يوجد اتصال بالإنترنت" بدلاً من ترك خطوة في حالة التحميل.
يواصل SDK التحقق من الاتصال في الخلفية، ويُغلق الشاشة تلقائياً بمجرد استعادة إمكانية الوصول إلى Didit، ويتابع المستخدم من الخطوة التي كان فيها.
تعرض الشاشة الزر **Try Again** وعند ضبط `showCloseButton` على `true` (وهي القيمة الافتراضية) الزر **Exit Verification**.
الخروج ينهي التحقق بنتيجة `failed` ويكون الخطأ فيها `networkError`، لكي يعرف تطبيقك أن المستخدم غادر بسبب الاتصال.### مثال كامل لمعالجة النتائج```tsx theme={null}
import {
  startVerification,
  VerificationStatus,
  type VerificationResult,
} from '@didit-protocol/sdk-react-native';

async function verify(token: string) {
  const result: VerificationResult = await startVerification(token);

  switch (result.type) {
    case 'completed':
      switch (result.session.status) {
        case VerificationStatus.Approved:
          console.log('Approved! Session:', result.session.sessionId);
          // User is verified — grant access
          break;
        case VerificationStatus.Pending:
          console.log('Under review. Session:', result.session.sessionId);
          // Show "verification in progress" UI
          break;
        case VerificationStatus.Declined:
          console.log('Declined. Session:', result.session.sessionId);
          // Handle declined verification
          break;
      }
      break;

    case 'cancelled':
      console.log('User cancelled the verification.');
      // Maybe show retry option
      break;

    case 'failed':
      console.log(`Error [${result.error.type}]: ${result.error.message}`);
      // Handle error — show retry or contact support
      break;
  }
}
```***## من البداية إلى النهاية (من الخادم الخلفي إلى SDK React Native إلى webhook)هذا تكامل جاهز للإنتاج: يُنشئ الخادم الخلفي الجلسة، ويستقبل تطبيق React Native الرمز `session_token`، ويُشغّل SDK مسار التحقق. يُرسَل القرار النهائي إلى الخادم الخلفي عبر webhook، ولا تثق أبداً بالنتيجة التي تظهر على الجهاز وحدها.### 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. React Native: تبادل الرمز وبدء SDK```tsx theme={null}
import { useCallback, useState } from 'react';
import { Button, View } from 'react-native';
import {
  startVerification,
  VerificationStatus,
  type VerificationResult,
} from '@didit-protocol/sdk-react-native';

export function VerifyButton({ userId }: { userId: string }) {
  const [loading, setLoading] = useState(false);

  const onPress = useCallback(async () => {
    setLoading(true);
    try {
      const r = await fetch('https://your-backend.example.com/api/verification/start', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId }),
      });
      const { session_token } = await r.json();

      const result: VerificationResult = await startVerification(session_token);

      switch (result.type) {
        case 'completed':
          if (result.session.status === VerificationStatus.Approved) {
            // Optimistic UI; rely on the webhook delivered to your backend as the source of truth.
          }
          break;
        case 'cancelled':
          // User dismissed the flow
          break;
        case 'failed':
          // Show retry — result.error.type / result.error.message
          break;
      }
    } finally {
      setLoading(false);
    }
  }, [userId]);

  return (
    <View>
      <Button title={loading ? 'Starting...' : 'Verify identity'} onPress={onPress} disabled={loading} />
    </View>
  );
}
```### 3. الخادم الخلفي: استلام القرار النهائي عبر webhook```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);
});
```راجع [دليل Webhooks](https://docs.didit.me/ar/integration/webhooks.md) لمعرفة تفاصيل التحقق من توقيع HMAC.***## مثال كامل```tsx theme={null}
import { useState, useCallback } from 'react';
import {
  Text,
  View,
  TextInput,
  TouchableOpacity,
  Alert,
  ActivityIndicator,
  SafeAreaView,
} from 'react-native';
import {
  startVerification,
  VerificationStatus,
  type VerificationResult,
} from '@didit-protocol/sdk-react-native';

export default function App() {
  const [token, setToken] = useState('');
  const [loading, setLoading] = useState(false);

  const handleVerify = useCallback(async () => {
    if (!token.trim()) {
      Alert.alert('Error', 'Please enter a session token.');
      return;
    }

    setLoading(true);
    try {
      const result = await startVerification(token.trim(), {
        loggingEnabled: true,
      });

      switch (result.type) {
        case 'completed':
          Alert.alert(
            'Verification Complete',
            `Status: ${result.session.status}\nSession: ${result.session.sessionId}`
          );
          break;
        case 'cancelled':
          Alert.alert('Cancelled', 'The user cancelled the verification.');
          break;
        case 'failed':
          Alert.alert('Failed', `${result.error.type}: ${result.error.message}`);
          break;
      }
    } catch (error) {
      Alert.alert('Error', `Unexpected error: ${error}`);
    } finally {
      setLoading(false);
    }
  }, [token]);

  return (
    <SafeAreaView style={{ flex: 1, padding: 24, justifyContent: 'center' }}>
      <TextInput
        placeholder="Enter session token..."
        value={token}
        onChangeText={setToken}
        autoCapitalize="none"
        style={{
          borderWidth: 1,
          borderColor: '#ccc',
          borderRadius: 8,
          padding: 12,
          marginBottom: 16,
        }}
      />
      <TouchableOpacity
        onPress={handleVerify}
        disabled={loading}
        style={{
          backgroundColor: '#1a1a1a',
          borderRadius: 8,
          padding: 16,
          alignItems: 'center',
          opacity: loading ? 0.6 : 1,
        }}
      >
        {loading ? (
          <ActivityIndicator color="#fff" />
        ) : (
          <Text style={{ color: '#fff', fontWeight: '600' }}>
            Start Verification
          </Text>
        )}
      </TouchableOpacity>
    </SafeAreaView>
  );
}
```***


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