Flutter SDK 集成指南
概述
WIDTH Identity SDK 以即插即用的 Flutter 插件形式提供身份验证流程(KYC 与 KYB)。你添加一个依赖、调用一个入口;原生 SDK 全屏呈现完整的采集 / 活体 / 审核界面,并返回单一结果。该插件封装原生 iOS 与 Android SDK — 仅支持 iOS 与 Android(不支持 web 或桌面)。
1.0.2 — 绑定 iOS SDK 1.0.11 与
Android SDK 1.0.11。升级插件即一并升级原生
SDK;不要手动覆盖原生依赖。
系统要求
| 要求 | 最低版本 |
|---|---|
| Flutter | 3.10+ |
| iOS | 16.0+(部署目标)、Xcode 16+、CocoaPods |
| Android | minSdk 26(Android 8.0)、compileSdk 36,并开启 core library desugaring(见下文 Android 一节) |
domain /
accessToken 也必须是生产凭据。用别的环境的 token,过不了
SDK 的安全初始化,报错表现为 W-RISK-102。
安装
插件仓库、以及它 iOS 侧要拉的那个私有 Specs 仓库,都要先给你的 GitHub
账号开通访问权 — 在那之前,flutter pub get 和
pod install 都只会提示仓库不存在。
该插件通过 WIDTH 的私有 Git 仓库分发。将它添加到
pubspec.yaml:
dependencies:
flutter_width_identity_sdk_plugin:
git:
url: https://github.com/width-com/WidthIdentity-Flutter.git
ref: 1.0.2然后执行 flutter pub get。
iOS
原生 WidthIdentity pod 从 WIDTH 的私有 Specs 仓库解析。在
ios/Podfile 顶部声明两个 source 并设置 platform:
source 'https://github.com/width-com/Specs.git' source 'https://cdn.cocoapods.org/' # default trunk, for any public pods platform :ios, '16.0'
然后执行 cd ios && pod install。
Android
在 android/app/build.gradle 中设置
minSdk 26。插件会自动注册 WIDTH Maven
仓库、供应商采集引擎仓库(Veriff、Regula)以及原生依赖。
原生 SDK 内置的 AWS 活体引擎要求两项构建配置 — 都加在你自己的 App 上,两项都不涉及你的源码:
// android/app/build.gradle.kts
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}
该引擎的 Amplify AAR 在元数据里声明了「requires core library
desugaring」,AGP 会在 App 模块上强制校验,与你的
minSdk 是多少无关;不开启,构建直接失败。
# android/gradle.properties — AGP 9 only android.uniquePackageNames=false
AGP 9 的清单合并会校验库命名空间的唯一性,而活体引擎传递引入的两个产物(com.google.ai.edge.litert:litert-support
与 litert-support-api)声明了同一个命名空间
org.tensorflow.lite.support —
这是上游的打包缺陷。不加这个开关,构建会以
Validation failed, exiting 失败。
若你的项目启用了
RepositoriesMode.FAIL_ON_PROJECT_REPOS,则改为在
android/settings.gradle 中声明这些仓库:
dependencyResolutionManagement {
repositories {
maven { url = uri("https://maven.width.com/repository/sdk-releases/") }
google()
mavenCentral()
maven {
url = uri("https://cdn.veriff.me/android/")
content { includeGroup("com.veriff") }
}
maven {
url = uri("https://maven-master.regulaforensics.com/RegulaDocumentReader/")
content { includeGroupByRegex("com\\.regula.*") }
}
}
}权限
iOS — 添加到
ios/Runner/Info.plist。相机、麦克风、语音识别三项必填;照片库那一项可选:
<!-- Required: document capture and liveness. -->
<key>NSCameraUsageDescription</key>
<string>Used to capture identity documents and complete the liveness check.</string>
<!-- Required: the document verification provider records background audio
(anti-fraud) — the app crashes at runtime without this key. -->
<key>NSMicrophoneUsageDescription</key>
<string>Used by the document verification provider during video capture.</string>
<!-- Required by App Store ingestion; never requested at runtime (a linked but
unreachable API inside the AWS liveness component). -->
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app does not request speech recognition.</string>
<!-- Optional: only if your app also lets users pick a document image from the
photo library. -->
<key>NSPhotoLibraryUsageDescription</key>
<string>Used to select identity document images.</string>
Android — 原生 SDK 的 manifest
会自动合并所需权限,你无需声明。运行时(危险级)权限是
CAMERA 与
RECORD_AUDIO(后者由内置的采集 / 活体引擎引入),由 SDK
在其自有 Activity 内部申请。完整权限清单见
Android 章「权限」节,并需把每一项反映到你的 Google Play Data Safety(数据安全)申报中。
快速开始
引入插件,用链式调用构建 SDK,再
await sdk.launch()。当原生流程关闭时该 future 完成。
import 'package:flutter_width_identity_sdk_plugin/flutter_width_identity_sdk_plugin.dart';
final sdk = WIDTHMobileSDK.init(sdkToken)
.withCredentials(domain: domain) // tenant routing domain (appId/apiKey are inside the token)
.withApplicant(customerId: 'C_abc123', email: 'user@example.com')
.withEventType(WIDTHEventType.kyc) // optional; omit → user picks KYC/KYB in-SDK
.withForcedDayNightMode(WIDTHDayNightMode.night) // optional; omit → follows system
.withLanguage(WIDTHLanguage.zh) // optional; omit → English (never the device locale)
.withHandlers(
onStatusChanged: (newStatus, prevStatus) { /* terminal status change */ },
verificationHandler: (isApproved) { /* final approve / reject only */ },
)
.build();
final result = await sdk.launch(); // resolves when the native flow closes
switch (result.status) {
case WIDTHStatus.approved: // final decision: approved
case WIDTHStatus.finallyRejected: // final decision: rejected
case WIDTHStatus.pending: // under manual review
case WIDTHStatus.incomplete: // mid-flow exit / waiting; resumable
case WIDTHStatus.cancelled: // discarded; not resumable
case WIDTHStatus.failed: // see result.exception
}事件日志(可选)
传入
onEvent handler,可在你自己的管道(Crashlytics、DataDog
等)中接收 SDK 生命周期事件(INFO / WARN / ERROR);回调触发前已脱敏
PII(个人身份信息)。
.withHandlers(
onEvent: (event) {
// event.level / event.tag / event.message
},
)界面语言(可选)
withLanguage(WIDTHLanguage.zh) 把整个流程切成简体中文
— 包括 SDK 自身的文案,以及后端返回的
{en, zh} 动态内容。不传就是英文:原生 SDK
从不跟随设备语言,所以已有的集成不会受影响。
内置的第三方采集页面另有限制:证件扫描商只有在设备联网、且租户的集成开启了中文时才显示中文,否则仍是英文;证件阅读器只支持简体中文。
结果处理
launch() 总会完成;对 SDK 级别的失败不会抛出异常。
result.status |
何时 |
|---|---|
approved |
服务端通过 |
finallyRejected |
服务端拒绝 |
pending |
提交在带外进行人工审核 |
incomplete |
用户中途退出或决定仍在等待;用相同
customerId 可恢复
|
cancelled |
用户主动放弃验证;不可恢复 |
failed |
内部错误;见 result.exception
|
当为
.failed
时,result.exception(WIDTHException)带一个
type —
initialization、network、api、permission、workflow、unknown
之一 — 并保留原始 code(如 W-LIV-499)与
message。result.executionId
标识该次运行,便于支持排查。
API 参考
| 符号 | 用途 |
|---|---|
WIDTHMobileSDK.init(accessToken) |
入口,返回 builder |
WIDTHMobileSDKBuilder |
withCredentials / withApplicant /
withEventType / withForcedDayNightMode /
withLanguage / withHandlers /
build()
|
WIDTHMobileSDK.launch() |
呈现流程;以结果完成 |
WIDTHMobileSDKResult |
status / success /
exception /
executionId
|
WIDTHStatus / WIDTHException /
WIDTHExceptionType
|
状态 / 错误 |
WIDTHSDKEvent / WIDTHLogLevel |
事件日志 |
WIDTHEventType |
可选的 KYC / KYB 流程预选 |
WIDTHDayNightMode |
强制主题 |
WIDTHLanguage |
可选的界面语言(en 为默认值 /
zh)
|
pubspec.yaml 中的
ref 标签并执行
flutter pub get。每个插件版本都绑定了它验证过的原生 SDK
版本 — 不要手动覆盖原生依赖。