Onfido Smart Capture iOS SDK

GitHub CocoaPods Platform License SwiftPM Carthage

目录

概述

Onfido Smart Capture SDK 提供了一系列屏幕和功能,使应用程序能够实现用户身份验证流程。每个 SDK 都包含

所有 Onfido Smart Capture SDK 都使用 Onfido Studio 工作流程进行编排,可用平台之间的自定义差异很小。

Capture Document and face

环境以及使用 SDK 进行测试

存在两种环境来支持 Onfido SDK 集成

正在使用的环境由用于生成必要 SDK 令牌的 API 令牌确定。

上线

一旦您对集成感到满意并准备好上线,请联系 Onfido 的 客户支持以获取实时 API 令牌。您将必须用实时令牌替换代码中的沙盒令牌。

在上线之前,请检查您是否在您的 Onfido 仪表板中输入了正确的账单详细信息。

添加 SDK 依赖项

iOS SDK 支持

注意:iOS SDK 需要 CoreNFC 才能运行(无论您是否使用 NFC)。自 Xcode 12 以来,存在一个错误,模拟器中缺少 libnfshared.dylib。有关此问题的解决方案,请参阅 Stack Overflow

注意:如果您禁用 NFC 功能,Apple 可能会要求您提供视频以演示 NFC 用法,因为 NFC 相关代码是 SDK 二进制文件的一部分,无论运行时配置如何。在我们致力于永久解决此问题的同时,您可以随时联系 Onfido 的 客户支持以获取视频。

应用权限

SDK 使用用户的设备摄像头(用于文档和面部捕捉)和麦克风(用于视频和运动捕捉)。您需要在应用程序的 Info.plist 文件中包含以下键

<key>NSCameraUsageDescription</key>
<string>Required for document and face capture</string>
<key>NSMicrophoneUsageDescription</key>
<string>Required for video capture</string>

注意:所有键都是应用程序提交所必需的。

添加依赖项

使用 Swift Package Manager

SDK 可通过 Swift Package Manager 获得,您可以通过添加以下软件包存储库 URL 将其包含在您的项目中

Swift
dependencies: [
    .package(url: "https://github.com/onfido/onfido-ios-sdk.git", .branch("master"))
]

使用 CocoaPods

SDK 也可在 CocoaPods 上获得,您可以通过将以下内容添加到您的 Podfile 中将其包含在您的项目中

pod 'Onfido'

运行 pod install 以获取 SDK。

手动安装

SDK 可在 GitHub Releases 选项卡中找到,您可以在其中下载压缩框架。您可以在此处找到最新版本。

  1. 下载包含 Onfido.xcframework 的压缩 zip 文件
  2. 解压缩 zip 文件,然后将 Onfido.xcframework 工件移动到您的项目文件夹中
  3. 在 Xcode 中打开您的应用程序项目文件。然后在目标列表下选择您的应用程序目标
  4. 将位于您的项目中的 Onfido.xcframework 添加到您的 iOS 应用程序目标的 General 选项卡中的 Embedded binaries 部分

⚠️不要将 xcframework 作为资源添加到您的应用程序目标,因为只需要少量文件,xcode 会在构建期间自动获取这些文件。

非 Swift 应用程序

如果您的应用程序不是基于 Swift 的,那么您必须在您的项目中创建一个新的 Swift 文件。此文件是强制 Xcode 打包运行 Onfido iOS SDK 所需的 Swift 运行时库所必需的。

  1. 创建一个包含以下内容的 Swift 文件

    import Foundation
    import AVFoundation
    import CoreImage
    import UIKit
    import Vision
    
    func fixLibSwiftOnoneSupport() {
        // from https://stackoverflow.com/a/54511127/2982993
        print("Fixes dyld: Library not loaded: @rpath/libswiftSwiftOnoneSupport.dylib")
    }
  2. 在您的项目配置中将 Always Embed Swift Standard Libraries 设置为 Yes

初始化 SDK

⚠️以下 SDK 初始化文档适用于使用 Onfido Studio 编排的身份验证工作流程。对于手动定义和配置验证步骤的集成,请参阅下面的 高级流程自定义 部分。

iOS SDK 具有多种初始化和自定义选项,可为您的集成提供灵活性,同时保持易于集成。

定义工作流程

Onfido Studio 是用于创建高度可重用的身份验证工作流程以与 Onfido SDK 配合使用的平台。有关工作流程入门介绍,请参阅我们的 入门指南,或 Onfido Studio 产品指南

SDK 会话由会话特定的 workflow_run_id 编排,而 workflow_run_id 本身源自 workflow_id,即给定工作流程的唯一标识符。

有关如何生成 workflow_run_id 的详细信息,请参阅 Onfido API 参考中的 POST /workflow_runs/ 端点定义。

注意,在 SDK 的上下文中,workflow_run_id 属性称为 workflowRunId

申请人 ID 重用

在定义工作流程和创建身份验证时,我们强烈建议针对特定用户保存 applicant_id 以便潜在重用。这有助于跟踪用户,如果您希望对同一人运行多个身份验证,或者在用户返回并恢复验证流程的情况下。

SDK 身份验证

SDK 使用 SDK 令牌进行身份验证。当工作流程运行创建时,Onfido Studio 会在 API 返回的工作流程运行负载中生成并公开 SDK 令牌。

Studio 的 SDK 令牌只能与为其生成的特定工作流程运行一起使用,并且有效期为五周。

注意:您绝不能在应用程序的前端使用 API 令牌,因为恶意用户可能会在您的源代码中发现它们。您应该只在您的服务器上使用它们。

构建配置对象

要使用 SDK,您需要使用您生成的 SDK 令牌和工作流程运行 ID 获取客户端对象的实例。

Swift
let workflowConfiguration = WorkflowConfiguration(workflowRunId: "<WORKFLOW_RUN_ID>", sdkToken: "<YOUR_SDK_TOKEN>")

启动流程

Swift
let onfidoRun = OnfidoFlow(workflowConfiguration: orchestrationConfig)
customerViewController.present(try onfidoRun.run(), animated: true, completion: nil)
// listen for the result

NFC 捕捉

最近的护照、国民身份证和居留许可包含可以使用近场通信 (NFC) 访问的芯片。Onfido SDK 提供了一系列屏幕和功能来提取此信息,验证其真实性,并将生成的验证作为文档报告的一部分提供。

从 Onfido iOS SDK 的 29.1.0 版本开始,默认启用 NFC,并在文档和设备都支持 NFC 时提供给最终用户。

有关如何配置 NFC 以及支持的文档列表的更多信息,请参阅 NFC 文档报告指南。

先决条件

<key>NFCReaderUsageDescription</key>
<string>Required to read ePassports</string>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
  <string>12FC</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
  <string>A0000002471001</string>
  <string>A0000002472001</string>
  <string>00000000000000</string>
  <string>D2760000850101</string>
</array>

配置 NFC

要使用 Onfido Studio 配置 NFC,您可以使用工作流程构建器中的以下选项之一

要在代码中配置 NFC,请在使用上述选项配置 OnfidoConfig 时调用 withNFC() 函数(请参阅下面的 高级流程自定义 部分)。

⚠️当 NFC 在代码中配置为 required 时,与 Studio 不同,SDK 不会过滤掉不支持 NFC 的文档类型,为了最终用户的最佳体验,仅公开此处 列出的那些支持 NFC 的文档类型,或者最好使用 Studio

样式自定义

iOS SDK 支持自定义 SDK 流程中使用的颜色、字体和字符串。

UI 自定义

外观和颜色

