Flutter接入

金融级实人认证服务提供Flutter客户端SDK,帮助您在业务应用(App)中实现刷脸认证功能。本文结合示例代码介绍Flutter客户端的接入流程。

使用限制

  • 不支持模拟器调试及使用,请您使用真机开发及功能测试。

  • 仅支持iOS 9.0、Android 5.0及以上版本的移动智能设备(手机或Pad)接入。

依赖配置

  1. 下载Flutter SDK并解压。

    说明
    • 当前 Flutter SDK 中使用的金融级实人认证SDK版本为2.3.39

    • Flutter SDK中的接口介绍,请参见接口说明

  2. 将解压后的Flutter SDK拷贝至业务工程。业务工程

  3. 编辑业务工程中的pubspec.yaml文件,并在dependencies字段下增加阿里云刷脸插件依赖。

    aliyun_face_plugin:
        path: aliyun_face_plugin

    pubspec.yaml

Android环境配置

增加模块依赖

编辑业务工程下/android/build.gradle文件,在allprojects字段中增加flatDir配置。

flatDir {
    dirs project(':aliyun_face_plugin').file('libs')
}

build.gradle

说明

如果您使用了高版本的Flutter出现报错:Namespace not specified. Specify a namespace in the module's build file.

可以尝试在/android/build.gradle文件,在android字段中增加namespace = com.aliyun.face.aliyun_face_plugin

配置Proguard混淆规则

如果在release场景下配置了Proguard代码混淆,则需要在业务工程的android/app/proguard-rules.pro文件中添加如下规则:

# 必须要依赖到应用混淆中
-keepclassmembers,allowobfuscation class * {
     @com.alibaba.fastjson.annotation.JSONField <fields>;
}
-keep class net.security.device.api.** {*;}
-keep class face.security.device.api.** {*;}
-keep class com.alipay.deviceid.** { *; }
-keep class org.json.** { *;}
-keep class com.alibaba.fastjson.** {*;}

# SDK混淆配置
-keep class com.alipay.face.api.** {*;}
-keep class com.alipay.zoloz.toyger.**{*;}
-keep class com.dtf.face.api.** {*;}
-keep class com.dtf.face.ocr.verify.DTFOcrFacade { *; }
-keep class com.dtf.face.verify.** {*;}
-keep class com.dtf.face.network.model.** {*;}
-keep class com.dtf.face.network.APICallback {*;}
-keep class com.dtf.face.config.**{*;}
-keep class com.dtf.face.log.** {*;}
-keep class com.dtf.face.ui.overlay.** {*;}
-keep class com.dtf.face.ui.widget.ToygerWebView {*;}
-keep class com.dtf.face.utils.ClientConfigUtil{
   boolean needUploadPreviewTrace*();
   boolean needVideoExDegrade*();
   boolean isCfgVideoExDevice*();
}
-keep class com.dtf.toyger.base.** {*;}
-keep class com.dtf.face.network.mpass.biz.model.** { *; }
-keep class com.dtf.face.utils.LogUtils { *; }
-keep class com.dtf.wish.api.** { *; }
-keep class com.dtf.wish.ui.** { *; }
-keep class com.dtf.wish.ui.WishFragment{*;}
-keep class com.dtf.voice.api.** { *; }
-keep class xnn.* { *; }
-keep class facadeverify.** { *; }
-keep class baseverify.** { *; }
-keep class faceverify.** { *; }
-keep class ocrverify.** { *; }
-keep class wishverify.** { *; }

# R8编译混淆配置
-keep class com.dtf.face.ui.toyger.FaceLoadingFragment{ *; }
-keep class com.dtf.face.ui.toyger.FaceShowFragment{*;}
-keep class com.dtf.face.ui.toyger.FaceShowElderlyFragment{*;}
-keepclassmembers class com.dtf.face.camera.ICameraCallback{
   void onPreviewFrame*(*);
}

