Flutter身份验证插件jumio_mobile_sdk_flutter的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter身份验证插件jumio_mobile_sdk_flutter的使用

插件概述

jumio_mobile_sdk_flutter 是Jumio官方为Flutter提供的移动SDK插件,用于实现身份验证功能。此插件与Jumio SDK iOS 4.12.0和Jumio SDK Android 4.12.1兼容。如果您有任何问题,请联系您的客户经理或Jumio支持

目录

兼容性

该插件已在Flutter版本3.27.1和Dart 3.6.0上进行了测试。

设置

创建Flutter项目并添加Jumio Mobile SDK模块

flutter create MyProject

添加依赖项

pubspec.yaml文件中添加Jumio Mobile SDK依赖项:

dependencies:
  flutter:
    sdk: flutter

  jumio_mobile_sdk_flutter: ^4.12.0

安装依赖项:

cd MyProject
flutter pub get
cd ios && pod install

集成

iOS

Info.plist配置

  1. Info.plist文件中添加NSCameraUsageDescription键。
  2. 确保应用的部署目标至少为iOS 11.0。

NFC、Digital Identity 和 Device Risk

Android

AndroidManifest.xml配置

打开AndroidManifest.xml文件并将allowBackup设置为false

<application>
...
android:allowBackup="false">
</application>
...

确保compileSdkVersionminSdkVersionbuildToolsVersion足够高:

android {
  minSdkVersion 21
  compileSdkVersion 33
  buildToolsVersion "32.0.0"
  ...
}

启用MultiDex

参考Android开发者指南启用MultiDex:

android {
  ...
  defaultConfig {
    ...
    multiDexEnabled true
  }
}

升级Gradle构建工具

插件要求至少使用8.0.0版本的Android构建工具,这需要升级Gradle包装器到版本8并更新到Java 11。

android/build.gradle中升级构建工具版本:

buildscript {
  ...
  dependencies {
    ...
    classpath 'com.android.tools.build:gradle:8.2.2'
  }
}

android/gradle.wrapper/gradle-wrapper.properties中修改Gradle Wrapper版本:

...
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip

Proguard规则

参考Android guides了解有关Jumio SDK的Android Proguard规则信息。

为了启用分析反馈和内部诊断,请确保在Proguard规则中包含以下行:

-keep class io.flutter.embedding.android.FlutterActivity

使用

导入库

import 'package:jumio_mobile_sdk_flutter/jumio_mobile_sdk_flutter.dart';

初始化SDK

Jumio.init("AUTHORIZATION_TOKEN", "DATACENTER");

DATACENTER可以是USEUSG。有关如何获取AUTHORIZATION_TOKEN的信息,请参考API Guide

启动SDK

Jumio.start();

获取信息

扫描结果将异步返回。可以通过await获取结果。如果发生问题(如无效凭据、缺少API密钥、权限错误等),会抛出异常。

自定义

Android

通过覆盖自定义主题AppThemeCustomJumio来自定义JumioSDK Android外观。可以在styles.xml中找到所有可自定义值的例子。

iOS

可以基于设备的外观设置(深色模式或浅色模式)自定义每个颜色,也可以为两种外观设置一个单一颜色。可以在启动时传递自定义选项。

例如,设置基于深色或浅色模式的颜色:

Jumio.start({
    "primaryColor": { light:"ffffff", dark:"000000" },
    "primaryButtonBackground": { light:"ffffff", dark:"000000" }
});

设置相同颜色用于深色和浅色模式:

Jumio.start({
    "primaryColor": "ffffff",
    "primaryButtonBackground": "ffffff"
});

所有颜色都以HEX字符串提供,格式为#ff00ff#66ff00ff(如果要设置透明度级别)。

配置

有关如何设置特定的SDK参数(如callbackUrluserReferencecountry等),请参考API Guide

回调

有关结果字段、检索API、删除API、全局设置等信息,请阅读服务器相关信息页面