要自定义 SDK 的外观,您可以将所需的 CSS 值传递给 WorkflowConfiguration 对象的根目录中的 Appearance 对象。

Swift
let appearance = Appearance()
appearance.primaryColor = <DESIRED_UI_COLOR_HERE>
appearance.primaryTitleColor = <DESIRED_UI_COLOR_HERE>
Objective-C
ONAppearance *appearance = [[ONAppearance alloc] init];
appearance.primaryColor = <DESIRED_UI_COLOR_HERE>;
appearance.primaryTitleColor = <DESIRED_UI_COLOR_HERE>;

有关可以在此属性中设置的支持的 UI 选项的详细信息,请参阅 SDK 自定义文档

深色主题

iOS SDK 支持深色主题自定义。默认情况下,用户的活动设备主题将自动应用于 Onfido SDK。但是,您可以选择退出运行时动态主题切换,而是在构建时静态设置主题,如下所示。在这种情况下,无论用户的设备主题如何,流程都将始终以选定的主题显示。

interfaceStyle 允许您分别通过 .dark.light 强制使用浅色或深色模式。默认情况下,它设置为 .unspecified,这将遵循系统的界面样式。

注意:之前的属性 supportDarkMode 现在已弃用。请改用 interfaceStyle

例如,要将界面样式设置为 .dark,您可以使用以下代码

Swift
let appearance = Appearance()
appearance.setUserInterfaceStyle(.dark)
Objective-C
ONAppearance *appearance = [ONAppearance new];
[appearance setUserInterfaceStyle:UIUserInterfaceStyleDark];

应用 Appearance 对象

要应用外观,您可以使用以下方法

Swift
let configBuilder = OnfidoConfig.builder()
configBuilder.withAppearance(appearance)
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withAppearance:appearance];

联合品牌

Onfido SDK 允许两种联合品牌选项,这些选项会影响 Onfido 屏幕底部 Onfido 徽标的显示。

文本联合品牌

Swift
let companyName = "MyCompany"
let enterpriseFeatures = EnterpriseFeatures.builder()
    .withCobrandingText(companyName)
    .build()
Objective-C
NSString *companyName = @"MyCompany";
ONEnterpriseFeaturesBuilder *enterpriseFeatures = [ONEnterpriseFeatures builder];
[enterpriseFeatures withCobrandingText: companyName];
[enterpriseFeatures build];

请注意:文本联合品牌必须由 Onfido 启用。请联系您的解决方案工程师或客户成功经理以激活此功能。

徽标联合品牌

Swift
let onfidoEnterpriseFeatures = EnterpriseFeatures.builder()
    .withCobrandingLogo(
        UIImage(named: "imageName_for_lightmode")!,
        cobrandingLogoDarkMode: UIImage(named: "imageName_for_darkmode")!
     )
    .build()
Objective-C
ONEnterpriseFeaturesBuilder *enterpriseFeatures = [ONEnterpriseFeatures builder];
[enterpriseFeatures withCobrandingLogo:
  [UIImage imageNamed:@"onfido-logo-white"] cobrandingLogoDarkMode:[UIImage imageNamed:@"onfido-logo-grey"]
];
[enterpriseFeatures build];

请注意:徽标联合品牌必须由 Onfido 启用。请联系您的解决方案工程师或客户成功经理以激活此功能。

将联合品牌添加到 OnfidoConfig

要应用联合品牌,请将企业功能对象添加到 OnfidoConfig

Swift
let configBuilder = OnfidoConfig.builder()
configBuilder.withEnterpriseFeatures(enterpriseFeatures)
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withEnterpriseFeatures: enterpriseFeatures];

语言本地化

Onfido SDK 支持并维护 40 多种语言的翻译。

SDK 中使用的字符串可以通过在您的应用程序中为所需语言提供 Localizable.strings 并在配置构建器上使用 withCustomLocalization() 方法配置流程来自定义。

Swift
- (void)withCustomLocalization {
    [self.configBuilder withCustomLocalization]; // will look for localizable strings in your Localizable.strings file
}

有关 Onfido 支持的语言列表,请参阅我们的 SDK 自定义文档

注意:如果未选择任何语言,SDK 将检测并使用最终用户的设备语言设置。如果设备语言不受支持,SDK 将默认为英语 (en_US)。

自定义语言

SDK 也可以以 Onfido 当前不支持的语言环境的自定义语言显示。您可以提供完整或部分翻译。对于任何没有翻译的键,将使用支持的语言默认值。

添加自定义翻译时,您必须添加 Localizable_EN.strings 文件中包含的整套键(参考)。

您可以根据需要命名包含翻译键的字符串文件,但文件名必须作为参数提供给 withCustomLocalization() 方法

此外,您可以指定从中读取字符串文件的捆绑包

注意:

要请求新的语言翻译,或提供有关提供的翻译的反馈或建议,您可以联系 Onfido 的 客户支持

完成会话

处理回调

当 Onfido SDK 会话结束时,可能会触发一系列回调函数。

有关用于用户分析和返回提交媒体的高级回调,请参阅本文档的 高级回调 部分。

要接收已完成工作流程的结果,您应该将回调传递给 OnfidoFlow 的实例。以下代码作为示例提供

Swift
onfidoRun.with(responseHandler: { (response: OnfidoResponse) in
    switch response {
        case .success:
        // User completed the flow

        case .cancel(let cancellationReason):
        // Flow cancelled by user
        print(cancellationReason)

        case .error(let error):
        // Error occurred
        print(error)

    }
},
    dismissFlowOnCompletion: true)
    // Dismiss the whole flow when the user completes it, and return back to the integrator view

属性 注释
.success 当工作流程中的所有交互式任务都已完成时触发的回调。成功后,如果您配置了 网络钩子,则会向您的后端发送通知,确认工作流程运行已完成。您无需使用后端创建检查,因为这由工作流程直接处理
.error(Error) 发生错误时触发的回调
.cancel 当用户过早退出工作流程时触发的回调。原因可能是 .userExit.consentDenied

错误处理

作为 OnfidoResponse.error(Error) 一部分返回的 Error 对象是 OnfidoFlowError 类型。它是一个枚举,具有多种情况,具体取决于错误类型。

switch response {
  case let OnfidoResponse.error(error):
    switch error {
      case OnfidoFlowError.cameraPermission:
        // This error is thrown if the user denies permission to the SDK during the flow
      case OnfidoFlowError.failedToWriteToDisk:
        // This error is thrown when the SDK tries to save capture to disk, maybe due to a lack of space
      case OnfidoFlowError.microphonePermission:
        // This error is thrown when the user denies permission for microphone usage by the app during the flow
      case OnfidoFlowError.upload(let OnfidoApiError):
        // This error is thrown when the SDK receives an error from an API call
        // See https://documentation.onfido.com/api/latest#errors for more information
      case OnfidoFlowError.exception(withError: let error, withMessage: let message):
        // This error is thrown when an unexpected error occurs
        // Please email [Customer support](mailto:supportonfido.com) when this happens
      case OnfidoFlowError.versionInsufficient:
        // This error is thrown when you are using an older version of the iOS SDK and trying
        // to access a new functionality from workflow. You can fix this by updating the SDK
      case OnfidoFlowError.studioTaskAbandoned:
        // This error is thrown when the workflow run (instance) is no longer available either due to it expiring or being completed already
      case OnfidoFlowError.studioTaskError:
        // This error is thrown when the workflow run can no longer be executed and returns a generic error
      case OnfidoFlowError.invalidImageData:
        // This error is thrown when the SDK is unable to compress the image captured by the user before uploading it    

      default: // necessary because of Swift
    }
}