# NFC编译配置
-keep class com.dtf.face.nfc.verify.DTFNfcFacade { *; }
-keep class com.eidlink.**{*;}
-keep class net.sf.**{*;}
-keep class org.**{*;}
-keep class cn.**{*;}
-keep class com.froad.**{*;}
-keep class com.huawei.**{*;}
-keep class com.eidlink.**{*;}
-keep class org.ejbca.cvc.**{*;}
-keep class org.jmrtd.**{*;}
-keep public class com.netease.nis.sdkwrapper.Utils {public <methods>;}
-keep class net.sf.scuba.**{*;}
-keep class org.eid_bc.bouncycastle.jcajce.provider.symmetric.**{*;}

# 忽略警告
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**

iOS环境配置

添加Camera权限

  1. 使用Xcode打开Runner工程(业务工程/ios/Runner.xcworkspace)。

  2. 按照下图指引,在Runner工程的Info.plist文件中增加Camera权限。

    Value值需要您根据业务自定义。info.plist

添加framework

Link Binary With Libraries配置项中添加SDKframework和系统依赖库。framework位于解压后的Flutter SDK目录下,路径为aliyun_face_plugin/ios/Products/

image.png

SDK中的framework:

AliyunFaceAuthFacade.framework
APBToygerFacade.framework
APPSecuritySDK.framework
BioAuthEngine.framework
faceguard.framework
DTFIdentityManager.framework
DTFUtility.framework
MultiFactorFacade.framework
OCRDetectSDKForTech.framework
ToygerNative.framework
ToygerService.framework
VerifyNativeAbility.framework

系统依赖库:

CoreGraphics.framework
Accelerate.framework
SystemConfiguration.framework
AssetsLibrary.framework
CoreTelephony.framework
QuartzCore.framework
CoreFoundation.framework
CoreLocation.framework
ImageIO.framework
CoreMedia.framework
CoreMotion.framework
AVFoundation.framework
WebKit.framework
libresolv.tbd
libz.tbd
libc++.tbd
libc++.1.tbd
libc++abi.tbd
AudioToolbox.framework
CFNetwork.framework
MobileCoreServices.framework
libz.1.2.8.tbd
AdSupport.framework
ReplayKit.framework

添加Bundle

按照下图指引,在Copy Bundle Resources配置项中添加以下Bundle。Bundle位于解压后的Flutter SDK目录下,路径为aliyun_face_plugin/ios/Products/

  • ToygerService.bundle:位于ToygerService.framework中。

  • APBToygerFacade.bundle:位于APBToygerFacade.framework中。

  • APBToygerFacadeSuitable.bundle:位于APBToygerFacade.framework中。

  • OCRXMedia.bundle:位于OCRDetectSDKForTech.framework中。

  • BioAuthEngine.bundle:位于BioAuthEngine.framework中。

image.png

增加-ObjC链接标志

按照下图指引,在Other Linker Flags配置项中添加-ObjC标志。链接标志

接口说明

Flutter SDK包含初始化SDK(init)、获取MetaInfos(getMetaInfos)、自定义UI(setCustomUI)和开始认证(verify)四个接口。

class AliyunFacePlugin {
  // SDK初始化接口
  Future<void> init() {
    return AliyunFacePluginPlatform.instance.init();
  }

  // 获取客户端的metainfos,用于服务器端接口获取认证id,即CertifyId
  Future<String?> getMetaInfos() {
    return AliyunFacePluginPlatform.instance.getMetaInfos();
  }
  
  // SDK认证接口
  Future<String?> verify(Map<String, String> params) {
    return AliyunFacePluginPlatform.instance.verify(params);
  }
  
  // SDK自定义UI
  Future<String?> setCustomUI(String configuration) {
    return AliyunFacePluginPlatform.instance.setCustomUI(configuration);
  }
}

初始化SDK

  • 描述:主要用于人脸模型及人脸安全模块的初始化。需要在应用刚启动,用户确认App隐私协议之后,尽可能早的调用。

  • 函数原型:

    Future<void> init() {
        return AliyunFacePluginPlatform.instance.init();
    }
  • 返回值:无。

