Flutter身份验证与KYC审核插件flutter_accura_kyc的使用

Flutter身份验证与KYC审核插件flutter_accura_kyc的使用

简介

flutter_accura_kyc 是一个基于 Accura Scan 的数字用户验证系统插件。它支持多种文档扫描功能,包括 MRZ、OCR、条形码、银行卡等,并且可以用于身份验证和 KYC 审核。


安装

pubspec.yaml 文件中添加以下依赖:

flutter pub add flutter_accura_kyc

或者通过本地路径安装:

flutter pub add <绝对路径到(flutter_accura_kyc)文件夹>

注意事项:

下载插件后,可以通过本地路径将 flutter_accura_kyc 添加到项目中。


安卓配置

权限设置

AndroidManifest.xml 文件中添加以下权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

配置 Gradle

在根目录的 build.gradle 文件末尾添加 jcenter()

buildscript {
    repositories {
        ...
        jcenter()
    }
}

allprojects {
    repositories {
        ...
        jcenter()
    }
}

app/build.gradle 中设置 Accura SDK:

android {
    defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    packagingOptions {
        pickFirst 'lib/arm64-v8a/libcrypto.so'
        pickFirst 'lib/arm64-v8a/libssl.so'
        pickFirst 'lib/armeabi-v7a/libcrypto.so'
        pickFirst 'lib/armeabi-v7a/libssl.so'
        pickFirst 'lib/x86/libcrypto.so'
        pickFirst 'lib/x86/libssl.so'
        pickFirst 'lib/x86_64/libcrypto.so'
        pickFirst 'lib/x86_64/libssl.so'
        pickFirst '**/libjsc.so'
        pickFirst '**/libc++_shared.so'
        pickFirst 'lib/x86/libc++_shared.so'
        pickFirst 'lib/x86_64/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libopencv_java4.so'
        pickFirst 'lib/arm64-v8a/libopencv_java4.so'
    }
}

iOS 配置

权限设置

Info.plist 文件中添加以下权限:

<key>NSCameraUsageDescription</key>
<string>App usage camera for scan documents.</string>
<key>NSMicrophoneUsageDescription</key>
<string>App usage microphone for oral verification.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>App usage speech recognition for oral verification.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App usage photos for get document picture.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App usage photos for save document picture.</string>

设置 Accura 许可证

Accura 提供三种许可证以启用完整的功能。从 这里 生成自己的许可证。

许可证类型:

  1. key.license:必备许可证,用于初始化 Accura SDK。
  2. accuraface.license:用于人脸匹配百分比计算。
  3. accuraactiveliveness.license:用于活体检测。

安卓配置

将三个许可证放入 android/app/src/main/assets/ 目录中。

iOS 配置

在 Xcode 中将许可证拖入项目根目录,并确保勾选 “复制如果需要” 和 “项目名称”。


使用方法

导入库

在 Dart 文件中导入插件:

import 'package:flutter_accura_kyc/flutter_accura_kyc.dart';

获取许可证配置

获取许可证的所有可用功能:

await FlutterAccuraKyc.getMetaData()
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

设置自定义配置

为 Accura SDK 设置自定义消息和配置:

let config = { 
    "ACCURA_ERROR_CODE_MOTION": '保持文档稳定',
    "ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME": '保持文档在框架内',
    "ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME": '将卡片靠近框架',
    "ACCURA_ERROR_CODE_PROCESSING": '处理中...',
    "ACCURA_ERROR_CODE_BLUR_DOCUMENT": '文档模糊检测',
    "ACCURA_ERROR_CODE_FACE_BLUR": '面部模糊检测',
    "ACCURA_ERROR_CODE_GLARE_DOCUMENT": '文档反光检测',
    "ACCURA_ERROR_CODE_HOLOGRAM": '检测到全息图',
    "ACCURA_ERROR_CODE_DARK_DOCUMENT": '低光照检测',
    "ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT": '无法接受复印件',
    "ACCURA_ERROR_CODE_FACE": '未检测到人脸',
    "ACCURA_ERROR_CODE_MRZ": '未检测到 MRZ',
    "ACCURA_ERROR_CODE_PASSPORT_MRZ": '护照 MRZ 未检测到',
    "ACCURA_ERROR_CODE_ID_MRZ": '身份证 MRZ 未检测到',
    "ACCURA_ERROR_CODE_VISA_MRZ": '签证 MRZ 未检测到',
    "ACCURA_ERROR_CODE_WRONG_SIDE": '扫描文档错误面',
    "ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE": '文档倒置,请正确放置',
    "IS_SHOW_LOGO": true,
    "SCAN_TITLE_OCR_FRONT": '扫描 OCR 文档正面',
    "SCAN_TITLE_OCR_BACK": '扫描 OCR 文档背面',
    "SCAN_TITLE_OCR": '扫描',
    "SCAN_TITLE_BANKCARD": '扫描银行卡',
    "SCAN_TITLE_BARCODE": '扫描条形码',
    "SCAN_TITLE_MRZ_PDF417_FRONT": '扫描文档正面',
    "SCAN_TITLE_MRZ_PDF417_BACK": '现在扫描文档背面',
    "SCAN_TITLE_DLPLATE": '扫描车牌'
};