生成验证报告

虽然 SDK 负责捕获和上传用户的媒体和数据,但身份验证报告本身是基于使用 Onfido Studio 创建的工作流程生成的。

有关使用 Onfido Studio 和我们的 SDK 创建身份验证的分步演练,请参阅我们的 快速入门指南

如果您的应用程序使用本文档的 高级自定义 部分中定义的选项初始化 Onfido iOS SDK,您可以手动使用 Onfido API 创建检查检索报告结果。您还可以配置 网络钩子,以便在生成报告结果时异步收到通知。

高级流程自定义

本节关于“高级自定义”是指在不使用 Onfido Studio 的情况下初始化 Onfido iOS SDK 的过程。此过程需要手动定义验证步骤及其配置。

这些流程步骤参数与 workflowRunId 互斥,需要使用替代方法来实例化客户端并启动流程。

注意不建议使用此初始化过程,因为大多数新功能都专门为 Studio 工作流程发布。

手动 SDK 身份验证

SDK 使用 SDK 令牌进行身份验证。由于每个 SDK 令牌都必须特定于给定的申请人和会话,因此每次初始化 Onfido iOS SDK 时都必须生成新令牌。

参数 注释
applicant_id 必需
指定 SDK 实例的申请人。
application_id 必需
在开发期间设置的应用程序 ID(对于 iOS 为“应用程序捆绑 ID”)。对于 iOS,这通常采用 com.your-company.app-name 形式。请确保使用有效的 application_id,否则您将收到 401 错误。

有关如何手动生成 SDK 令牌的详细信息,请参阅 Onfido API 参考中的 POST /sdk_token/ 定义。

注意:您绝不能在应用程序的前端使用 API 令牌,因为恶意用户可能会在您的源代码中发现它们。您应该只在您的服务器上使用它们。

使用 expireHandler 管理 SDK 令牌过期

手动生成 SDK 令牌时,重要的是要注意它们会在 90 分钟后过期。

考虑到这一点,我们建议您在 SDK 令牌配置函数中使用可选的 expireHandler 参数,以便在 SDK 令牌过期时生成并传递新 SDK 令牌。这确保 SDK 即使在 SDK 令牌过期后也能继续其流程。

例如

Swift
func getSDKToken(_ completion: @escaping (String) -> Void) {
    // Your network request logic to retrieve SDK token goes here
    completion(myNewSDKtoken)
}

let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN>", expireHandler: getSDKToken)
Objective-C
-(void) getSDKToken: (void(^)(NSString *)) handler {
   // <Your network request logic to retrieve SDK token goes here>
   handler(sdkToken);
}

ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN" expireHandler:^(void (^ handler)(NSString *  expireHandler)) {
    [self getSDKToken:handler];
}];

创建 SDK 配置

一旦您添加了 SDK 依赖项,并且您拥有申请人 ID,您就可以手动配置 SDK 流程步骤

Swift
let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN>")
    .withWelcomeStep()
    .withDocumentStep()
    .withProofOfAddressStep()
    .withFaceStep(ofVariant: .photo(withConfiguration: nil))
    .build()

let onfidoFlow = OnfidoFlow(withConfiguration: config)
    .with(responseHandler: { results in
        // Callback when flow ends
    })
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];

[configBuilder withSdkToken:@"YOUR_SDK_TOKEN"];
[configBuilder withWelcomeStep];
[configBuilder withDocumentStep];
[configBuilder withProofOfAddressStep];

NSError *variantConfigError = NULL;
Builder *variantBuilder = [ONFaceStepVariantConfig builder];
[variantBuilder withPhotoCaptureWithConfig: NULL];
[configBuilder withFaceStepOfVariant: [variantBuilder buildAndReturnError: &variantConfigError]];

if (variantConfigError == NULL) {
  NSError *configError = NULL;
  ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];

  if (configError == NULL) {
      ONFlow *onFlow = [[ONFlow alloc] initWithFlowConfiguration:config];
      [onFlow withResponseHandler:^(ONFlowResponse *response) {
          // Callback when flow ends
      }];
  }
}

启动流程

Swift
try onfidoRun.run(from: yourViewController, animated: true)
Objective-C
NSError *runError = NULL;
[onFlow runFrom:yourViewController animated:YES error:&runError completion:nil];

if (runError != NULL) {
    // do fallback logic
}

高级 UI 自定义

外观和颜色

要自定义 SDK 的外观,您可以将所需的 CSS 值传递给 OnfidoConfig.builder() 对象的根目录中的 Appearance 对象。

Swift
let appearance = Appearance()
appearance.primaryColor = <DESIRED_UI_COLOR_HERE>
appearance.primaryTitleColor = <DESIRED_UI_COLOR_HERE>
Objective-C
ONAppearance *appearance = [[ONAppearance alloc] init];
appearance.primaryColor = <DESIRED_UI_COLOR_HERE>;
appearance.primaryTitleColor = <DESIRED_UI_COLOR_HERE>;

要应用外观,您可以使用以下方法

Swift
let configBuilder = OnfidoConfig.builder()
configBuilder.withAppearance(appearance)
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withAppearance:appearance];

有关可以在此属性中设置的支持的 UI 选项的详细信息,请参阅 SDK 自定义文档

流程自定义

您可以通过向 SDK 流程添加步骤来自定义 SDK 的流程。

可能的步骤包括

步骤 描述
withWelcomeStep 向用户显示的欢迎屏幕,其中包含初步说明。自定义选项包括修改文本元素和向用户显示的说明。
withDocumentStep 控制通过照片或上传用户文档进行捕捉的一组屏幕。许多自定义选项可用于定义呈现给用户的文档列表和整体捕捉体验。
withFaceStep 控制捕捉用户自拍、视频或运动捕捉的一组屏幕。自定义选项允许选择捕捉变体。
withProofOfAddressStep 用户在其中选择签发国家/地区和文档类型以验证其地址的屏幕。

欢迎步骤

此步骤是 SDK 的介绍屏幕。它介绍了流程并为用户准备了他们需要完成的步骤。

虽然此屏幕是可选的,但如果您已经有自己的身份验证欢迎屏幕,我们才建议删除它。

您可以通过在 Swift 中调用 configBuilder.withWelcomeStep() 或在 Objective-C 中调用 [configBuilder withWelcomeStep] 来显示欢迎屏幕。

Swift
let config = try OnfidoConfig.builder()
    .withWelcomeStep()
    ...
    .build()
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];
...
[configBuilder withWelcomeStep];

NSError *configError = NULL;
ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];

if (configError) {
    // Handle config build error
} else {
    // use config
}

同意步骤

此步骤包含当您向美国用户提供服务时所需的同意语言,以及指向 Onfido 政策和使用条款的链接。对于使用location 参数值为美国的申请人,同意收集是强制性的

用户必须单击“接受”才能跳过此步骤并继续流程。内容仅提供英文版本,且不可翻译。

注意:此步骤不会自动通知 Onfido 用户已同意

如果您选择禁用 Onfido 的 SDK 同意步骤,您仍然必须在您的用户开始与 Onfido SDK 交互之前,将所需的同意语言和指向 Onfido 政策和使用条款的链接纳入您自己的应用程序流程中。

有关此步骤以及如何收集用户同意的更多信息,请访问 Onfido 隐私声明和同意

文档步骤

在文档捕捉步骤中,最终用户可以在捕捉之前选择签发国家/地区和文档类型。在极少数情况下,还可能会询问最终用户是否拥有其文档的卡片或纸质版本。

此信息用于优化捕捉体验,并告知最终用户他们允许使用哪些文档。