结果对象

JumioSDK将在工作流成功完成后返回EventResult,在出现错误时返回EventErrorEventError包括错误代码和错误消息。

EventResult

参数 类型 最大长度 描述
selectedCountry String 3 ISO 3166-1 alpha-3国家代码
selectedDocumentType String 16 PASSPORT, DRIVER_LICENSE, IDENTITY_CARD 或 VISA
selectedDocumentSubType String 扫描ID的子类型
idNumber String 100 文档识别号
personalNumber String 文档个人编号
issuingDate Date 发行日期
expiryDate Date 到期日期
issuingCountry String 3 发行国ISO 3166-1 alpha-3国家代码
lastName String 100 客户姓氏
firstName String 100 客户名字
dob Date 出生日期
gender String 1 m, f 或 x
originatingCountry String 3 原籍国ISO 3166-1 alpha-3国家代码
addressLine String 64 街道名称
city String 64 城市
subdivision String 3 ISO 3166-2:US州代码后三位
postCode String 15 邮政编码
mrzData MRZ-DATA MRZ数据
optionalData1 String 50 MRZ第一行的可选字段
optionalData2 String 50 MRZ第二行的可选字段
placeOfBirth String 255 出生地

MRZ-Data

参数 类型 最大长度 描述
format String 8 MRP, TD1, TD2, CNIS, MRVA, MRVB 或 UNKNOWN
line1 String 50 MRZ第一行
line2 String 50 MRZ第二行
line3 String 50 MRZ第三行
idNumberValid BOOL 如果ID号码校验位有效则为true,否则为false
dobValid BOOL 如果出生日期校验位有效则为true,否则为false
expiryDateValid BOOL 如果到期日校验位有效或不可用则为true,否则为false
personalNumberValid BOOL 如果个人编号校验位有效或不可用则为true,否则为false
compositeValid BOOL 如果复合校验位有效则为true,否则为false

本地模型

我们的SDK需要几个机器学习模型来最佳工作。我们建议下载这些文件并将其添加到项目中而不更改其名称(类似于添加本地化文件)。这将在运行时节省两个网络请求以下载这些文件。

预加载模型

可以在初始化Jumio SDK之前预加载ML模型。为此,设置完成块JumioMobileSDK.setPreloaderFinishedBlock并使用JumioMobileSDK.preloadIfNeeded开始预加载。

iOS

可以在Bundling models in the app部分找到模型,并将其复制到ios/Assets文件夹中。

Android

可以在Bundling models in the app部分找到模型,并将其复制到app/src/main/assets/文件夹中。

常见问题

Android面帮助动画在发布版本中损坏

如果面帮助动画在调试版本中看起来正常但在发布版本中损坏,请确保在Proguard文件中包含以下规则:

-keep class androidx.constraintlayout.motion.widget.** { *; }

iOS模拟器显示白屏

Jumio SDK不支持iOS模拟器。请仅在物理设备上运行Jumio SDK。

iOS调试版本运行正常但发布版本崩溃

这是由于Xcode 13引入了新的选项“管理版本和构建号”。请确保禁用此选项。或者,可以在exportOptions.plist中设置manageAppVersionAndBuildNumberfalse

iOS应用启动时崩溃

如果iOS应用程序在启动时立即崩溃且没有其他信息,但Android正常工作,请确保在Podfile中添加以下行:

post_install do |installer|
    installer.pods_project.targets.each do |target|
      if ['iProov', 'DatadogRUM', 'DatadogCore', 'DatadogInternal'].include? target.name
        target.build_configurations.each do |config|
          config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
        end
      end
    end
end

对于Xcode 15及以上版本,请确保在Podfile中添加以下行:

post_install do |installer|
    installer.pods_project.targets.each do |target|
      if ['iProov', 'DatadogRUM', 'DatadogCore', 'DatadogInternal'].include? target.name
        target.build_configurations.each do |config|
          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
        end
      end
    end
