跳轉到主要內容

Web SDK 集成指南

文檔對應版本。Web SDK 1.0.1(默認標籤)/ 1.0.0-beta.3(@beta)。本頁依據更新日期爲 2026 年 9 月 11 日的 WIDTH 集成指南。部署前請確認所選 SDK 構建版本及其目標環境。

概述

Width Web SDK 爲 Web 應用提供即插即用的身份驗證流程。支持 KYC 和 KYB 工作流,包括證件採集、活體檢測與審覈。SDK 自託管:你引入一個包,用鏈式調用配置它,再調用 launch() — SDK 會自行彈出彈窗或打開新標籤頁,並通過事件回報結果。無需提供 DOM 容器。它以 ESM 構建發佈,自帶完整 TypeScript 類型定義,無 peer 依賴。

系統要求

要求 最低版本
模塊格式 ESM(import 引入)
TypeScript 自帶類型定義(可選)
Peer 依賴 無
後端 需通過 sdk.credentials 簽發會話 token

步驟 1:獲取會話 token(後端)

Web SDK 從一個一次性會話 token(即 sdkToken)開始。你的服務端向 Width 的 sdk.credentials 接口請求它,再把它交給瀏覽器。公開的 apiKey 與 domainId 在後續步驟中配置;帶密鑰的簽名只在你的服務端完成。

// Server-side request to Width (signed with your secret)
POST {WIDTH_GATEWAY_URL}/gateway?api=sdk.credentials&apiVersion=1.0.0&apiKey={your_apiKey}&sign=...
Content-Type: application/json

{}
// Response — read sdkToken and the domains[] list
{
  "apiCode": 200,
  "apiMsg": "OK",
  "data": {
    "data": {
      "sdkToken": "eyJhbGciOi...",
      "domains": [
        { "code": "DEFAULT", "name": "Default", "id": "dom_xxxxxxxx" }
      ]
    }
  }
}

在後端開一個小接口(例如 /your-backend/sdk-token),把 sdkToken 和 domainId 返回給前端。把從 domains[] 中選定的 domainId 在步驟 3 傳入 SDK 配置。

每個 token 僅一次性使用 每個 sdkToken 僅可使用一次。每當用戶開始一次新的驗證時,都要重新簽發一個新 token — 不要緩存或複用。
sdk.credentials 調用使用與其他 API 相同的網關基址及 HMAC 簽名,詳見 OpenAPI 參考。

步驟 2:安裝 SDK

從 npm 安裝。安裝後即可按包名 @width-com/web-sdk 引入 — ESM 構建,自帶 TypeScript 類型定義,無 peer 依賴。裝哪個標籤同時決定 SDK 連到哪個環境:按本指南基準,默認(latest)版對應正式環境,@beta 標籤版對應 platform(測試)環境。請按你的 apiKey 所屬環境選擇對應標籤,並在上線前確認你裝的這一版實際打開的是哪個地址(見下方提示)。

# Production (正式环境)
npm install @width-com/web-sdk
# or
pnpm add @width-com/web-sdk
# or
yarn add @width-com/web-sdk

# Testing / beta (测试环境)
npm install @width-com/web-sdk@beta
# or
pnpm add @width-com/web-sdk@beta
# or
yarn add @width-com/web-sdk@beta
標籤決定環境 — 裝錯會看到 Invalid apiKey 驗證頁地址是隨每個發佈版本編譯進包裏的,裝好之後連哪個環境就定死了,withConf 裏也沒有任何字段能改它。按本指南基準,默認(latest)版打開的是 https://identity.width.com/sdk-page(正式環境),@beta 版打開的是 https://identity-platform.width.com/sdk-page(platform 環境)— 這個對應關係取決於兩個標籤本指南記錄的各自指向哪個構建,是當下的狀態、不是固定規則,上線前請自行確認你裝的這一版實際打開的是哪個地址。如果標籤與你 apiKey 所屬的環境對不上,這個頁面會直接顯示 Invalid apiKey,流程就停在這裏 — 用同一把 key 調用後端 OpenAPI 不受影響,所以問題不在 key 本身。按環境選標籤,不要按版本號新舊選。前後端共用一把 key:withConf 裏與 key 相關的字段只有 apiKey 一個,它就是你簽發 sdk.credentials 時用的那一把 — 包內自帶的 TypeScript 類型定義列出了它接受的全部字段。供參考:@beta 在本指南基準中指向 1.0.0-beta.3(2026-08-05 發佈),默認版爲 1.0.1,兩者都含 eventType 與 language。

步驟 3:初始化(快速開始)

用一條鏈式調用構建驗證:init 傳入會話 token,withConf 傳入配置,用 on / onMessage 訂閱事件,再 build().launch()。launch() 會彈出自託管的彈窗或新標籤頁 — 無需提供 DOM 容器。

import { widthWebSdk } from '@width-com/web-sdk';

// Get the session token from your backend (sdkToken from sdk.credentials)
const { sdkToken, domainId } =
  await fetch('/your-backend/sdk-token').then(r => r.json());