await FlutterAccuraKyc.setupAccuraConfig([config])
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

扫描 MRZ 文档

let config = [{ enableLogs: false }, MRZType, CountryList, AppOrientation];
await FlutterAccuraKyc.startMRZ(config)
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

扫描 OCR 文档

let config = [{ enableLogs: false }, CountryId, CardId, CardName, CardType, AppOrientation];
await FlutterAccuraKyc.startOcrWithCard(config)
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

扫描条形码

let config = [{ enableLogs: false }, BarcodeType, AppOrientation];
await FlutterAccuraKyc.startBarcode(config)
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

扫描银行卡

let config = [{ enableLogs: false }, AppOrientation];
await FlutterAccuraKyc.startBankCard(config)
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

获取人脸匹配百分比

var accuraConfs = { enableLogs: false, with_face: true, face_uri: 'uri of face'};
var config = {
    "feedbackTextSize": 18,
    "feedBackframeMessage": '框住你的脸',
    "feedBackAwayMessage": '远离手机',
    "feedBackOpenEyesMessage": '保持眼睛睁开',
    "feedBackCloserMessage": '靠近手机',
    "feedBackCenterMessage": '移动到中心',
    "feedBackMultipleFaceMessage": '检测到多张人脸',
    "feedBackHeadStraightMessage": '保持头部直立',
    "feedBackBlurFaceMessage": '检测到人脸模糊',
    "feedBackGlareFaceMessage": '检测到反光',
    "setBlurPercentage": 80,
    "setGlarePercentage_0": -1,
    "setGlarePercentage_1": -1,
};

let passArgs = [accuraConfs, config, AppOrientation];
await FlutterAccuraKyc.startFaceMatch(passArgs)
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

活体检测

var accuraConfs = { enableLogs: false, with_face: true, face_uri: 'uri of face' };
var config = {
    "feedbackTextSize": 18,
    "feedBackframeMessage": '框住你的脸',
    "feedBackAwayMessage": '远离手机',
    "feedBackOpenEyesMessage": '保持眼睛睁开',
    "feedBackCloserMessage": '靠近手机',
    "feedBackCenterMessage": '移动到中心',
    "feedBackMultipleFaceMessage": '检测到多张人脸',
    "feedBackHeadStraightMessage": '保持头部直立',
    "feedBackBlurFaceMessage": '检测到人脸模糊',
    "feedBackGlareFaceMessage": '检测到反光',
    "setBlurPercentage": 80,
    "setGlarePercentage_0": -1,
    "setGlarePercentage_1": -1,
    "isSaveImage": true,
    "liveness_url": 'your liveness url',
    "contentType": 'form_data',
    "feedBackLowLightMessage": '低光照检测',
    "feedbackLowLightTolerence": 39,
    "feedBackStartMessage": '将你的脸放在椭圆形内',
    "feedBackLookLeftMessage": '看向左肩',
    "feedBackLookRightMessage": '看向右肩',
    "feedBackOralInfoMessage": '大声说出每个数字',
    "enableOralVerification": false,
    "codeTextColor": 'white'
};

let passArgs = [accuraConfs, config, AppOrientation];
await FlutterAccuraKyc.startLiveness(passArgs)
    .then((value) => {
        dynamic result = json.decode(value);
    })
    .onError((error, stackTrace) => {
        print("Error: $error");
    });

示例代码

以下是完整的示例代码:

