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

# JavaScript 身份验证 SDK：Web KYC 集成

> Didit 提供即插即用的 JavaScript SDK，支持 KYC、KYB、AML 和生物活体检测，可嵌入、跳转或以 iframe 集成。完整 KYC 每次 $0.33 起，每月免费 $10，无需签约。



JavaScript SDK 集成提示
        将提示词复制到剪贴板



      
      

\<pre>

\`Integrate Didit identity verification into my web application using the JavaScript SDK.

\## Setup
Install: npm install @didit-protocol/sdk-web
Or CDN: <script src="https://unpkg.com/@didit-protocol/sdk-web/dist/didit-sdk.umd.min.js"></script>

\## Integration Flow
1\. (Option A — UniLink) Use a fixed UniLink URL from the Didit Console (no backend needed)
2\. (Option B — API session) Backend creates a session via POST /v3/session/ → 201 response includes "url"
3\. Frontend calls DiditSdk.shared.startVerification({ url }) — the SDK opens a modal (or inline if embedded mode)
4\. On completion, the SDK invokes DiditSdk.shared.onComplete(result) with type "completed" | "cancelled" | "failed"
5\. Backend receives full signed decision via webhook (status.updated)

\## Frontend Code — Vanilla JS / TypeScript
import { DiditSdk } from '@didit-protocol/sdk-web';

DiditSdk.shared.onComplete = (result) => {
switch (result.type) {
case 'completed':
  // result.session.status: "Approved" | "Pending" | "Declined"
  console.log('Done:', result.session.sessionId, result.session.status);
  break;
case 'cancelled':
  console.log('User cancelled');
  break;
case 'failed':
  console.error('Failed:', result.error.type, result.error.message);
  break;
}
};

// Modal mode (default)
DiditSdk.shared.startVerification({
url: 'https://verify.didit.me/session/SESSION_TOKEN' // from backend OR UniLink
});

// Inline / embedded mode
DiditSdk.shared.startVerification({
url: 'https://verify.didit.me/session/SESSION_TOKEN',
configuration: { embedded: true, embeddedContainerId: 'didit-container' }
});

\## Frontend Code — React
function VerifyButton({ userId }) {
const [loading, setLoading] = useState(false);

async function handleVerify() {
setLoading(true);
const res = await fetch('/api/create-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ user_id: userId })
});
const { url } = await res.json(); // OpenAPI field is named "url"

const { DiditSdk } = await import('@didit-protocol/sdk-web');
DiditSdk.shared.onComplete = (result) => {
  if (result.type === 'completed') {
    // update UI; final, signed result arrives on backend via webhook
  }
  setLoading(false);
};
DiditSdk.shared.startVerification({ url });
}

return <button onClick={handleVerify} disabled={loading}>Verify Identity</button>;
}

\## Backend: Create Session
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "callback": "https://myapp.com/done", "vendor_data": userId }
Returns 201 (all 10 fields, per OpenAPI):
\{
"session_id": "uuid",
"session_number": 43762,
"session_token": "3FaJ9wLqX2Mz",   // 12-char URL-safe token; valid until the session expires
"url": "https://verify.didit.me/session/3FaJ9wLqX2Mz",
"vendor_data": "userId",
"metadata": null,
"status": "Not Started",
"workflow_id": "uuid",
"workflow_version": 3,
"callback": "https://myapp.com/done"
}
Pass the "url" field to DiditSdk.shared.startVerification({ url }) — never build the URL by hand.
(If the request sets "language", the URL gains a language segment: https://verify.didit.me/es/session/...)

\## SDK Surface (singleton — DiditSdk.shared)
Methods:  startVerification(options), close(), destroy()
Callbacks: onComplete(result), onStateChange(state, error?), onEvent(event)
State enum: 'idle' | 'loading' | 'ready' | 'error'

\## Rate Limits
600 session-create requests per minute per API key (falls back to bearer token, then client IP), plus a shared budget of 300 write (POST/PATCH/DELETE) requests per minute across all endpoints — the 300/min budget is exhausted first. Exceeding either returns HTTP 429 with Retry-After.

\## Environment Variables
\- DIDIT_API_KEY — backend only (Didit Console > API & Webhooks)
\- DIDIT_WORKFLOW_ID — backend only (Didit Console > Workflows)
\- Never expose the API key on the frontend — the session_token embedded in "url" is the only credential the SDK needs. It grants access to that one session's flow (valid until the session expires), so don't log or share it either.

\## Docs
\- JavaScript SDK: https://docs.didit.me/integration/web-sdks/javascript-sdk
\- Create Session API: https://docs.didit.me/sessions-api/create-session
\- Webhooks: https://docs.didit.me/integration/webhooks`