此选择屏幕是动态的,当最终用户不需要指示将捕捉哪个文档时,将自动隐藏。

默认情况下,国家/地区选择将根据最终用户的主要 SIM 卡预先填充,但最终用户可以在允许的情况下从列表中选择另一个国家/地区。当没有 SIM 卡时,选择将默认为空。

The default country selection The default country selection

您可以通过以下三种方式之一指定文档捕捉步骤的允许签发国家/地区和文档类型

通过仪表板选择国家/地区和文档类型

使用您的仪表板配置签发国家/地区和文档类型选择步骤是推荐的自定义方法(从 iOS SDK 28.0.0 版本和 Android SDK 16.0.0 版本开始提供),因为此配置也适用于您的文档报告。

我们将很快推出基于仪表板的允许文档配置。在此期间,请联系 support@onfido.com 或您的客户支持经理,以请求访问此功能。

The Supported Documents tab in the Dashboard

请注意以下 SDK 行为

国家/地区和文档类型选择 - SDK 集成代码

如果您想使用您自己的自定义文档选择 UI 而不是显示 Onfido 文档选择屏幕,您需要在 SDK 初始化期间指定文档详细信息。

当指定单个文档类型时,将自动跳过文档选择屏幕。

SDK 将接受以下内容

注意:您可能仍然希望配置基于仪表板的方法,以确保文档报告也拒绝最终用户根据您的指导上传的任何文档。

用户可见的文档类型列表可以使用此选项显示或隐藏。每种文档类型都有自己的配置类。配置文档类型时,您可以选择性地传递配置对象以及文档类型。

支持以下文档类型

文档类型 配置类 可配置属性
护照 PassportConfiguration - 国家/地区
驾驶执照 DrivingLicenceConfiguration - 国家/地区
- 文档格式
国民身份证 NationalIdentityConfiguration - 国家/地区
- 文档格式
居留许可 ResidencePermitConfiguration - 国家/地区
签证 VisaConfiguration - 国家/地区
工作许可证 WorkPermitConfiguration - 国家/地区
通用 GenericDocumentConfiguration - 标题
- 副标题
- 国家/地区
- 页数

注意Generic 文档类型不为所需的文档类型提供优化的捕捉体验。

注意:如果仅指定一种文档类型,用户将不会看到选择屏幕,并将直接进入捕捉屏幕。

国家/地区配置允许您指定文档的原产国家/地区。这是可选的,但建议使用。这可以启用 SDK 可能针对此国家/地区签发的特定文档进行的任何优化。

您需要将相应的 ISO 3166-1 alpha-3 国家/地区代码传递给 SDK。

注意:您可以为除 passport 之外的所有文档类型指定国家/地区。这是因为护照在全球范围内具有相同的格式,因此 SDK 不需要此附加信息。

注意::如果提供了无效的国家/地区代码,SDK 将抛出 OnfidoConfigError.invalidCountryCode (ONFlowConfigErrorInvalidCountryCode) 错误。

例如,仅捕捉英国驾驶执照

Swift
let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withDocumentStep(ofType: .drivingLicence(config: DrivingLicenceConfiguration(country: "GBR")))
    .build()
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];

NSError *documentConfigError = NULL;
DocumentConfigBuilder *documentConfigBuilder = [ONDocumentTypeConfig builder];
[documentConfigBuilder withDrivingLicenceWithConfig:[[DrivingLicenceConfiguration alloc] initWithCountry: @"GBR"]];
ONDocumentTypeConfig *documentTypeConfig = [documentConfigBuilder buildAndReturnError: documentConfigError];

if (documentConfigError) {
  // Handle variant config error
} else {
  NSError *configError = NULL;
  [configBuilder withDocumentStepOfType:documentTypeConfig];
  ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];
}

文档格式是可选的,仅适用于法国驾驶执照意大利国民身份证南非国民身份证。这默认为 Card,表示这些文档的现代形式。如果最终用户表示他们拥有这些文档之一的旧纸质版本,请使用 Folded 以确保优化的捕捉体验。

如果配置了 Folded,SDK 将在文档捕捉期间显示特定的模板叠加层。

以下是每种文档类型支持的文档格式

文档类型/文档格式 卡片 折叠
驾驶执照 所有国家/地区 仅限法国(国家/地区代码“FRA”)
国民身份证 所有国家/地区 意大利(国家/地区代码“ITA”)
南非(国家/地区代码“ZAF”)
文档类型/文档格式
护照 不可配置
居留许可 不可配置
签证 不可配置
工作许可证 不可配置
通用 不可配置

注意:如果您使用不支持的文档格式配置 SDK,SDK 将在运行时抛出 OnfidoConfigError.invalidDocumentFormatAndCountryCombination (Objective-C 中的 ONFlowConfigErrorInvalidDocumentFormatAndCountryCombination) 错误。

例如,对于折叠的意大利国民身份证

Swift
let config = try OnfidoConfig.builder()
    .withSDKToken("YOUR_SDK_TOKEN_HERE")
    .withDocumentStep(ofType: .nationalIdentityCard(config: NationalIdentityConfiguration(documentFormat: .folded, country: "ITA")))
    .build()
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];

NSError *documentConfigError = NULL;
DocumentConfigBuilder *documentConfigBuilder = [ONDocumentTypeConfig builder];
[documentConfigBuilder withNationalIdentityCardWithConfig:[[NationalIdentityConfiguration alloc] initWithDocumentFormat:DocumentFormatFolded country: @"ITA"]];
ONDocumentTypeConfig *documentTypeConfig = [documentConfigBuilder buildAndReturnError: documentConfigError];

if (documentConfigError) {
  // Handle variant config error
} else {
  NSError *configError = NULL;
  [configBuilder withDocumentStepOfType:documentTypeConfig];
  ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];
}

您还可以自定义屏幕以仅显示有限的文档类型列表,使用配置函数指定您想要显示的文档类型。

目前,您只能在列表中包含 passportidentityCarddrivingLicenceresidencePermit

例如,仅显示 passportdrivingLicence 文档类型

Swift
let config = try OnfidoConfig.builder()
    .withDocumentStep(ofSelectableTypes: [.passport, .drivingLicence])
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withDocumentStepWithSelectableDocumentTypes: @[@(SelectableDocumentTypePassport), @(SelectableDocumentTypeDrivingLicence)]];

这对于在 Onfido 平台上支持但 SDK 中尚不存在的文档运行文档报告,或者更改向用户显示的文档类型的默认名称或用户将被要求捕获的默认侧面/页面数量非常有用。

“通用”文档类型支持有限的设备端图像质量检查。在可用时使用标准文档类型以获得更佳的捕获体验。

自定义文档包含以下信息

建议在初始化 SDK 时提供预先翻译的标题和副标题字符串,因为这些自定义字符串不会在内部进行翻译。

The Selection Screen with Generic Documents

以下是添加自定义文档的几个选项

Swift

let config = try! OnfidoConfig.builder()
    .withSDKToken("YOUR_SDK_TOKEN_HERE")
    .withGenericDocuments(additionalTypes: [
        .generic(config: GenericDocumentConfiguration(title: "Tax ID", country: "PHL", pages: .frontAndBack))
        .generic(config: GenericDocumentConfiguration(title: "Voter's ID", subtitle: "your voting ID", country: "PHL", pages: .single))
    ])
    .build()

Objective-C

ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];