end

Android发布版本国家列表为空

如果Android发布版本中的国家列表为空,请确保应用程序具有适当的互联网权限。如果没有有效的网络连接,国家不会加载,列表将保持为空。如果需要,请在AndroidManifest.xml文件中添加android.permission.INTERNET权限。

支持

如果您有任何问题,请联系Jumio客户服务:support@jumio.com或访问支持页面

示例代码

以下是一个完整的示例demo,展示了如何在Flutter应用中使用jumio_mobile_sdk_flutter插件进行身份验证。

import 'package:flutter/material.dart';
import 'package:jumio_mobile_sdk_flutter/jumio_mobile_sdk_flutter.dart';

void main() {
  runApp(DemoApp());
}

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomePage(title: "Mobile SDK Demo App"),
    );
  }
}

class HomePage extends StatefulWidget {
  final String? title;

  HomePage({Key? key, this.title}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _HomePageState(title);
}

class _HomePageState extends State<HomePage> {
  final String? title;
  final tokenInputController = TextEditingController();
  bool pressedUS = false;
  bool pressedEU = false;
  bool pressedSGP = false;

  _HomePageState(this.title);

  @override
  void initState() {
    super.initState();
    initModelPreloading();
  }

  void initModelPreloading() {
    Jumio.setPreloaderFinishedBlock(() {
      print('All models are preloaded. You may start the SDK now!');
    });
    Jumio.preloadIfNeeded();
  }