\</pre>



      
      

粘贴到

Didit JavaScript SDK 提供了一种编程方式，可将验证集成到您的 Web 应用中，并完全掌控用户体验。***## 功能特性- **简单的 API** - 单例模式，方法易于使用
- **灵活集成** - 可直接使用 UniLink URL，也可通过后端创建会话
- **响应式** - 适用于桌面和移动端浏览器
- **可自定义** - 提供样式和行为的配置选项
- **多种格式** - 提供 ESM、CommonJS 和 UMD 构建版本
- **TypeScript 支持** - 包含完整的类型定义
- **弹窗与内嵌模式** - 可选择弹窗覆盖层或内嵌方式
- **事件回调** - 用于跟踪验证进度的实时事件（已开始、步骤已完成、已结束）
- **状态管理** - 监听 SDK 状态以实现自定义界面***## 安装### NPM/Yarn```bash theme={null}
npm install @didit-protocol/sdk-web
# or
yarn add @didit-protocol/sdk-web
```### CDN (UMD)```html theme={null}
<script src="https://unpkg.com/@didit-protocol/sdk-web/dist/didit-sdk.umd.min.js"></script>
```> [!NOTE]
>
> 最新发布的 npm 版本为 `0.5.1`。
> `0.5.0` 新增了 `DiditSdk.shared.submitEvent()`（参见[提交事件](#提交事件)），`0.5.1` 允许托管流程在 SDK 内向数字身份钱包请求用户的 ID，并在启动失败时保持 `error` 状态，同时提供 `errorMessage`。
> `0.4.0` 新增了原生 SDK 已提供的摄像头选项，包括 `defaultLivenessCamera`，它会让人脸采集首先打开后置摄像头（参见[摄像头选项](#摄像头选项)）。### 检查已安装版本以包管理器的记录为准，确定已安装的版本：```bash theme={null}
npm list @didit-protocol/sdk-web
npm view @didit-protocol/sdk-web version
```您也可以检查运行时导出的内容：```typescript theme={null}
const { SDK_VERSION } = await import('@didit-protocol/sdk-web');

console.log(SDK_VERSION);
```从 `0.3.1` 开始，该导出内容由每种 JavaScript 格式（ESM、CommonJS、UMD、压缩版 UMD）以及 TypeScript 声明文件中的包版本生成，因此始终与已安装的版本一致。`0.3.0` 及更早版本无论安装的是哪个版本，都会从该导出返回 `0.2.1`。对于这些版本，请改用 `npm list` 或您的锁文件。***## 原生 JavaScript### ES Modules / TypeScript```typescript theme={null}
import { DiditSdk } from '@didit-protocol/sdk-web';

// Set up completion callback
DiditSdk.shared.onComplete = (result) => {
  switch (result.type) {
    case 'completed':
      console.log('Verification completed!');
      console.log('Session ID:', result.session?.sessionId);
      console.log('Status:', result.session?.status);
      break;
    case 'cancelled':
      console.log('User cancelled verification');
      break;
    case 'failed':
      console.error('Verification failed:', result.error?.message);
      break;
  }
};

// Start verification with the `url` returned by POST /v3/session/ (or your UniLink)
DiditSdk.shared.startVerification({
  url: 'https://verify.didit.me/session/3FaJ9wLqX2Mz'
});
```### Script 标签 (UMD)```html theme={null}
<script src="https://unpkg.com/@didit-protocol/sdk-web/dist/didit-sdk.umd.min.js"></script>
<script>
  const { DiditSdk } = DiditSDK;

  DiditSdk.shared.onComplete = (result) => {
    if (result.type === 'completed') {
      alert('Verification completed: ' + result.session.status);
    }
  };

  function startVerification() {
    DiditSdk.shared.startVerification({
      // You can get this link by clicking on "copy link" in the workflows view
      url: 'https://verify.didit.me/u/WORKFLOW_ID_IN_BASE_64'
    });
  }