widthWebSdk
  .init(sdkToken)
  .withConf({
    apiKey:     'ak_your_public_api_key', // required
    domainId,                             // required
    email:      'enduser@example.com',    // required
    customerId: 'cust_internal_id',       // required
    mode:       'modal',                  // 'modal' (default) | 'newtab'
    // eventType: 'KYC_EVENT',            // optional — 'KYC_EVENT' | 'KYB_EVENT'; omit for default routing
  })
  .on('idCheck.onApplicantVerificationCompleted', (payload) => {
    // payload.reviewResult.reviewAnswer: 'GREEN' (approved) | 'RED' (not approved)
  })
  .on('idCheck.onApplicantSubmitted', (payload) => {
    // Submitted; async review in progress
  })
  .on('idCheck.onError', (payload) => {
    // payload.code / payload.error
  })
  .onMessage((type, payload) => {
    if (type === 'width.onCancelled') {
      // User closed the flow
    }
  })
  .build()
  .launch();   // self-hosted modal / new tab — no DOM container needed
eventType 與 language 需要 1.0.1 及以上版本 這兩個字段自 1.0.1(2026-08-20 發佈,即本指南記錄的默認 latest 版)起提供,@beta 在本指南基準中指向的 1.0.0-beta.3 同樣含有它們 — 也就是說兩個環境都能用,標籤仍按環境選(見步驟 2)。1.0.0 及更早的正式版不含它們:TypeScript 項目會編譯失敗,純 JavaScript 項目則不報錯、也不生效。eventType 只接受 KYC_EVENT 或 KYB_EVENT,language 只接受 en 或 zh;兩者都是選填,不傳即走默認行爲。

配置(withConf)

字段 類型 必填 描述
apiKey string 是 公開 Width API Key(ak_...)
domainId string 是 業務域(domain)GID,取自 sdk.credentials 的 domains[]
email string 是 終端用戶郵箱
customerId string 是 你的內部用戶 ID
mode 'modal' | 'newtab' 否 展示形態,默認 'modal'
language 'en' | 'zh' 否 界面語言。不傳該字段時界面爲英文;不會按瀏覽器語言自動判斷。自 1.0.1 起提供。
eventType 'KYC_EVENT' | 'KYB_EVENT' 否 這次要跑哪一類流程——個人覈驗(KYC_EVENT)還是企業覈驗(KYB_EVENT)。不傳該字段時按默認方式路由(見工作流與決策模型)。自 1.0.1 起提供。
zIndex number 否 本指南基準未指定默認值。彈窗層級

步驟 4:處理驗證結果

launch() 成功時返回本次會話的完整覈驗頁 URL,失敗時返回空字符串。錯誤通過 idCheck.onError 回傳。

按你訂閱的事件分支處理。最終結論由 reviewResult.reviewAnswer 攜帶,只有兩個取值:結論爲通過時是 GREEN,其餘一律是 RED。

.on('idCheck.onApplicantVerificationCompleted', (payload) => {
  const { reviewResult, executionId } = payload;
  if (reviewResult.reviewAnswer === 'GREEN') {
    grantAccess(executionId);
  } else {
    handleNotApproved(executionId);
  }
})

每個事件對應一條處理分支:

事件 處理方式
idCheck.onApplicantVerificationCompleted 已有最終結論 — 讀取 reviewAnswer
idCheck.onApplicantSubmitted 已提交;進入異步審覈
idCheck.onError 上報失敗
width.onCancelled (via onMessage) 用戶關閉了流程
對賬 executionId 是與後端 / OpenAPI 對賬的句柄。對 idCheck.onApplicantSubmitted(異步審覈)場景請持久化它,以便服務端稍後輪詢最終狀態。

驗證結果參考

最終結論由 reviewResult.reviewAnswer 攜帶:

reviewAnswer 含義
GREEN 通過
RED 未通過。SDK 會把「通過」以外的所有結論都映射成 RED——被拒絕的會落在這裏,其他非通過的結果同樣落在這裏。把 RED 當作「已拒絕」處理之前,先查案件狀態(workflow.execution.status 返回的 caseStatus,或到控制檯看該案件)。
只有兩個取值 截至 1.0.1(1.0.0-beta.3 相同),Web SDK 只把結論收成這兩個值,沒有第三個取值。GREEN 走通過分支;RED 按「未通過」處理,除非案件狀態確認它就是拒絕。

方法

調用 返回 作用
widthWebSdk.init(accessToken) builder 用會話 token 開始鏈式配置
.withConf(conf) builder 提供配置(見「配置」)
.on(eventName, callback) builder 訂閱單個事件
.onMessage((type, payload) => {}) builder 用一個處理器接收所有事件
.build() 實例 完成構建
instance.launch(container?) string 啓動驗證,返回本次會話的整條驗證頁網址 — 形如 https://identity.width.com/sdk-page?sdkMode=1&sdkSession=<会话 id>&apiKey=<你的 apiKey>&theme=light,其中主機名取自你安裝的那一版(見步驟 2)— 啓動失敗時返回 ''。這條網址對應的就是本次驗證會話,它背後的會話 token 僅一次性有效(見步驟 1)。container 被忽略
instance.close() void 主動關閉驗證窗口

事件參考