NSError *documentConfigError = NULL;
DocumentConfigBuilder * documentConfigBuilder = [ONDocumentTypeConfig builder];
[documentConfigBuilder withGenericWithConfig:[[GenericDocumentConfiguration alloc] initWithTitle: @"Tax ID" subtitle: nil country: @"PHL" pages: ONDocumentPagesFrontAndBack]];
[documentConfigBuilder withGenericWithConfig:[[GenericDocumentConfiguration alloc] initWithTitle: @"Voter's ID" subtitle: @"your voting ID" country: @"PHL" pages: ONDocumentPagesSingle]];
ONDocumentTypeConfig *documentTypeConfig = [documentConfigBuilder buildAndReturnError: documentConfigError];

if (documentConfigError) {
  // Handle variant config error
} else {
  NSError *configError = NULL;
  [configBuilder withGenericDocumentsWithAdditionalTypes:documentTypeConfig];
  ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];
}

Swift

let config = try! OnfidoConfig.builder()
    .withSDKToken("YOUR_SDK_TOKEN_HERE")
    .withDocumentStep(ofSelectableTypes: [.passport, .drivingLicence])
    .withGenericDocuments(additionalTypes: [
        .generic(config: GenericDocumentConfiguration(title: "Tax ID", country: "PHL", pages: .frontAndBack))
        .generic(config: GenericDocumentConfiguration(title: "Voter's ID", subtitle: "your voting ID", country: "PHL", pages: .single))
    ])
    .build()

Objective-C

ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];

NSError *documentConfigError = NULL;
DocumentConfigBuilder *documentConfigBuilder = [ONDocumentTypeConfig builder];
[documentConfigBuilder withDocumentStepWithSelectableDocumentTypes: @[@(SelectableDocumentTypePassport), @(SelectableDocumentTypeDrivingLicence)]];
[documentConfigBuilder withGenericWithConfig:[[GenericDocumentConfiguration alloc] initWithTitle: @"Tax ID" subtitle: nil country: @"PHL" pages: ONDocumentPagesFrontAndBack]];
[documentConfigBuilder withGenericWithConfig:[[GenericDocumentConfiguration alloc] initWithTitle: @"Voter's ID" subtitle: @"your voting ID" country: @"PHL" pages: ONDocumentPagesSingle]];
ONDocumentTypeConfig *documentTypeConfig = [documentConfigBuilder buildAndReturnError: documentConfigError];

if (documentConfigError) {
  // Handle variant config error
} else {
  NSError *configError = NULL;
  [configBuilder withGenericDocumentsWithAdditionalTypes:documentTypeConfig];
  ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];
}

Swift

let config = try! OnfidoConfig.builder()
    .withSDKToken("YOUR_SDK_TOKEN_HERE")
    .withDocumentStep(ofType:.generic(config:
        GenericDocumentConfiguration(title: "Voter's ID", subtitle: "your voting ID", country: "PHL", pages: .single))
    )
    .build()

Objective-C

ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];

NSError *documentConfigError = NULL;
DocumentConfigBuilder *documentConfigBuilder = [ONDocumentTypeConfig builder];
[documentConfigBuilder withGenericWithConfig:[[GenericDocumentConfiguration alloc] initWithTitle: @"Tax ID" subtitle: nil country: @"PHL" pages: ONDocumentPagesSingle]];
ONDocumentTypeConfig *documentTypeConfig = [documentConfigBuilder buildAndReturnError: documentConfigError];

if (documentConfigError) {
  // Handle variant config error
} else {
  NSError *configError = NULL;
  [configBuilder withDocumentStepOfType:documentTypeConfig];
  ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];
}

注意

人脸步骤

在人脸步骤中,用户可以使用其设备的前置摄像头捕获其面部的实时照片(照片)、实时视频(视频)或使用 Motion 产品进行动作捕捉(Motion)。

Objective-C

对于 Objective-C 接口,您应该使用 ONFaceStepVariantConfig,如下所示。

配置 实时照片

NSError * error;
Builder * variantBuilder = [ONFaceStepVariantConfig builder];
[variantBuilder withPhotoCaptureWithConfig: [[PhotoStepConfiguration alloc] initWithShowSelfieIntroScreen: YES]]];
[configBuilder withFaceStepOfVariant: [variantBuilder buildAndReturnError: &error]];

配置 实时视频

NSError * error;
Builder * variantBuilder = [ONFaceStepVariantConfig builder];
[variantBuilder withVideoCaptureWithConfig:
   [[VideoStepConfiguration alloc] initWithShowIntroVideo: YES manualLivenessCapture: NO]];
[configBuilder withFaceStepOfVariant: [variantBuilder buildAndReturnError: &error]];

配置 Motion

NSError * error;
Builder * variantBuilder = [ONFaceStepVariantConfig builder];
[variantBuilder withMotionWithConfig: NULL];
[configBuilder withFaceStepOfVariant: [variantBuilder buildAndReturnError: &error]];

配置 带有录音的 Motion

NSError * error;
Builder * variantBuilder = [ONFaceStepVariantConfig builder];
[variantBuilder withMotionWithConfig: [[MotionStepConfiguration alloc] initWithRecordAudio: YES]];
[configBuilder withFaceStepOfVariant: [variantBuilder buildAndReturnError: &error]];

配置 不带介绍屏幕的 Motion

介绍屏幕旨在为最终用户提供关于他们需要采取哪些操作以及为什么这些操作是必要的清晰背景。删除此屏幕可能会导致困惑和更高的放弃率,因为用户可能不理解对他们的要求并选择放弃该过程。至关重要的是,尤其是在入职期间,如果删除介绍屏幕,则需要提供类似程度的指导,以确保用户仍然充分了解情况。但是,当重新验证已经熟悉流程的回头用户时,跳过介绍屏幕可以通过简化流程并消除不必要的步骤来增强用户体验。

NSError * error;
Builder * variantBuilder = [ONFaceStepVariantConfig builder];
[variantBuilder withMotionWithConfig: [[MotionStepConfiguration alloc] initWithShowIntro: NO]];
[configBuilder withFaceStepOfVariant: [variantBuilder buildAndReturnError: &error]];
Swift

人脸步骤对于 Swift 接口 有 3 种变体

配置 实时照片

let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withWelcomeStep()
    .withDocumentStep()
    .withFaceStep(ofVariant: .photo(withConfiguration: PhotoStepConfiguration(showSelfieIntroScreen: true)))
    .build()

配置 实时视频

let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withWelcomeStep()
    .withDocumentStep()
    .withFaceStep(ofVariant: .video(withConfiguration: VideoStepConfiguration(showIntroVideo: true, manualLivenessCapture: false)))
    .build()

配置 Motion

let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withWelcomeStep()
    .withDocumentStep()
    .withFaceStep(ofVariant: .motion(withConfiguration: nil))
    .build()

配置 带有录音的 Motion

let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withWelcomeStep()
    .withDocumentStep()
    .withFaceStep(ofVariant: .motion(withConfiguration: MotionStepConfiguration(recordAudio: true)))
    .build()

配置 不带介绍屏幕的 Motion

介绍屏幕旨在为最终用户提供关于他们需要采取哪些操作以及为什么这些操作是必要的清晰背景。删除此屏幕可能会导致困惑和更高的放弃率,因为用户可能不理解对他们的要求并选择放弃该过程。至关重要的是,尤其是在入职期间,如果删除介绍屏幕,则需要提供类似程度的指导,以确保用户仍然充分了解情况。但是,当重新验证已经熟悉流程的回头用户时,跳过介绍屏幕可以通过简化流程并消除不必要的步骤来增强用户体验。

let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withWelcomeStep()
    .withDocumentStep()
    .withFaceStep(ofVariant: .motion(withConfiguration: MotionStepConfiguration(showIntro: false)))
    .build()