</script>

<button onclick="startVerification()">Verify Identity</button>
```***## 框架示例> [card] [SDK Web 示例](https://github.com/didit-protocol/sdk-web-examples)
>
> React、Angular、Svelte、Next.js、Nuxt、Vue 等框架，并附有每个框架的示例和文档。***## 集成方式集成 SDK 有两种方式：### 方式 1: UniLink URL (最简单)直接使用 Didit 控制台中工作流的 UniLink URL。无需后端。```typescript theme={null}
DiditSdk.shared.startVerification({
  // You can get this link by clicking on "copy link" in the workflows view
  url: 'https://verify.didit.me/u/WORKFLOW_ID_IN_BASE_64'
});
```在 [Didit 控制台](https://business.didit.me) → 您的工作流 → Copy Link 中获取 UniLink URL。**生成的 session\_id 会通过事件发送给您。**
**[请在此查看事件参考](#事件参考)**### 方式 2: 后端会话 (推荐用于生产环境)您的后端通过 Didit API 创建会话，并返回托管验证页面的 URL。这样您可以控制 `vendor_data`、每个会话的 `callback` 和 `metadata`，还可以在用户到达前端之前创建会话。详见[创建会话 API 参考](https://docs.didit.me/zh/sessions-api/create-session.md)。**后端 (Node.js / Express)**```javascript theme={null}
import express from 'express';
const app = express();
app.use(express.json());

app.post('/api/create-session', 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,             // links the session to your user
      callback: 'https://yourapp.com/verified', // optional — overrides workflow default
    }),
  });

  if (!response.ok) {
    return res.status(response.status).send(await response.text());
  }

  // 201 response fields (per OpenAPI): session_id, session_number, session_token, url,
  // vendor_data, metadata, status, workflow_id, workflow_version, callback
  const session = await response.json();
  res.json({ session_id: session.session_id, url: session.url });
});
```**前端**```typescript theme={null}
import { DiditSdk } from '@didit-protocol/sdk-web';

const res = await fetch('/api/create-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ userId: 'user-123' }),
});
const { url } = await res.json();