import 'dart:ffi';
import 'dart:io';

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:flutter_accura_kyc/flutter_accura_kyc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'ResultScreen.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
    debugShowCheckedModeBanner: false,
  ));
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  dynamic _result = {'isValid': false};
  String language = 'en';
  Map<String, dynamic> countrySelected = {};
  Map<String, dynamic> cardSelected = {};
  Map<String, dynamic> mrzSelected = {};
  Map<String, dynamic> barcodeSelected = {};
  String mrzCountryList = 'all';
  List<Map<String, dynamic>> mrzList = [
    {"label": "Passport", "value": "passport_mrz"},
    {"label": "Mrz ID", "value": "id_mrz"},
    {"label": "Visa Card", "value": "visa_mrz"},
    {"label": "Other", "value": "other_mrz"}
  ];
  List<String> ocrCountryDropdownOptions = [''];
  List<String> ocrCardDropdownOptions = [''];
  List<String> mrzDropdownOptions = [''];
  List<String> barcodeDropdownOptions = [''];
  dynamic sdkConfig;

  String selectedCardString = "";

  [@override](/user/override)
  void initState() {
    super.initState();
    requestForPermission();
    getMetaData();
  }

  Future<bool> requestForPermission() async {
    List<bool> grantStatus = [];
    var status = true;
    Map<Permission, PermissionStatus> statuses = await [
      Permission.camera,
      Permission.storage,
      Permission.microphone,
    ].request();
    print(statuses);
    for (var i = 0; i < statuses.length; i++) {
      if (statuses[i] != PermissionStatus.granted) {
        grantStatus.add(true);
      } else {
        grantStatus.add(false);
      }
    }

    for (var item in grantStatus) {
      if (!item) {
        status = false;
      }
    }
    return status;
  }

  String getOrientation() {
    if (MediaQuery.of(context).orientation.toString().contains('landscape')) {
      return 'landscape';
    }
    return 'portrait';
  }

  void showFlutterToast(msg) {
    Fluttertoast.showToast(
        msg: msg,
        gravity: ToastGravity.BOTTOM,
        toastLength: Toast.LENGTH_SHORT);
  }

  Future<void> getMetaData() async {
    try {
      await FlutterAccuraKyc.getMetaData()
          .then((value) => {setupConfigData(json.decode(value))})
          .onError((error, stackTrace) => {
                showFlutterToast("Error :" + error.toString())
              });
    } on PlatformException {}
    if (!mounted) return;
  }

  void setupConfigData(obj) {
    setState(() {
      sdkConfig = obj;
    });
    print("setupConfigData $obj");
    setupAccuraConfig();
    List<String> tempList1 = [];
    for (var item in mrzList) {
      tempList1.add(item["label"]);
    }

    List<String> tempList2 = [];
    for (var item in obj['barcodes']) {
      tempList2.add(item['name']);
    }

    List<String> tempList3 = [];
    for (var item in obj['countries']) {
      tempList3.add(item['name']);
    }

    setState(() {
      mrzDropdownOptions = tempList1;
      barcodeDropdownOptions = tempList2;
      ocrCountryDropdownOptions = tempList3;
    });
  }

  Future<void> setupAccuraConfig() async {
    try {
      var config = {
        "ACCURA_ERROR_CODE_MOTION": this.language == 'en'
            ? 'Keep Document Steady'
            : 'حافظ على ثبات المستند',
        "ACCURA_ERROR_CODE_DOCUMENT_IN_FRAME": this.language == 'en'
            ? 'Keep document in frame'
            : 'احتفظ بالمستند في الإطار',
        "ACCURA_ERROR_CODE_BRING_DOCUMENT_IN_FRAME": this.language == 'en'
            ? 'Bring card near to frame'
            : 'إحضار البطاقة بالقرب من الإطار',
        "ACCURA_ERROR_CODE_PROCESSING": this.language == 'en'
            ? 'Processing'
            : 'يعالج',
        "ACCURA_ERROR_CODE_BLUR_DOCUMENT": this.language == 'en'
            ? 'Blur detect in document'
            : 'كشف التمويه في المستند',
        "ACCURA_ERROR_CODE_FACE_BLUR": this.language == 'en'
            ? 'Blur detected over face'
            : 'تم الكشف عن ضبابية على الوجه',
        "ACCURA_ERROR_CODE_GLARE_DOCUMENT": this.language == 'en'
            ? 'Glare detect in document'
            : 'كشف الوهج في المستند',
        "ACCURA_ERROR_CODE_HOLOGRAM": this.language == 'en'
            ? 'Hologram Detected'
            : 'تم الكشف عن صورة ثلاثية الأبعاد',
        "ACCURA_ERROR_CODE_DARK_DOCUMENT": this.language == 'en'
            ? 'Low lighting detected'
            : 'تم الكشف عن إضاءة منخفضة',
        "ACCURA_ERROR_CODE_PHOTO_COPY_DOCUMENT": this.language == 'en'
            ? 'Can not accept Photo Copy Document'
            : 'لا يمكن قبول مستند نسخ الصور',
        "ACCURA_ERROR_CODE_FACE": this.language == 'en'
            ? 'Face not detected'
            : 'لم يتم الكشف عن الوجه',
        "ACCURA_ERROR_CODE_MRZ": this.language == 'en'
            ? 'MRZ not detected'
            : 'لم يتم الكشف عن MRZ',
        "ACCURA_ERROR_CODE_PASSPORT_MRZ": this.language == 'en'
            ? 'Passport MRZ not detected'
            : 'لم يتم الكشف عن MRZ جواز سفر',
        "ACCURA_ERROR_CODE_ID_MRZ": this.language == 'en'
            ? 'ID card MRZ not detected'
            : 'لم يتم الكشف عن بطاقة الهوية MRZ',
        "ACCURA_ERROR_CODE_VISA_MRZ": this.language == 'en'
            ? 'Visa MRZ not detected'
            : 'لم يتم الكشف عن Visa MRZ',
        "ACCURA_ERROR_CODE_WRONG_SIDE": this.language == 'en'
            ? 'Scanning wrong side of document'
            : 'مسح الجانب الخطأ من المستند',
        "ACCURA_ERROR_CODE_UPSIDE_DOWN_SIDE": this.language == 'en'
            ? 'Document is upside down. Place it properly'
            : 'المستند مقلوب. ضعه بشكل صحيح',
        "IS_SHOW_LOGO": false,
        "SCAN_TITLE_OCR_FRONT": this.language == 'en'
            ? 'Scan Front Side of'
            : 'مسح الجانب الأمامي من',
        "SCAN_TITLE_OCR_BACK": this.language == 'en'
            ? 'Scan Back Side of'
            : 'مسح الجانب الخلفي من',
        "SCAN_TITLE_OCR": this.language == 'en' ? 'Scan' : 'مسح',
        "SCAN_TITLE_BANKCARD": this.language == 'en'
            ? 'Scan Bank Card'
            : 'مسح البطاقة المصرفية',
        "SCAN_TITLE_BARCODE": this.language == 'en'
            ? 'Scan Barcode'
            : 'مسح الرمز الشريطى',
        "SCAN_TITLE_MRZ_PDF417_FRONT": this.language == 'en'
            ? 'Scan Front Side of Document'
            : 'مسح الوجه الأمامي للمستند',
        "SCAN_TITLE_MRZ_PDF417_BACK": this.language == 'en'
            ? 'Now Scan Back Side of Document'
            : 'الآن مسح الجانب الخلفي من المستند',
        "SCAN_TITLE_DLPLATE": this.language == 'en'
            ? 'Scan Number Plate'
            : 'مسح رقم اللوحة'
      };
      await FlutterAccuraKyc.setupAccuraConfig([config])
          .then((value) => {
                setState(() {
                  print("RESULT:- $value");
                })
              })
          .onError((error, stackTrace) => {
                showFlutterToast("Error :" + error.toString())
              });
    } on PlatformException {}
  }

  Future<void> startOCR() async {
    try {
      var config = [
        {"enableLogs": false},
        countrySelected['id'],
        cardSelected['id'],
        cardSelected['name'],
        cardSelected['type'],
        getOrientation()
      ];
      print('startOCR:- $config');
      await FlutterAccuraKyc.startOcrWithCard(config)
          .then((value) => {
                setState(() {
                  _result = json.decode(value);
                  print("RESULT:- $_result");
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => ResultScreen(data: _result)));
                })
              })
          .onError((error, stackTrace) => {
                showFlutterToast("Error :" + error.toString())
              });
    } on PlatformException {}
  }

  Future<void> startMRZ() async {
    try {
      var config = [
        {"enableLogs": false},
        this.mrzSelected["value"],
        this.mrzCountryList,
        getOrientation()
      ];
      print('startMRZ:- $config');
      await FlutterAccuraKyc.startMRZ(config)
          .then((value) => {
                setState(() {
                  _result = json.decode(value);
                  print("RESULT:- $_result");
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => ResultScreen(data: _result)));
                })
              })
          .onError((error, stackTrace) => {
                showFlutterToast("Error :" + error.toString())
              });
    } on PlatformException {}
  }

  Future<void> startBarcode() async {
    try {
      var config = [
        {"enableLogs": false},
        this.barcodeSelected["name"],
        getOrientation()
      ];
      print('startBarcode:- $config');
      await FlutterAccuraKyc.startBarcode(config)
          .then((value) => {
                setState(() {
                  _result = json.decode(value);
                  print("RESULT:- $_result");
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => ResultScreen(data: _result)));
                })
              })
          .onError((error, stackTrace) => {
                showFlutterToast("Error :" + error.toString())
              });
    } on PlatformException {}
  }

  Future<void> startBankCard() async {
    try {
      var config = [
        {"enableLogs": false},
        getOrientation()
      ];
      print('startBankCard:- $config');
      await FlutterAccuraKyc.startBankCard(config)
          .then((value) => {
                setState(() {
                  _result = json.decode(value);
                  print("RESULT:- $_result");
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => ResultScreen(data: _result)));
                })
              })
          .onError((error, stackTrace) => {
                showFlutterToast("Error :" + error.toString())
              });
    } on PlatformException {}
  }

  void onChangeMRZ(value) {
    setState(() {
      mrzSelected = mrzList.where((i) => i["label"] == value).first;
    });
  }

  void onChangeBarcode(value) {
    var selected =
        sdkConfig!['barcodes'].where((i) => i['name'] == value).first;
    print("SELECTED:- $selected");
    setState(() {
      barcodeSelected = selected;
    });
  }

  void onChangeCountry(value) {
    var selected =
        sdkConfig!['countries'].where((i) => i['name'] == value).first;
    List<String> tempList = [];
    for (var item in selected['cards']) {
      tempList.add(item['name']);
    }
    setState(() {
      countrySelected = selected;
      cardSelected = {};
      selectedCardString = "";
      ocrCardDropdownOptions = tempList;
    });
  }

  void onChangeCard(value) {
    var selectedCard =
        countrySelected['cards'].where((i) => i['name'] == value).first;
    setState(() {
      cardSelected = selectedCard;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Accura Flutter'),
        backgroundColor: Colors.red[800],
      ),
      body: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage("assets/images/background.png"),
            fit: BoxFit.cover,
          ),
        ),
        child: SingleChildScrollView(
          child: Container(
            padding: EdgeInsets.all(20),
            child: Center(
              child: sdkConfig == null
                  ? CircularProgressIndicator()
                  : !sdkConfig['isValid']
                      ? Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Image.asset(
                              "assets/images/license.png",
                              height: 150,
                              width: 150,
                            ),
                            Text(
                              "License you provided for sacnning is invalid please visit www.accurascan.com for more information.",
                              textAlign: TextAlign.center,
                            ),
                          ],
                        )
                      : Column(
                          children: [
                            sdkConfig['isOCR']
                                ? Container(
                                    decoration: BoxDecoration(
                                        boxShadow: [
                                          BoxShadow(
                                            color: Colors.grey,
                                            blurRadius: 5.0,
                                          ),
                                        ],
                                        color: Colors.white,
                                        borderRadius: BorderRadius.all(
                                            Radius.circular(15))),
                                    padding: EdgeInsets.all(15),
                                    child: Column(
                                      children: [
                                        Text(
                                          'Scan OCR Documents',
                                          style: TextStyle(
                                              fontSize: 20,
                                              fontWeight: FontWeight.bold),
                                        ),
                                        Container(
                                          height: 20,
                                        ),
                                        DropdownSearch<String>(
                                            mode: Mode.MENU,
                                            showSearchBox: true,
                                            showSelectedItems: true,
                                            items: ocrCountryDropdownOptions,
                                            label: "Select Country",
                                            onChanged: (value) =>
                                                onChangeCountry(value),
                                            selectedItem: ""),
                                        Container(
                                          height: 20,
                                        ),
                                        DropdownSearch<String>(
                                            mode: Mode.MENU,
                                            showSelectedItems: true,
                                            items: ocrCardDropdownOptions,
                                            label: "Select Card",
                                            onChanged: (value) =>
                                                onChangeCard(value),
                                            selectedItem: selectedCardString),
                                        Container(
                                          height: 20,
                                        ),
                                        ElevatedButton(
                                          onPressed: countrySelected.length != 0 &&
                                                  cardSelected.length != 0
                                              ? () => {startOCR()}
                                              : null,
                                          style: ElevatedButton.styleFrom(
                                              primary: Colors.red[800]),
                                          child: Text("START SCAN",
                                              style: TextStyle(
                                                color: Colors.white,
                                                fontWeight: FontWeight.bold,
                                              )),
                                        )
                                      ],
                                    ),
                                  )
                                : Container(),
                            Container(
                              height: 20,
                            ),
                            sdkConfig['isMRZ']
                                ? Container(
                                    decoration: BoxDecoration(
                                        boxShadow: [
                                          BoxShadow(
                                            color: Colors.grey,
                                            blurRadius: 5.0,
                                          ),
                                        ],
                                        color: Colors.white,
                                        borderRadius: BorderRadius.all(
                                            Radius.circular(15))),
                                    padding: EdgeInsets.all(15),
                                    child: Column(
                                      children: [
                                        Text(
                                          'Scan MRZ Documents',
                                          style: TextStyle(
                                              fontSize: 20,
                                              fontWeight: FontWeight.bold),
                                        ),
                                        Container(
                                          height: 20,
                                        ),
                                        DropdownSearch<String>(
                                            mode: Mode.MENU,
                                            showSelectedItems: true,
                                            items: mrzDropdownOptions,
                                            label: "Select MRZ Type",
                                            onChanged: (value) =>
                                                onChangeMRZ(value),
                                            selectedItem: ""),
                                        Container(
                                          height: 20,
                                        ),
                                        ElevatedButton(
                                          onPressed: mrzSelected.length != 0
                                              ? () => {startMRZ()}
                                              : null,
                                          style: ElevatedButton.styleFrom(
                                              primary: Colors.red[800]),
                                          child: Text("START SCAN",
                                              style: TextStyle(
                                                color: Colors.white,
                                                fontWeight: FontWeight.bold,
                                              )),
                                        )
                                      ],
                                    ),
                                  )
                                : Container(),

                            Container(
                              height: 20,
                            ),
                            sdkConfig['isBarcode']
                                ? Container(
                                    decoration: BoxDecoration(
                                        boxShadow: [
                                          BoxShadow(
                                            color: Colors.grey,
                                            blurRadius: 5.0,
                                          ),
                                        ],
                                        color: Colors.white,
                                        borderRadius: BorderRadius.all(
                                            Radius.circular(15))),
                                    padding: EdgeInsets.all(15),
                                    child: Column(
                                      children: [
                                        Text(
                                          'Scan Barcode Documents',
                                          style: TextStyle(
                                              fontSize: 20,
                                              fontWeight: FontWeight.bold),
                                        ),
                                        Container(
                                          height: 20,
                                        ),
                                        DropdownSearch<String>(
                                            mode: Mode.MENU,
                                            showSelectedItems: true,
                                            items: barcodeDropdownOptions,
                                            label: "Select Barcode Type",
                                            popupItemDisabled: (String s) =>
                                                s.startsWith('I'),
                                            onChanged: (value) =>
                                                onChangeBarcode(value),
                                            selectedItem: ""),
                                        Container(
                                          height: 20,
                                        ),
                                        ElevatedButton(
                                          onPressed: barcodeSelected.length != 0
                                              ? () => {startBarcode()}
                                              : null,
                                          style: ElevatedButton.styleFrom(
                                              primary: Colors.red[800]),
                                          child: Text("START SCAN",
                                              style: TextStyle(
                                                color: Colors.white,
                                                fontWeight: FontWeight.bold,
                                              )),
                                        )
                                      ],
                                    ),
                                  )
                                : Container(),

                            Container(
                              height: 20,
                            ),
                            sdkConfig['isBankCard']
                                ? Container(
                                    decoration: BoxDecoration(
                                        boxShadow: [
                                          BoxShadow(
                                            color: Colors.grey,
                                            blurRadius: 5.0,
                                          ),
                                        ],
                                        color: Colors.white,
                                        borderRadius: BorderRadius.all(
                                            Radius.circular(15))),
                                    padding: EdgeInsets.all(15),
                                    child: Column(
                                      children: [
                                        Text(
                                          'Scan Bankcard',
                                          style: TextStyle(
                                              fontSize: 20,
                                              fontWeight: FontWeight.bold),
                                        ),
                                        Container(
                                          height: 20,
                                        ),
                                        Text(
                                          'You can scan any bank card here by tap on "START SCAN" button.',
                                          textAlign: TextAlign.center,
                                          style: TextStyle(
                                              fontSize: 15,
                                              fontWeight: FontWeight.bold,
                                              color: Colors.grey[600]),
                                        ),
                                        Container(
                                          height: 20,
                                        ),
                                        ElevatedButton(
                                          onPressed: () => {startBankCard()},
                                          style: ElevatedButton.styleFrom(
                                              primary: Colors.red[800]),
                                          child: Text("START SCAN",
                                              style: TextStyle(
                                                color: Colors.white,
                                                fontWeight: FontWeight.bold,
                                              )),
                                        )
                                      ],
                                    ),
                                  )
                                : Container(),
                          ],
                        ),
            ),
          ),
        ),
      ),
    );
  }
}
1 回复

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