用 .on(eventName, callback) 註冊單個事件,或用 .onMessage((type, payload) => {}) 接收全部。

事件 觸發時機 載荷
idCheck.onApplicantVerificationCompleted 流程完成、有結論 { reviewStatus: 'completed', reviewResult: { reviewAnswer: 'GREEN' | 'RED' }, executionId }
idCheck.onApplicantStatusChanged 與 Completed(idCheck.onApplicantVerificationCompleted)同時觸發{ reviewStatus: 'completed', reviewResult: { reviewAnswer: 'GREEN' | 'RED' }, executionId }
idCheck.onApplicantSubmitted 已提交、異步審覈中 { executionId }
idCheck.onError 失敗 { code, error, executionId? }
width.onCancelled 用戶關閉(僅經 onMessage) {}
錯誤投遞 校驗失敗與運行時錯誤統一經 idCheck.onError 投遞 — SDK 不會向你的代碼拋異常。

錯誤碼

在 idCheck.onError 中,payload.code 爲以下之一:

碼 含義 可重試
INVALID_INPUT 啓動參數缺失或非法 否
SDK_ERROR 網絡、超時或內部錯誤 是
WORKFLOW_FAILED 流程以非成功狀態結束 否

瀏覽器支持

Web SDK 依賴 crypto.randomUUID、ES2020 語法,以及現代的 fetch 與 postMessage。下表是同時具備這三項的最低版本,低於該版本的瀏覽器不在支持範圍內。

瀏覽器 最低版本
Chrome / Edge(桌面端) 92+
Firefox 95+
Safari(macOS 與 iOS) 15.4+
Chrome(Android) 92+

故障排查

現象 可能原因 解決
onError { INVALID_INPUT, "apiKey is required." } apiKey 缺失或爲空 傳入公開 API Key
onError { INVALID_INPUT, "accessToken is required." } 後端未返回 sdkToken 檢查 sdk.credentials 集成
onError { INVALID_INPUT, "domainId is required." } 初始化時 withConf 未傳 domainId 傳入你從 sdk.credentials 返回的 domains[] 中選定那個 domain 的 id
onError { INVALID_INPUT, "email is required." } 缺少 email 傳入終端用戶郵箱
onError { INVALID_INPUT, "customerId is required." } 缺少 customerId 傳入內部用戶 ID
onError { INVALID_INPUT, "email format is invalid." } 郵箱格式錯誤 表單先校驗
onError { INVALID_INPUT, "apiKey does not match SDK credentials." } apiKey 與 accessToken 不屬於同一應用 用同一 apiKey 重新簽發 token
onError { SDK_ERROR } 網絡 / 連接問題 重新構建鏈並再次 launch()
彈窗不出現 / iframe 被攔截 域名未加白名單,或 CSP frame-src 缺少該源 在控制檯 API & Integration 下把該源加進白名單(見表格下方說明),並在 CSP frame-src 裏放行它
相機權限被拒 宿主 Permissions-Policy 過嚴 更新你的策略頭(見下方說明)
無事件觸發 會話仍在進行,或未註冊回調 等待完成;檢查 .on() 回調
在控制檯把你的站點加進白名單 白名單由你自己在控制檯配置:在 API & Integration(API 與集成) 下,把承載 SDK 的每個源逐個加進去。每條地址必須以 https:// 或 http:// 開頭、不帶路徑、也不支持通配符,因此每個主機名都要單獨寫一條(例如 https://app.example.com 和 https://checkout.example.com)。如果這個頁面上看不到生成密鑰的按鈕,通常是本指南記錄的賬號的角色缺少管理 API 密鑰這條權限 — 這類按鈕按權限渲染,沒有權限時是直接不顯示、而不是變灰,請讓租戶管理員爲你開通。
CSP 與權限策略 在 modal 模式下,SDK 會在你自己的頁面裏插入一個 iframe 來加載驗證頁,所以只要你的頁面設了 Content-Security-Policy,就必須在 frame-src 裏放行這個源,並通過 Permissions-Policy 把相機(以及活體所需的麥克風 / 運動傳感器)授權給同一個源。填哪個源取決於你裝的是哪個標籤(見步驟 2):默認(latest,本指南記錄的爲 1.0.1)版加載的是 https://identity.width.com,@beta 版加載的是 https://identity-platform.width.com。按你實際上線的那一版選對應的一段 — 源沒寫進 frame-src,瀏覽器就會攔掉這個 iframe,驗證窗口只剩空白。
# Default (latest) build / 默认(latest)版
Content-Security-Policy: frame-src https://identity.width.com;
Permissions-Policy: camera=(self "https://identity.width.com"),
                    microphone=(self "https://identity.width.com"),
                    accelerometer=(self "https://identity.width.com"),
                    gyroscope=(self "https://identity.width.com")
# @beta build / @beta 版
Content-Security-Policy: frame-src https://identity-platform.width.com;
Permissions-Policy: camera=(self "https://identity-platform.width.com"),
                    microphone=(self "https://identity-platform.width.com"),
                    accelerometer=(self "https://identity-platform.width.com"),
                    gyroscope=(self "https://identity-platform.width.com")