DiditSdk.shared.startVerification({
  url,
  configuration: {
    loggingEnabled: true,
  },
});
```> [!NOTE]
>
> 创建会话的响应字段名为 `url`（参见[创建会话 OpenAPI 架构](https://docs.didit.me/zh/sessions-api/create-session.md)）。请将其直接传递给 `startVerification({ url })`。***## 配置| 选项 | 类型 | 默认值 | 描述 |
| - | - | - | - |
| `loggingEnabled` | `boolean` | `false` | 启用 SDK 日志，便于调试 |
| `containerElement` | `HTMLElement` | `document.body` | 用于挂载弹窗的自定义容器元素 |
| `zIndex` | `number` | `9999` | 弹窗覆盖层的 z-index |
| `showCloseButton` | `boolean` | `true` | 在弹窗上显示关闭按钮 |
| `showExitConfirmation` | `boolean` | `true` | 关闭时显示退出确认对话框 |
| `closeModalOnComplete` | `boolean` | `false` | 验证完成后自动关闭弹窗 |
| `embedded` | `boolean` | `false` | 以内嵌方式渲染验证，而非弹窗覆盖层 |
| `embeddedContainerId` | `string` | — | 嵌入模式的容器元素 ID（当 `embedded` 为 `true` 时必填） |
| `defaultDocumentCamera` | `'front' \| 'back'` | `'back'` | 证件采集首先打开的摄像头。参见[摄像头选项](#摄像头选项) |
| `defaultLivenessCamera` | `'front' \| 'back'` | `'front'` | 人脸（活体）采集首先打开的摄像头。参见[摄像头选项](#摄像头选项) |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | 在证件步骤中显示采集过程中的摄像头切换按钮 |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | 在活体步骤中显示采集过程中的摄像头切换按钮 |> [!TIP]
>
> 完整的 `DiditSdkConfiguration` 接口请参见下方的[完整 TypeScript 类型定义](#typescript-类型)。***## 摄像头选项> [!NOTE]
>
> 摄像头选项需要 `@didit-protocol/sdk-web`**0.4.0** 或更高版本。Web SDK 提供与[原生 SDK](https://docs.didit.me/zh/integration/native-sdks/overview.md) 相同的四个摄像头选项。默认情况下，证件采集打开后置摄像头，人脸（活体检测）采集打开前置（自拍）摄像头。只要设备有多个摄像头，两个步骤的采集界面中都会提供切换按钮。若要让人脸采集打开后置摄像头，例如在自助终端上，或由操作员手持设备对准被验证的人，请设置 `defaultLivenessCamera: 'back'`。| 选项 | 类型 | 默认值 | 说明 |
| - | - | - | - |
| `defaultDocumentCamera` | `'front' \| 'back'` | `'back'` | 首次进入证件采集界面时使用的镜头 |
| `defaultLivenessCamera` | `'front' \| 'back'` | `'front'` | 首次进入活体检测（被动人脸）采集界面时使用的镜头 |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | 在证件界面显示采集中的摄像头切换按钮；设为 `false` 时，用户只能使用 `defaultDocumentCamera` |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | 在活体检测界面显示采集中的摄像头切换按钮；设为 `false` 时，用户只能使用 `defaultLivenessCamera` |```typescript theme={null}
// A kiosk: the operator points the device at the person, on the rear camera, with no way to switch
DiditSdk.shared.startVerification({
  url,
  configuration: {
    defaultLivenessCamera: 'back',
    showLivenessCameraSwitchButton: false
  }
});
```- 可接受的镜头值为 `'front'` 和 `'back'`。其他任何值都会被忽略，不是布尔值的切换按钮标志同样会被忽略。
- 设备没有所请求的摄像头时，将继续使用其现有的摄像头：请求 `'back'` 的笔记本电脑仍使用其网络摄像头。在单摄像头设备上，无论标志如何设置，切换按钮都会隐藏。
- 摄像头选项仅作用于被动活体检测，主动活体检测不受影响。
- SDK 会将这些选项作为验证 URL 的查询参数传递给验证页面：`document_camera`、`liveness_camera`、`document_camera_switch` 和 `liveness_camera_switch`。如果你不通过 SDK，而是直接打开验证 URL，请自行设置这些参数：对于不带查询字符串的 URL，追加 `?liveness_camera=back`；对于已有参数的 URL，追加 `&liveness_camera=back`；也可以使用 `URL` API 设置，这样两种情况都能正确处理：```typescript theme={null}
const verificationUrl = new URL(url);
verificationUrl.searchParams.set('liveness_camera', 'back');
verificationUrl.searchParams.set('liveness_camera_switch', 'false');
window.location.assign(verificationUrl.toString());
```***## 提交事件`DiditSdk.shared.submitEvent()` 会将终端用户事件（注册、登录、登录失败、登出、密码重置、MFA、设备变更）加入队列，提交给 Didit 的事件监控。
你的后端为该用户生成监控令牌，SDK 则随设备指纹分批发送事件。
切勿将 API 密钥发送到浏览器中。```typescript theme={null}
DiditSdk.shared.submitEvent({
  monitoringToken, // minted by your backend for this person
  event: { category: "auth", actionType: "login", payload: { method: "password" } },
});
```有关令牌、事件字段和投递行为，请参阅 [SDK 事件提交](https://docs.didit.me/zh/transaction-monitoring/sdk-event-submission.md)。***## 弹窗尺寸与滚动> [!NOTE]
>
> 以下尺寸行为需要 **0.3.1** 或更高版本。**0.3.0** 及更早版本在较矮的桌面和横屏视口中可能会裁切验证流程。弹窗模式的最大宽度为 500px，最大高度为 700px。在较矮的桌面和横屏视口中，iframe 占可见视口的 90%。验证流程在 iframe 内部滚动，因此每个步骤都可以访问，同时弹窗背后的页面保持锁定。SDK 在支持动态视口单位的浏览器中使用 `dvh`，在较旧的受支持浏览器中回退到 `vh`。宽度为 540px 及以下时，弹窗会占满可见视口。关闭按钮和退出确认始终保持在弹窗内。### 重新设计的验证流程> [!NOTE]
>
> 本节所有内容适用于 **0.5.0** 版本，该版本尚未发布。在你升级之前，弹窗会保持上述尺寸。自 0.5.0 版本起，页面通过[`didit:layout` 消息](https://docs.didit.me/zh/integration/web-sdks/incontext-iframe#根据-diditlayout-设置-iframe-尺寸)报告其布局后，弹窗会根据重新设计的验证流程调整自身尺寸：| 窗口宽度 | 弹窗（自 0.5.0 版本起） |
| - | - |
| 1024px 及以上 | 每个步骤均为 960px × 660px，且不超过窗口宽度和高度的 90% |
| 541px 至 1023px | 宽 500px，高度与页面内容一致，且不超过窗口高度的 90% |
| 540px 及以下 | 全屏 |- **起始尺寸（自 0.5.0 版本起）：** 在页面报告布局之前，以及从不报告布局的页面，弹窗保持现有的最大尺寸 500px × 700px。它仍然适配较矮的窗口，并在 540px 及以下时保持全屏。
- **关闭按钮（自 0.5.0 版本起）：** 覆盖在页面顶部栏上的 44px 圆形按钮。它跟随页面的浅色或深色主题，在从右到左书写的语言中移动到左侧。
- **嵌入模式（自 0.5.0 版本起）：** 与以前一样，仍填充其宿主元素（请参阅[嵌入模式](#嵌入模式)）。
- **验证 URL（自 0.5.0 版本起）：** SDK 会添加 `sdk_presentation`（`modal` 或 `embedded`），并且在弹窗中添加 `sdk_close_button`（`true` 或 `false`，与 `showCloseButton` 保持一致），以便页面了解自己的展示方式。
- **事件（自 0.5.0 版本起）：** SDK 自行处理 `didit:layout`，不会将其传递给 `onEvent`。无需进行任何配置，所有现有选项都继续有效。***## 嵌入模式嵌入模式不使用弹窗的 500px × 700px 上限。SDK 会填充宿主元素的内容框，因此请为该元素设置明确的或其他可解析的高度：```html theme={null}
<div id="verification-container" style="width: 500px; height: 700px;"></div>
``````typescript theme={null}
DiditSdk.shared.startVerification({
  url: 'https://verify.didit.me/u/...',
  configuration: {
    embedded: true,
    embeddedContainerId: 'verification-container'
  }
});
```如果宿主没有可解析的高度，嵌入的 iframe 也将没有可用的高度。布局变化时请调整宿主大小，SDK 会自动继续填充它。***## 验证结果SDK 返回三种类型的结果：### 已完成验证流程已结束（已通过、待处理或已拒绝）。```typescript theme={null}
{
  type: 'completed',
  session: {
    sessionId: 'session-uuid',
    status: 'Approved' | 'Pending' | 'Declined'
  }
}
```> [!NOTE]
>
> TypeScript 类型声明的是 `'Approved' | 'Pending' | 'Declined'`，但该值直接取自托管流程的会话状态，因此您还可能收到其他状态，例如 `In Review`。当流程未返回状态时，SDK 会使用 `Pending` 作为默认值。请将 `status` 仅作为参考，并以 [Webhook](https://docs.didit.me/zh/integration/webhooks.md) 给出的结果为准。### 已取消用户关闭了验证弹窗。如果已获知 `sessionId`，则会包含 `session`（如果用户在 iframe 上报之前取消，则可能为 `undefined`）。```typescript theme={null}
{
  type: 'cancelled',
  session: {
    sessionId: 'session-uuid',
    status: 'Pending'
  }
}
```### 失败验证过程中发生错误。```typescript theme={null}
{
  type: 'failed',
  error: {
    type: 'sessionExpired' | 'networkError' | 'cameraAccessDenied' | 'unknown',
    message: 'Your verification session has expired.'
  }
}
```***## 状态管理您可以监听 SDK 状态，以实现自定义 UI：```typescript theme={null}
DiditSdk.shared.onStateChange = (state, error) => {
  switch (state) {
    case 'idle':
      // Ready to start
      break;
    case 'loading':
      // Loading verification iframe
      showLoadingSpinner();
      break;
    case 'ready':
      // Verification in progress
      hideLoadingSpinner();
      break;
    case 'error':
      // Error occurred
      showError(error);
      break;
  }
};