获取MetaInfos

  • 描述:该接口返回客户端的环境信息,客户端需要将这些信息发送至业务服务器端,业务服务器端将这些信息作为参数之一(MetaInfo)调用服务端初始化认证接口InitFaceVerify,从而获取CertifyId,用于后续认证环节。

  • 函数原型:

    Future<String?> getMetaInfos() {
        return AliyunFacePluginPlatform.instance.getMetaInfos();
    }
  • 返回值:无。

自定义UI

  • 描述:可自定义认证页面的UI颜色、icon图标等内容。

  • 函数原型:

    Future<String?> setCustomUI() {
        return AliyunFacePluginPlatform.instance.setCustomUI(configuration);
    }

开始认证

  • 描述:用于发起实人认证请求。

  • 函数原型:

    Future<String?> verify(Map<String, String> params) {
        return AliyunFacePluginPlatform.instance.verify(params);
    }
  • 参数 params:JSON格式传入认证ID(CertifyId)和扩展参数Key-Value(详情见AndroidiOSextParams说明):

    {"certifyId":"认证id","扩展参数key":"扩展参数value"}
    重要
    • 每个CertifyId只能使用一次,否则会返回错误。错误信息如下:

      • iOS:2002,ZIMNetworkfail

      • Android:1001,NET_RESPONSE_INVALID

    • 您可以在为扩展参数传值前判断运行环境是Android还是iOS,从而传入准确的extParams值(推荐),也可以将两个环境的extParams一起传入。

  • 返回值:返回实人认证请求状态。格式为code,reson,中间以逗号(,)分隔。code为错误码;reson为具体原因。

    说明

    iOS、Android平台的codereson释义可能会有不同,以相应的文档说明为准。

    点击查看错误码详情

    Android

    为了方便您在离线环境下也可以查询参考,可以缓存下方表格到本地

    客户端错误码

    Android

    1000

    Z5120 - 刷脸成功,认证通过。可通过服务端查询接口获取认证详细资料信息

    1001

    Z1000 - 其他异常

    Z1001 - 人脸识别算法初始化失败

    Z1002 - 无法启动相机

    Z1003 - 不支持的CPU架构

    Z1004 - Android系统版本过低

    Z1018 - 无前置摄像头

    Z1019 - 摄像头权限未赋予

    Z1020 - 打开摄像头失败

    Z1021 - 摄像头流错误

    Z1023 - 认证内部错误

    Z1024 - SDK认证流程正在进行中,请等待本地认证流程完成后再发起新调用

    Z1029 - 系统版本过低,不支持录屏

    Z1030 - 录音权限未赋予

    Z1031 - 录屏权限未赋予

    Z1032 - 麦克风打开失败

    Z1033 - 录屏打开失败

    Z1035 - Context为空

    Z1036 - 认证之前没有调用 install() 接口完成初始化

    Z1037 - CertifyIdnull或长度为0

    Z1056 - 混淆配置错误

    Z1039 - 多进程使用webview

    Z1045 - Context为空

    Z1046 - 刷脸过程中断

    Z1047 - 模型数据错误

    Z1048 - 质量认证异常

    Z5112 - 上传炫彩Meta信息失败

    Z5113 - 上传炫彩视频失败

    Z5114 - 认证视频上传失败

    Z6001 - OCR识别次数超限

    Z6003 - OSS Token过期

    Z6004 - 人脸照片处理失败

    Z7001 - SDK初始化或者使用过程中数据异常

    Z3002 - 拒绝打开系统NFC功能

    Z3003 - 设备不支持NFC

    Z3004 - NFC协议相关异常

    Z3005 - 透传模式三要素错误

    Z5115_4 - so加载异常

    A4001 - 刷脸模块接入异常

    A4002 - 炫彩模块接入异常

    A4003 - OCR模块接入异常

    A4004 - NFC模块接入异常

    A4005 - 意愿模块接入异常

    1003

    Z1005 - 刷脸超时(单次)

    Z1006 - 多次刷脸超时

    Z1008 - 用户在认证过程中点击X退出

    Z1009 - 用户在授权页面点击“暂不授权”退出

    Z1013 - 活体检测不通过

    Z1041 - OCR重试次数过多退出

    Z1044 - 认证过程中折叠屏设备折叠/展开状态调整

    Z3001 - NFC重试超过限制

    2002

    Z1011 - 客户端初始化网络错误

    Z1012 - 客户端网络访问异常

    Z1025 - 客户端初始化接口返回网络错误

    Z1026 - 信息上传网络错误

    Z1027 - 服务端认证接口网络错误

    Z1028 - 服务端接口并发请求超出限制

    Z1040 - 刷脸模型下载失败

    Z1042 - OCR认证服务报错

    Z1043 - 刷脸认证服务报错

    Z5116 - 音频文件上传失败

    Z6002 - OCR图片上传网络超时

    2003

    客户端设备时间错误

    2006

    Z5128 - 刷脸失败,认证未通过。可通过服务端查询接口获取认证未通过具体原因。

    iOS

    response.code包含以下返回参数,具体说明如下表所示。

    错误码

    是否计费

    错误码文案

    错误码描述

    1000

    刷脸成功

    用户完成了刷脸过程,认证建议结果为通过。

    该结果仅供参考,可通过调用服务端DescribeFaceVerify接口获取最终认证结果。

    1001

    系统错误

    表示系统错误。

    1003

    验证中断

    表示验证中断。

    2002

    网络错误

    表示网络错误。

    2003

    客户端设备时间错误

    表示客户端设备时间错误。

    2006

    是(失败次数过多场景不计费)

    失败次数过多,或刷脸验证失败。

    该结果仅供参考,可通过调用服务端 DescribeFaceVerify 接口获取最终认证结果以及未通过的详细原因。

    说明

    关于错误码的更多信息,您可以下载金融级客户端iOS错误码详表查看。