在Flutter应用中集成身份验证和KYC(Know Your Customer)审核功能,可以使用 flutter_accura_kyc 插件。这个插件通常用于与AccuraScan的KYC服务集成,以进行身份证件验证、人脸识别等操作。以下是如何使用 flutter_accura_kyc 插件的步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 flutter_accura_kyc 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_accura_kyc: ^1.0.0  # 请使用最新版本

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

2. 配置插件

android/app/build.gradle 文件中,确保 minSdkVersion 至少为 21:

android {
    defaultConfig {
        minSdkVersion 21
        ...
    }
    ...
}

3. 初始化插件

在你的Flutter应用中初始化 flutter_accura_kyc 插件。通常,你需要在 main.dart 或某个初始化文件中进行初始化。

import 'package:flutter_accura_kyc/flutter_accura_kyc.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化Accura KYC
  await FlutterAccuraKyc.initialize(
    licenseKey: 'YOUR_LICENSE_KEY',  // 从AccuraScan获取的许可证密钥
    country: 'US',  // 默认国家代码
    isShowLogs: true,  // 是否显示日志
  );

  runApp(MyApp());
}

4. 启动KYC流程

在你的应用中,你可以通过调用 startKyc 方法来启动KYC流程。通常,你会在用户点击某个按钮时触发这个流程。

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