// Check current state
console.log(DiditSdk.shared.state);

// Check if verification is presented
console.log(DiditSdk.shared.isPresented);
```***## API 参考### DiditSdk.shared单例 SDK 实例。### 方法| 方法 | 描述 |
| - | - |
| `startVerification(options)` | 启动验证流程 |
| `submitEvent(options)` | 使用监控 token 将终端用户事件加入队列，用于事件监控 |
| `close()` | 以编程方式关闭验证弹窗 |
| `destroy()` | 销毁 SDK 实例并清理资源 |### 属性| 属性 | 类型 | 描述 |
| - | - | - |
| `state` | `DiditSdkState` | 当前 SDK 状态 |
| `configuration` | `DiditSdkConfiguration \| undefined` | 当前生效的配置（验证进行中时设置） |
| `isPresented` | `boolean` | 验证弹窗是否已打开 |
| `errorMessage` | `string \| undefined` | 错误信息（状态为 `error` 时设置）；启动失败后，状态会保持为 `error`，直到您重新开始 |### 回调| 回调 | 参数 | 描述 |
| - | - | - |
| `onComplete` | `(result: VerificationResult)` | 验证完成时调用 |
| `onStateChange` | `(state: DiditSdkState, error?: string)` | 状态变化时调用 |
| `onEvent` | `(event: VerificationEvent)` | 在细粒度验证事件发生时调用 |***## 精细事件使用 `onEvent` 回调跟踪验证进度：```typescript theme={null}
DiditSdk.shared.onEvent = (event) => {
  console.log('Event:', event.type, event.data);
};
```### 事件参考| 事件 | 说明 | 数据 payload |
| - | - | - |
| `didit:ready` | 页面已就绪，sessionId 可用 | `{ sessionId }` |
| `didit:started` | 用户开始验证 | `{ sessionId? }` |
| `didit:step_started` | 某个验证步骤已开始 | `{ step, sessionId? }` |
| `didit:step_completed` | 某个步骤已成功完成 | `{ step, nextStep?, sessionId? }` |
| `didit:step_changed` | 当前步骤已变更 | `{ step, previousStep?, sessionId? }` |
| `didit:media_started` | 摄像头或媒体采集已开始 | `{ step, mediaType }` |
| `didit:media_captured` | 已拍摄照片或视频 | `{ step, isAuto }` |
| `didit:document_selected` | 用户已选择证件类型和国家/地区 | `{ documentType, country }` |
| `didit:verification_submitted` | 数据已提交处理 | `{ step, sessionId? }` |
| `didit:code_sent` | 已发送 OTP 验证码 | `{ step, channel?, codeSize?, sessionId? }` |
| `didit:code_verified` | OTP 验证码已验证 | `{ step, sessionId? }` |
| `didit:status_updated` | 会话状态已变更 | `{ status, previousStep?, sessionId? }` |
| `didit:completed` | 验证流程已完成 | `{ sessionId?, status?, country?, documentType? }` |
| `didit:cancelled` | 用户已取消验证 | `{ sessionId? }` |
| `didit:error` | 发生错误 | `{ error: string, step?, sessionId? }` |
| `didit:close_request` | 用户请求关闭弹窗 | （无数据） |### 连接中断如果用户的网络连接中断，验证页面会用“无网络连接”页面覆盖整个流程，而不是让某个步骤一直处于加载状态。
页面会在后台持续检测连接，一旦可以访问 Didit，该页面会自动关闭，用户从原来所在的步骤继续操作。
在 SDK 的弹窗或 iframe 中，该页面还会提供 **退出验证** 按钮：点击后，页面会先发送 `didit:error`（`error: "network_error"`），再发送 `didit:cancelled`，SDK 随即关闭弹窗，并以 `type: "cancelled"` 调用 `onComplete`。从 0.5.0 版本起，页面的 `didit:layout` 消息用于设置弹窗尺寸，不会传递给 `onEvent`。如果你改为使用自己的 iframe 嵌入页面，请参阅 [从 `didit:layout` 设置 iframe 尺寸](https://docs.didit.me/zh/integration/web-sdks/incontext-iframe#根据-diditlayout-设置-iframe-尺寸)。### 步骤取值`step` 字段可以是以下值之一：- `document_selection` - 证件类型选择
- `document_front` - 证件正面
- `document_back` - 证件背面
- `face` - 人脸/活体验证
- `email` - 邮箱验证
- `phone` - 电话验证
- `poa` - 地址证明
- `questionnaire` - 问卷步骤### 渠道取值`code_sent` 中的 `channel` 字段可以是：- `email` - 通过邮件发送验证码
- `sms` - 通过短信发送验证码
- `whatsapp` - 通过 WhatsApp 发送验证码### 验证码长度`code_sent` 中的 `codeSize` 字段表示 OTP 验证码的位数（例如 4 位或 6 位）。***## TypeScript 类型```typescript theme={null}
// Configuration types
interface DiditSdkConfiguration {
  /**
   * Enable SDK logging for debugging
   * @default false
   */
  loggingEnabled?: boolean;