示例代码

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

import 'package:flutter/services.dart';
import 'package:aliyun_face_plugin/aliyun_face_plugin.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _infos = 'Unknown';
  final _aliyunFacePlugin = AliyunFacePlugin();

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

    // 在App启动的早期调用init接口。
    _aliyunFacePlugin.init();
  }

  Future<void> getMetaInfos() async {
    String metainfos;

    try {
      // 获取客户端metainfos,将信息发送到服务器端,调用服务器端相关接口获取认证ID,即CertifyId。
      metainfos = await _aliyunFacePlugin.getMetaInfos() ?? 'Unknown metainfos';
    } on PlatformException {
      metainfos = 'Failed to get metainfos.';
    }

    setState(() {
      _infos = "metainfos: " + metainfos;
    });
  }

  Future<void> startVerify() async {
    String verifyResult;
    try {
      // 调用认证接口,CertifyId需要调用服务器端接口获取。
      // 每个CertifyId只能使用一次,否则会返回code: "2002(iOS), 1001(Android)"。
      Map<String, String> params = {"certifyId":"认证id","扩展参数key":"扩展参数value"};
      verifyResult = await _aliyunFacePlugin.verify(
              params) ??
          '-1,error';
    } on PlatformException {
      verifyResult = '-2,exception';
    }

    setState(() {
      _infos = "verifyResult: " + verifyResult;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Aliyun face plugin demo')),
        body: Center(
            child: Column(children: <Widget>[
          Text('$_infos\n'),
          ElevatedButton(
              onPressed: () async {
                getMetaInfos();
              },
              child: Text("getMetaInfos")),
          ElevatedButton(
              onPressed: () async {
                startVerify();
              },
              child: Text("startVerify")),
        ])),
      ),
    );
  }
}
            

完整代码示例,请点击Demo下载。