  @override
  void dispose() {
    tokenInputController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title!),
      ),
      body: Center(
        child: IntrinsicWidth(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Container(
                width: 250.0,
                child: TextFormField(
                  controller: tokenInputController,
                  decoration: InputDecoration(
                    border: UnderlineInputBorder(),
                    labelText: 'Authorization token',
                  ),
                ),
              ),
              ElevatedButton(
                child: Text("Start"),
                onPressed: () {
                  _start(tokenInputController.text);
                },
              ),
              ElevatedButton(
                child: Text("US"),
                style: ElevatedButton.styleFrom(
                  backgroundColor: pressedUS ? Colors.yellow : Colors.blue,
                  foregroundColor: Colors.white,
                ),
                onPressed: () => {
                  setState(() {
                    pressedUS = !pressedUS;
                    pressedEU = false;
                    pressedSGP = false;
                  }),
                  DATACENTER = 'US',
                },
              ),
              ElevatedButton(
                child: Text("EU"),
                style: ElevatedButton.styleFrom(
                  backgroundColor: pressedEU ? Colors.yellow : Colors.blue,
                  foregroundColor: Colors.white,
                ),
                onPressed: () => {
                  setState(() {
                    pressedEU = !pressedEU;
                    pressedUS = false;
                    pressedSGP = false;
                  }),
                  DATACENTER = 'EU',
                },
              ),
              ElevatedButton(
                child: Text("SG"),
                style: ElevatedButton.styleFrom(
                  backgroundColor: pressedSGP ? Colors.yellow : Colors.blue,
                  foregroundColor: Colors.white,
                ),
                onPressed: () => {
                  setState(() {
                    pressedSGP = !pressedSGP;
                    pressedUS = false;
                    pressedEU = false;
                  }),
                  DATACENTER = 'SG',
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _start(String authorizationToken) async {
    await _logErrors(() async {
      await Jumio.init(authorizationToken, DATACENTER);
      final result = await Jumio.start(
        {
          // "background": "#AC3D9A",
          // "primaryColor": "#FF5722",
          // "loadingCircleIcon": "#F2F233",
          // "loadingCirclePlain": "#57ffc7",
          // "loadingCircleGradientStart": "#EC407A",
          // "loadingCircleGradientEnd": "#bc2e41",
          // "loadingErrorCircleGradientStart": "#AC3D9A",
          // "loadingErrorCircleGradientEnd": "#C31322",
          // "primaryButtonBackground": {"light": "#D900ff00", "dark": "#9Edd9E"}
        }
      );
      await _showDialogWithMessage("Jumio has completed. Result: $result");
    });
  }

  Future<void> _logErrors(Future<void> Function() block) async {
    try {
      await block();
    } catch (error) {
      await _showDialogWithMessage(error.toString(), "Error");
    }
  }

  Future<void> _showDialogWithMessage(String message, [String title = "Result"]) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(title),
          content: SingleChildScrollView(child: Text(message)),
          actions: <Widget>[
            TextButton(
              child: Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }
}

希望这个详细的指南能帮助您顺利集成和使用jumio_mobile_sdk_flutter插件。如果有任何问题,请随时联系Jumio支持团队。


更多关于Flutter身份验证插件jumio_mobile_sdk_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter身份验证插件jumio_mobile_sdk_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用jumio_mobile_sdk_flutter插件进行身份验证的示例代码。这个示例假设你已经安装并配置好了jumio_mobile_sdk_flutter插件。

首先,确保你的pubspec.yaml文件中已经添加了jumio_mobile_sdk_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  jumio_mobile_sdk_flutter: ^latest_version  # 请替换为最新的版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中,你可以按照以下步骤使用Jumio SDK进行身份验证:

  1. 初始化SDK(通常在你的应用的主入口文件中,比如main.dart):
import 'package:flutter/material.dart';
import 'package:jumio_mobile_sdk_flutter/jumio_mobile_sdk_flutter.dart';

void main() {
  // 初始化Jumio SDK(这里假设你已经有了Jumio提供的必要配置信息)
  Jumio.initialize(
    apiKey: 'YOUR_API_KEY',
    apiSecret: 'YOUR_API_SECRET',
    environment: JumioEnvironment.sandbox, // 或者 JumioEnvironment.production
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Jumio Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: JumioDemoScreen(),
    );
  }
}
  1. 创建一个屏幕来触发身份验证流程(比如JumioDemoScreen.dart):
import 'package:flutter/material.dart';
import 'package:jumio_mobile_sdk_flutter/jumio_mobile_sdk_flutter.dart';

class JumioDemoScreen extends StatefulWidget {
  @override
  _JumioDemoScreenState createState() => _JumioDemoScreenState();
}

class _JumioDemoScreenState extends State<JumioDemoScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Jumio Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            try {
              // 触发Jumio身份验证流程
              final result = await Jumio.startDocumentVerification(
                configuration: DocumentVerificationConfiguration(
                  // 根据你的需求配置相关参数
                  allowedDocumentTypes: [
                    DocumentType.driversLicense,
                    DocumentType.passport,
                    // 其他支持的文档类型
                  ],
                  countryCodes: ['US'], // 支持的国家代码列表
                  // 其他可选配置参数
                ),
                listener: (event) {
                  // 处理身份验证过程中的事件,比如扫描进度、错误信息等
                  print('Jumio event: $event');
                },
              );

              // 处理身份验证结果
              if (result.isVerified) {
                print('Document is verified!');
                // 可以在这里处理验证成功后的逻辑
              } else {
                print('Document verification failed.');
                // 可以在这里处理验证失败后的逻辑
              }
            } catch (e) {
              // 处理错误
              print('Error during Jumio verification: $e');
            }
          },
          child: Text('Start Jumio Verification'),
        ),
      ),
    );
  }
}

请注意,上述代码是一个简化的示例,实际使用中你可能需要根据Jumio SDK的文档来调整配置参数,并处理更多的身份验证流程和结果。

另外,确保你已经在Jumio开发者门户中注册并获取了必要的API密钥和秘密,以及配置了你的应用信息。

最后,不要忘记在发布应用前将环境从JumioEnvironment.sandbox切换到JumioEnvironment.production

回到顶部