  /**
   * Custom container element to mount the modal
   * @default document.body
   */
  containerElement?: HTMLElement;

  /**
   * Z-index for the modal overlay
   * @default 9999
   */
  zIndex?: number;

  /**
   * Show close button on modal
   * @default true
   */
  showCloseButton?: boolean;

  /**
   * Show exit confirmation dialog when closing
   * @default true
   */
  showExitConfirmation?: boolean;

  /**
   * Automatically close modal when verification completes
   * @default false
   */
  closeModalOnComplete?: boolean;

  /**
   * Render verification inline instead of modal overlay
   * @default false
   */
  embedded?: boolean;

  /**
   * Container element ID for embedded mode
   * Required when embedded is true
   */
  embeddedContainerId?: string;

  /**
   * Camera the document capture opens first.
   * @default 'back'
   */
  defaultDocumentCamera?: CameraLens;

  /**
   * Camera the face (liveness) capture opens first.
   * Applies to passive liveness; devices without a rear camera keep the front one.
   * @default 'front'
   */
  defaultLivenessCamera?: CameraLens;

  /**
   * Show the in-capture camera switcher on the document step.
   * false locks the user to defaultDocumentCamera.
   * @default true
   */
  showDocumentCameraSwitchButton?: boolean;

  /**
   * Show the in-capture camera switcher on the liveness step.
   * false locks the user to defaultLivenessCamera.
   * @default true
   */
  showLivenessCameraSwitchButton?: boolean;
}

