Flutter接入

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

使用限制

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

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

依赖配置

  1. 下载Flutter SDK并解压。

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

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

  3. 编辑业务工程中的pubspec.yaml文件,并在dev_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

配置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.**{*;}

iOS环境配置

添加Camera权限

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

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

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

添加framework

Link Binary With Libraries配置项中添加SDK的framework和系统依赖库。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(详情见AndroidiOS的extParams说明):

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

      • iOS:2002,ZIMNetworkfail

      • Android:1001,NET_RESPONSE_INVALID

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

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

    说明

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

    点击查看错误码详情

    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 - CertifyId为null或长度为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加载异常

    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(ZIMResponseSuccess)

    刷脸成功

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

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

    1001(ZIMInternalError)

    系统错误

    表示系统错误。

    1003(ZIMInterrupt)

    验证中断

    表示验证中断。

    2002(ZIMNetworkfail)

    网络错误

    表示网络错误。

    2003(ZIMTIMEError)

    客户端设备时间错误

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

    2006(ZIMResponseFail)

    刷脸失败

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

    该结果仅供参考,可通过调用服务端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下载。