地址证明步骤

在地址证明步骤中,用户选择签发国家/地区和证明其地址的文档类型,然后再使用其设备摄像头捕获文档或上传文档。

Swift
let config = try OnfidoConfig.builder()
    .withSDKToken("<YOUR_SDK_TOKEN_HERE>")
    .withProofOfAddressStep()
    .build()
Objective-C
ONFlowConfigBuilder *configBuilder = [ONFlowConfig builder];
[configBuilder withSdkToken:@"YOUR_SDK_TOKEN_HERE"];
[configBuilder withProofOfAddressStep];

NSError *configError = NULL;
ONFlowConfig *config = [configBuilder buildAndReturnError:&configError];

if (configError) {
    // Handle config build error
} else {
    // use config
}

高级回调

处理回调

Swift

要从流程接收结果,您应该将回调传递给 OnfidoFlow 的实例。

传递给回调的结果对象可能包含以下属性

let responseHandler: (OnfidoResponse) -> Void = { response in
    switch response {
    case .error(let error):
    case .success(let results):
    case .cancel(let reason):
    }
}
属性 注释
.success([OnfidoResult]) 用户已完成流程。您现在可以在您的后端服务器上创建一个检查。
.error(Error) 错误发生时触发的回调。
.cancel 流程被用户取消。原因可能是 .userExit(当用户点击第一个屏幕上的后退按钮时)或 .deniedConsent(当用户在 同意屏幕 上拒绝同意时)或 .requiredNFCFlowNotCompleted(当需要 NFC 步骤且用户未完成时)。
Objective-C

要从流程接收结果,您应该将回调传递给 ONFlow 的实例。

ONFlowResponse 的实例被传递回回调,带有 3 个属性

(^responseHandlerBlock)(ONFlowResponse *response) {
    if (response.userCanceled) {
    } else if (response.results) {
    } else if (response.error) {
    }
}
属性 注释
results 用户已完成流程。您现在可以在您的后端服务器上创建一个检查。
error 错误发生时触发的回调。
userCanceled 流程被用户取消。您可以使用 response.userCanceled.reason 检查用户取消的原因。当 userCanceled 为 false 时,将设置 resultserror 属性。

成功处理

成功是指用户已到达流程的终点。

Swift

[OnfidoResult] 是一个包含多个结果的列表。这些结果是不同的枚举值,每个值都有其自己的关联值(也称为有效负载)。此枚举 OnfidoResult 可以具有以下值

  1. OnfidoResult.documentOnfidoResult.face:如果您想以某种方式操作或预览捕获的内容,其有效负载是相关的。

捕获结果有效负载

您无需检查文档和人脸捕获的结果,因为 SDK 会处理文件上传。但是,如果您想查看更多信息,您可以访问结果对象。

文档捕获示例

let document: Optional<OnfidoResult> = results.first { result in
    if case OnfidoResult.document = result { return true }
    return false
}

if let document,
   case OnfidoResult.document(let documentResult) = document {
    print(document.front.id)
}

要访问人脸捕获的结果对象,请输入 case 作为 OnfidoResult.face

Objective-C

[ONFlowResult] 是一个包含多个结果的列表。结果是 ONFlowResult 的实例,包含 2 个属性

捕获结果有效负载

您无需检查文档和人脸捕获的结果,因为 SDK 会处理文件上传。但是,如果您想查看更多信息,您可以访问结果对象。

文档捕获示例

NSPredicate *documentResultPredicate = [NSPredicate predicateWithBlock:^BOOL(id flowResult, NSDictionary *bindings) {
    if (((ONFlowResult *)flowResult).type == ONFlowResultTypeDocument) {
        return YES;
    } else {
        return NO;
    }
}];
NSArray *flowWithDocumentResults = [results filteredArrayUsingPredicate:documentResultPredicate];

if (flowWithDocumentResults.count > 0) {
    ONDocumentResult *documentResult = ((ONFlowResult *)flowWithDocumentResults[0]).result;
    NSLog(@"%@", documentResult.front.id);
}

具有 FlowStep.documentFlowStep.faceFlowStep.proofOfAddress 的流程返回的实例示例

Document:
        Front: DocumentSideResult(id=document_id, side=FRONT, type=DRIVING_LICENCE, issuingCounfry=GBR)
        Back: DocumentSideResult(id=document_id, side=BACK, type=DRIVING_LICENCE, issuingCounfry=GBR)
        Type: DRIVING_LICENCE

Face:
        Face(id=face_id, variant=PHOTO)

Proof of address:
        ProofOfAddress(type=UTILITY_BILL, front=(id=front_side_id, type=(optional)), back=(id=back_side_id, type=(optional)))

要访问人脸捕获的结果对象,请将类型更改为 ONFlowResultTypeFace

错误处理

Swift

响应处理程序错误

作为 OnfidoResponse.error(Error) 一部分返回的 Error 对象是 OnfidoFlowError 类型。它是一个枚举,具有多种情况,具体取决于错误类型。

switch response {
case let OnfidoResponse.error(error):
    switch error {
    case OnfidoFlowError.cameraPermission:
        // This error is thrown if the user denies permission to the SDK during the flow
    case OnfidoFlowError.microphonePermission:
        // This error is thrown when the user denies permission for microphone usage by the app during the flow
    case OnfidoFlowError.failedToWriteToDisk:
        // This error is thrown when the SDK tries to save capture to disk, maybe due to a lack of space
    case OnfidoFlowError.upload(let OnfidoApiError):
        // This error is thrown when the SDK receives an error from an API call, see [https://documentation.onfido.com/api/latest#errors](https://documentation.onfido.com/api/latest#errors) for more information
    case OnfidoFlowError.exception(withError: let error, withMessage: let message):
        // This error is thrown when an unexpected error occurs, please contact [support](mailto:support@onfido.com) when this happens
    case OnfidoFlowError.invalidImageData:
        // This error is thrown when the SDK tries to save capture to disk, but the image failed to compress to JPEG data
    case OnfidoFlowError.versionInsufficient:
        // This error is thrown when the workflow version is insufficient
    default: // necessary because swift
    }
}

注意:并非所有错误都会传递给 OnfidoResponse.error运行时异常配置错误 将作为异常返回。

运行时异常

当初始化 SDK 时,可能会出现异常。

您可以使用 do/catch 在 Swift 中处理运行时异常,如下所示

do {
    try onfidoFlow.run(from: yourViewController, animated: true)
} catch let error {
    switch error {
    case OnfidoFlowError.cameraPermission:
        // do something about it here
    case OnfidoFlowError.microphonePermission:
        // do something about it here
    default:
        // should not happen, so if it does, log it and let us know
    }
}

配置错误

配置 Onfido iOS SDK 时,您必须提供以下内容

否则,在 OnfidoConfig.Builder 实例上调用 build() 函数时,您可能会遇到以下错误

错误 注释
OnfidoConfigError.missingSDKToken 当未提供令牌或令牌为空字符串时。
OnfidoConfigError.invalidSDKToken 当提供无效令牌时。
OnfidoConfigError.missingSteps 当未提供步骤时。
OnfidoConfigError.invalidDocumentFormatAndCountryCombination 当它是为提供的指定国家/地区提供的不受支持的文档格式时。请参阅 文档类型配置 以检查受支持的组合。
OnfidoConfigError.invalidCountryCode 当提供无效国家/地区代码时。
Objective-C

响应处理程序错误

ONFlowResponseerror 属性的类型为 NSError