type CameraLens = 'front' | 'back';

// Session + error types
type VerificationStatus = 'Approved' | 'Pending' | 'Declined';

interface SessionData {
  sessionId: string;
  status: VerificationStatus;
}

type VerificationErrorType =
  | 'sessionExpired'
  | 'networkError'
  | 'cameraAccessDenied'
  | 'unknown';

interface VerificationError {
  type: VerificationErrorType;
  message: string;
}

// Verification result — `session` and `error` are both optional fields
// on every result; which one is populated depends on `type`.
type VerificationResultType = 'completed' | 'cancelled' | 'failed';

interface VerificationResult {
  type: VerificationResultType;
  session?: SessionData;
  error?: VerificationError;
}

// State types
type DiditSdkState = 'idle' | 'loading' | 'ready' | 'error';

// Event types
type VerificationEventType =
  | 'didit:ready'
  | 'didit:started'
  | 'didit:step_started'
  | 'didit:step_completed'
  | 'didit:step_changed'
  | 'didit:media_started'
  | 'didit:media_captured'
  | 'didit:document_selected'
  | 'didit:verification_submitted'
  | 'didit:code_sent'
  | 'didit:code_verified'
  | 'didit:status_updated'
  | 'didit:completed'
  | 'didit:cancelled'
  | 'didit:error'
  | 'didit:close_request';

interface VerificationEventData {
  sessionId?: string;
  status?: string;
  step?: string;
  nextStep?: string;
  previousStep?: string;
  error?: string;
  country?: string;
  documentType?: string;
  isAuto?: boolean;
  mediaType?: string;
  channel?: string;
  codeSize?: number;
  [key: string]: unknown;
}

interface VerificationEvent {
  type: VerificationEventType;
  data?: VerificationEventData;
  timestamp?: number;
}

// Start verification options
interface StartVerificationOptions {
  url: string;
  configuration?: DiditSdkConfiguration;
}
```


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