class KycScreen extends StatelessWidget {
  Future<void> startKyc() async {
    try {
      final result = await FlutterAccuraKyc.startKyc(
        country: 'US',  // 国家代码
        documentType: 'PASSPORT',  // 证件类型,如PASSPORT, DRIVING_LICENSE等
        isShowLogs: true,
      );

      // 处理KYC结果
      print('KYC Result: $result');
    } catch (e) {
      print('KYC Error: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('KYC Verification'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: startKyc,
          child: Text('Start KYC'),
        ),
      ),
    );
  }
}

5. 处理KYC结果

startKyc 方法会返回一个包含KYC结果的对象。你可以根据返回的结果进行进一步的处理,例如将结果发送到服务器或显示给用户。

final result = await FlutterAccuraKyc.startKyc(
  country: 'US',
  documentType: 'PASSPORT',
  isShowLogs: true,
);

if (result['status'] == 'SUCCESS') {
  // KYC成功
  print('KYC Successful: ${result['data']}');
} else {
  // KYC失败
  print('KYC Failed: ${result['error']}');
}

6. 其他功能

flutter_accura_kyc 插件可能还提供其他功能,例如人脸识别、OCR(光学字符识别)等。你可以根据插件的文档来使用这些功能。

7. 注意事项

  • 许可证密钥:你需要从AccuraScan获取有效的许可证密钥。
  • 网络连接:KYC流程通常需要网络连接,确保设备在启动KYC时处于联网状态。
  • 权限:确保你的应用已经请求了必要的权限,例如相机权限、存储权限等。

8. 调试与日志

在开发过程中,你可以启用日志来帮助调试。通过设置 isShowLogstrue,你可以在控制台中看到详细的日志信息。

await FlutterAccuraKyc.initialize(
  licenseKey: 'YOUR_LICENSE_KEY',
  country: 'US',
  isShowLogs: true,
);

9. 发布应用

在发布应用之前,确保你已经禁用了调试日志,并且使用了正确的生产环境许可证密钥。

await FlutterAccuraKyc.initialize(
  licenseKey: 'YOUR_PRODUCTION_LICENSE_KEY',
  country: 'US',
  isShowLogs: false,
);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!