您可以通过将 NSError 实例的 code 属性与 ONFlowError 进行比较来识别错误,例如 response.code == ONFlowErrorCameraPermission。您还可以打印或记录 NSError 实例的 userInfo 属性。

ONFlowResponseerror 属性中包含的 NSError 可以按如下方式处理

switch (error.code) {
case ONFlowErrorCameraPermission:
    // Occurs if the user denies permission to the SDK during the flow
    break;
case ONFlowErrorMicrophonePermission:
    // Occurs when the user denies permission for microphone usage by the app during the flow
    break;
case ONFlowErrorFailedToWriteToDisk:
    // Occurs when the SDK tries to save capture to disk, maybe due to a lack of space
    break;
case ONFlowErrorUpload:
    // Occurs when the SDK receives an error from an API call, see [https://documentation.onfido.com/api/latest#errors](https://documentation.onfido.com/api/latest#errors) for more information
    // you can find out more by printing or logging userInfo from error
    break;
case ONFlowErrorException:
    // Returned when an unexpected error occurs, please contact Onfido's [Customer Support](mailto:support@onfido.com) when this happens
    break;
case ONFlowErrorInvalidImageData:
    // Occurs when the SDK tries to save capture to disk, but the image failed to compress to JPEG data
    break;
case ONFlowErrorVersionInsufficient:
    // Occurs when the workflow version is insufficient
    break;
}

注意:并非所有作为 ONFlowError 一部分的错误都会传递到响应处理程序块。运行时异常配置错误 将作为异常返回。

运行时异常

您可以按如下所示处理运行时异常

NSError *runError = NULL;
[onFlow runFrom:yourViewController animated:YES error:&runError completion:nil]; //`yourViewController` should be your view controller

if (runError) {
    switch (runError.code) {
        case ONFlowErrorCameraPermission:
            // do something about it here
            break;
        case ONFlowErrorMicrophonePermission:
            // do something about it here
            break;
        default:
            // do something about it here
            break;
    }
}

配置错误

配置 Onfido iOS SDK 时,您必须提供以下内容

否则,在 ONFlowConfigBuilder 上调用 build() 函数时,您可能会遇到以下错误

错误 注释
ONFlowConfigErrorMissingToken 当未提供令牌或令牌为空字符串时。
ONFlowConfigErrorMissingApplicant 当未提供申请人实例时。
ONFlowConfigErrorMissingSteps 当未提供步骤时。
ONFlowConfigErrorMultipleTokenTypes 当同时提供 SDK 令牌和移动令牌时。
ONFlowConfigErrorApplicantProvidedWithSDKToken 当同时提供 SDK 令牌和申请人时。
ONFlowConfigErrorInvalidDocumentFormatAndCountryCombination 当它是为提供的指定国家/地区提供的不受支持的文档格式时。请参阅 文档类型配置 以检查受支持的组合。
ONFlowConfigErrorInvalidCountryCode 当提供无效国家/地区代码时。

自定义媒体回调

必须为您的帐户启用以下功能才能使用它们。有关更多信息,请联系您的 Onfido 解决方案工程师或客户成功经理。

简介

Onfido 提供了与我们的 Smart Capture SDK 集成的可能性,而无需仅通过 Onfido API 使用此数据。媒体回调使您能够在最终用户提交其捕获的媒体后控制 SDK 收集的最终用户数据。因此,您可以利用 Onfido 先进的设备端技术,包括图像质量验证,同时仍然能够直接处理最终用户的数据。这解锁了额外的用例,包括需要这种额外灵活性的合规性要求和多供应商配置。

必须为您的帐户启用此功能。 请联系您的 Onfido 解决方案工程师或客户成功经理。

实施

要使用此功能,请使用 .withMediaCallback 并为文档提供 MediaDocumentResult 的回调,为实时照片和实时视频提供 MediaFile 的回调。

Swift
final class SwiftDynamicFrameworkOnfidoRunner: OnfidoRunner, MediaCallback {
    func onMediaCaptured(result: MediaResult) {
        switch result {
        case let documentResult as MediaDocumentResult:
            // Your callback code here
        case let selfieResult as SelfieResult:
            // Your callback code here
        case let livenessResult as LivenessResult:
            // Your callback code here
        default:
            break
        }
    }

    init() {
        ...
        configBuilder.withMediaCallback(mediaCallback: self)
    }
}

用户数据

回调返回一个对象,其中包括 SDK 通常直接发送到 Onfido 的信息。当最终用户通过 SDK 的用户界面确认提交其图像时,将调用回调。

注意: 目前,最终用户数据仍将自动发送到 Onfido 后端,但您无需使用 Onfido 来处理此数据。

回调返回 3 个可能的对象

  1. 对于文档,回调返回 MediaDocumentResult 对象
class MediaDocumentResult {
    let metadata: DocumentMetadata
    let file: MediaFile
}

DocumentMetadata 对象包含捕获文档的元数据

class DocumentMetadata {
    let side: String
    let type: String
    let issuingCountry: String?
}

注意: issuingCountry 是可选的,基于最终用户的选择,并且可以为 null

注意: 如果使用 NFC 扫描文档,则回调将在 file 中返回护照照片,但没有其他数据。

  1. 对于实时照片,回调返回 SelfieResult 对象
class SelfieResult {
    let fileData: MediaFile
}
  1. 对于视频,回调返回 LivenessResult 对象
class LivenessResult {
    let fileData: MediaFile
}

并且 MediaFile 对象具有

class MediaFile {
    let fileData: Data
    let fileName: String
    let fileType: String
}

用户分析

SDK 还允许您通过可定义的 hook 跟踪用户在 Onfido 验证过程中的旅程。

覆盖 hook

为了公开用户在 SDK 中的进度,必须在使用 .with(eventHandler: EventHandler) 调用创建 OnfidoFlow.swift 实例时定义一个 hook 方法。例如

OnfidoFlow(withConfiguration: config)
    .with(eventHandler: {
        (event: Event) -> () in
        // Your code here
    })

现在,当特定事件被触发时,通常是当用户到达新屏幕时,将调用定义方法内部的代码。有关事件的完整列表,请参阅 跟踪事件

传入的参数是一个 OnfidoFlow.Event 结构,其中包含以下内容

eventName 字符串
指示事件的类型。这将始终作为 "Screen" 返回,因为每个跟踪事件都是用户访问屏幕。
属性 字典
包含事件的具体详细信息。例如,访问的屏幕名称。

使用数据

您可以使用这些数据来跟踪有多少用户到达流程中的每个屏幕。您可以通过存储到达每个屏幕的用户数,并将其与到达 Welcome 屏幕的用户数进行比较来完成此操作。

跟踪事件

以下是 hook 当前跟踪的潜在事件列表

WELCOME - User reached the "Welcome" screen
USER_CONSENT - User reached "User consent" screen
DOCUMENT_CAPTURE - User reached the "Document capture" screen (for one-sided document)
DOCUMENT_CAPTURE_FRONT - User reached the "Document capture" screen for the front side (for two-sided document)
DOCUMENT_CAPTURE_BACK - User reached the "Document capture" screen for the back side (for two-sided document)
DOCUMENT_CAPTURE_CONFIRMATION - User reached the "Document confirmation" screen (for one-sided document)
DOCUMENT_CAPTURE_CONFIRMATION_FRONT - User reached the "Document confirmation" screen for the front side (for two-sided document)
DOCUMENT_CAPTURE_CONFIRMATION_BACK - User reached the "Document confirmation" screen for the back side (for two-sided document)
DOCUMENT_UPLOAD - User's document is uploading
FACIAL_INTRO - User reached the "Selfie intro" screen
FACIAL_CAPTURE - User reached the "Selfie capture" screen
FACIAL_CAPTURE_CONFIRMATION - User reached the "Selfie confirmation" screen
FACIAL_UPLOAD - User's selfie is uploading
VIDEO_FACIAL_INTRO - User reached the "Liveness intro" screen
VIDEO_FACIAL_CAPTURE - User reached the "Liveness video capture" screen
VIDEO_FACIAL_CAPTURE_STEP_1 - User reached the 1st challenge during "Liveness video capture", challenge_type can be found in eventProperties
VIDEO_FACIAL_CAPTURE_STEP_2 - User reached the 1st challenge during "Liveness video capture", challenge_type can be found in eventProperties
VIDEO_FACIAL_CAPTURE_CONFIRMATION - User reached the "Liveness video confirmation" screen
VIDEO_FACIAL_UPLOAD - User's liveness video is uploading
MOTION_FACIAL_INTRO - User reached the "Motion intro" screen
MOTION_FACIAL_ALIGNMENT - User reached the "Motion alignment" screen
MOTION_FACIAL_CAPTURE - User reached the "Motion capture" screen
MOTION_FACIAL_NO_FACE_DETECTED - User's face was not detected
MOTION_FACIAL_CAPTURE_ERROR_TIMEOUT - User's motion capture timed out
MOTION_FACIAL_CAPTURE_ERROR_TOO_FAST - User performed the motion head turn too fast
MOTION_FACIAL_UPLOAD - User's motion capture is uploading
MOTION_FACIAL_UPLOAD_COMPLETED - User's motion capture finished uploading
MOTION_FACIAL_CONNECTION_ERROR - User was presented the "Motion connection error" screen during upload

自定义生物识别令牌存储

当使用带有本地存储解决方案的身份验证时,默认情况下 SDK 管理生物识别令牌存储。SDK 还允许您通过公开 API 来控制令牌生命周期,以覆盖读取和写入令牌的默认实现,因此令牌可以存储在设备上、云端、钥匙串中或您的服务器上。

实施

您需要提供一个符合 EncryptedBiometricTokenHandler 协议的类。请注意需要实现的两个函数中的 customerUserHash 参数。这是用户的唯一标识符,可以用作令牌存储的密钥。如果您有自己的标识符,请随时忽略它。

处理令牌生成时和我们向您请求令牌时的回调的类示例

class CustomTokenHandlerClass: EncryptedBiometricTokenHandler {
    func onTokenGenerated(customerUserHash: String, encryptedBiometricToken: String) {
        // You store `customerUserHash` and `encryptedBiometricToken` however you choose to do so
    }

    func onTokenRequested(customerUserHash: String, completion: @escaping (String) -> Void) {
        // You use the `customerUserHash` to retrieve the encrypted biometric token you have stored and call `completion`, passing in this token
    }
}

使用处理令牌的类初始化工作流程的示例

let workflowConfiguration = WorkflowConfiguration(workflowRunId: "<WORKFLOW_RUN_ID>", sdkToken: "<YOUR_SDK_TOKEN>")
workflowConfiguration.withEncryptedBiometricTokenHandler(handler: self) // `self` to be replaced with a different instance if you are using a different class conforming to `EncryptedBiometricTokenHandler`

迁移

您可以在 MIGRATION.md 找到迁移指南

安全

证书锁定

注意:证书锁定仅适用于运行 iOS 10.3 或更高版本的设备。

您可以通过我们 OnfidoConfig.Builder 配置构建器中的 .withCertificatePinning() 方法锁定我们的 SDK 和服务器之间的任何通信。此方法接受 CertificatePinningConfiguration 作为参数,其中包含证书公钥的 sha-256 哈希值。

有关哈希的更多信息,请发送电子邮件至 Onfido 的 客户支持

Swift
let config = try OnfidoConfig.builder()
...
do {
    config.withCertificatePinning(try CertificatePinningConfiguration(hashes: ["<EXAMPLE_HASH>"]))
} catch {
    // handle CertificatePinningConfiguration initialisation failures. i.e Providing empty array causes initializer to be failed.
}
...
configBuilder.build()
Objective-C
ONFlowConfigBuilder * builder =[ONFlowConfig builder];
...
NSError * error = NULL;
ONCertificatePinningConfiguration * pinningConf = [[ONCertificatePinningConfiguration alloc] initWithHashes: @[@"<EXAMPLE_HASH>"] error: &error]];
if (error != NULL) {
    // handle ONCertificatePinningConfiguration initialisation failures. i.e Providing empty array causes initializer to be failed.
}
[builder withCertificatePinningConfiguration: pinningConf];

...

处理证书锁定错误

要识别证书锁定错误,请检查 OnfidoFlowError.exception 对象的 message 属性。对于与证书锁定相关的错误,它将返回 invalid_certificate

let responseHandler: (OnfidoResponse) -> Void = { response in
  switch response {
    case let .error(error):
        // Some error happened
        if case OnfidoFlowError.exception(withError: _, withMessage: let optionalMessage) = error, let message = optionalMessage {
            if message == "invalid_certificate" {
                // HANDLE INVALID CERTIFICATE CASE HERE
            }
        }
    case let .success(results):
        // User completed the flow
        // You can create your check here
    case .cancel:
        // Flow cancelled by the user
  }
}

辅助功能

Onfido SDK 符合 WCAG 2.1 AA 级标准。它们经过优化,默认提供以下辅助功能支持

有关更多详细信息,请参阅我们的 辅助功能声明

许可

由于 API 设计约束,以及为避免集成期间可能发生的冲突,我们捆绑了一些第三方依赖项。对于这些依赖项,我们将许可信息包含在我们的捆绑包中,并在本仓库的 licenses 文件夹中,文件名为 onfido_licenses.json。此文件包含我们捆绑的依赖项的摘要和所有必需的许可信息,包括指向同一文件夹中相关许可文本的链接。我们库的集成者有责任将此信息与他们的集成一起保存。

如何访问许可证的示例

let onfidoBundle = Bundle(for: OnfidoFlow.self)
guard let licensesPath = onfidoBundle.path(forResource: "onfido_licenses", ofType: "json", inDirectory: nil),
      let licensesData = try? Data(contentsOf: URL(fileURLWithPath: licensesPath)),
      let licensesContent = String(data: licensesData, encoding: .utf8)
else {
    return
}

print(licensesContent)

guard let mitLicensePath = onfidoBundle.path(forResource: "onfido_licenses_mit", ofType: "txt", inDirectory: nil),
      let mitLicenseData = try? Data(contentsOf: URL(fileURLWithPath: mitLicensePath)),
      let mitLicenseFileContents = String(data: mitLicenseData, encoding: .utf8)
else {
    return
}

print(mitLicenseFileContents)

更多信息

示例应用

我们包含了示例应用,以展示如何使用 Swift 和 Objective-C 与 Onfido iOS SDK 集成。有关更多信息,请参阅 SampleAppSampleAppObjC 目录。

支持

如果您在集成过程中遇到任何技术问题,请通过 电子邮件 联系 Onfido 的客户支持团队,并在主题行的开头包含单词 ISSUE:。

或者,您可以搜索通过客户体验门户提供的支持文档,public.support.onfido.com

我们建议您尽可能频繁地将 SDK 更新到最新版本。使用较新版本 Onfido SDK 的客户在用户入职和欺诈缓解方面始终能看到更好的性能,因此我们强烈建议您保持 SDK 集成处于最新状态。

您可以在 此处 查看我们的完整 SDK 版本控制策略。

版权所有 2025 Onfido, Ltd. 保留所有权利。