Flutter身份验证与KYC插件vtcc_ekyc_flutter的使用

Flutter身份验证与KYC插件vtcc_ekyc_flutter的使用

本项目是一个基于Flutter的插件包,用于实现身份验证和KYC(Know Your Customer)功能。该插件包包括了适用于Android和iOS平台的具体实现代码。

开始使用

要开始使用vtcc_ekyc_flutter插件,请确保你已经安装了Flutter开发环境,并且了解如何创建一个新的Flutter项目。

初始化项目

首先,创建一个新的Flutter项目:

flutter create vtcc_ekyc_example
cd vtcc_ekyc_example

然后,在你的pubspec.yaml文件中添加vtcc_ekyc_flutter依赖项:

dependencies:
  flutter:
    sdk: flutter
  vtcc_ekyc_flutter: ^1.0.0  # 请根据实际版本进行替换

运行flutter pub get来获取依赖项。

示例代码

以下是完整的示例代码,展示了如何在Flutter应用中使用vtcc_ekyc_flutter插件。

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
import 'package:vtcc_ekyc_flutter/models/config/ekyc_config.dart';
import 'package:vtcc_ekyc_flutter/models/kyc_result.dart';
import 'package:vtcc_ekyc_flutter/models/kyc_ui_result.dart';
import 'package:vtcc_ekyc_flutter/vtcc_ekyc_flutter.dart';
import 'package:vtcc_ekyc_flutter/vtcc_ekyc_flutter_method_channel.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TestPage(),
    );
  }
}

class TestPage extends StatefulWidget {
  [@override](/user/override)
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  String _platformVersion = 'Unknown';

  final _vtccEkycFlutterPlugin = VtccEkycFlutter();
  final channel = MethodChannelVtccEkycFlutter();
  final trackingLogs = <String>[].toList(growable: true);

  var isResultModalVisible = false;

  var isTrackingLogVisible = false;

  KycUIResult? ekycUIResult;
  KycResult? ekycResult;

  var normalFlow = FlowType.EKYC_FULL;

  var uiFlow = UiFlowType.ID_CARD_FRONT;

  var sdkType = SdkType.UI_ONLY;

  var isShowAutoCaptureButton = true;

  var autoCaptureMode = true;

  var isDebug = false;

  var isShowHelp = true;

  var isEnableVoiceHelp = true;

  var flashMode = true;

  var isDefaultBackground = true;

  var isDefaultPopupBackground = true;

  var isDefaultButtonColor = true;

  var isDefaultText = true;

  var isSkipConfirmScreen = false;

  var isImageId = false;

  var isCacheImage = false;

  var isCacheVideo = false;

  var isSmallButtonRadius = false;

  var isTestFont = false;

  var zoomLevel = 1;

  var iouThreshold = 0.92;

  var iouCaptureTime = 1000;

  var idCardBoxPercentage = 0.025;

  var proxyUrl = 'http://ekyc.spower.asia';

  var token =
      'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJzcG93ZXIiLCJpYXQiOjE2NzgxMTk2NDUsImV4cCI6Mjg4NzcxOTY0NX0.chpQiH_vlgiCUeLZO30C1YZvUzH7eV6F7SyNqIFyE5qcPZOCLMIfTO9hznXXRogB8DC1YLSs3-46xCIVbUEJOw';

  var requestId = '';

  var xRequestId = '';

  var clientCode = 'spower';

  var userId = '02323123213';

  var userIdType = UserIdType.PHONE_NUM_TYPE;

  var isCardQualityCheck = true;

  var isCardSpoofCheck = true;

  var isIdCardAbbr = true;

  var idCardMinRatio = 0.6;

  var cardRetakeLimit = 10;

  var frontIdCardId = 'j21sss21321e3';

  var idCardCameraMode = CameraMode.BACK;

  var idCardTypes = <IdCardType>[IdCardType.CMND, IdCardType.CCCD];

  var isFaceSearch = false;

  var isFaceSave = false;

  var isFaceUpdate = false;

  var isFaceQuality = true;

  var isFaceLiveness = true;

  var faceRetakeLimit = 10;

  var faceMinRatio = 0.25;

  var faceMaxRatio = 0.7;

  var selfieCameraMode = CameraMode.FRONT;

  var isAdvancedLiveness = true;

  var isAdvancedLivenessFaceMatching = false;

  var leftAngle = 30;

  var rightAngle = 30;

  var challengeRetakeLimit = 4;

  var advancedDuration = 20;

  var faceGuideUrl = 'https://api24cdn.vtmoney.vn/vtmoney3.mov';

  var isNfcChipVerify = false;

  var isNfc = false;

  var nfcCardNumber = '038096005533';

  var nfcBirthDate = '07/08/1996';

  var nfcExpiredDate = '07/08/2036';

  [@override](/user/override)
  void initState() {
    super.initState();
    initPlatformState();
    channel.registerTracking(onTracking);
  }

  void onTracking(Map<String, dynamic> trackObject) {
    final now = DateTime.now();
    String formatter = DateFormat.Hms().format(now); // 28/03/2020
    trackingLogs.add(formatter);
    trackingLogs.add(jsonEncode(trackObject));
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      platformVersion = "Fuck";
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  void startEkyc() async {
    trackingLogs.clear();

    final advancedConfig = AdvancedLivenessConfig(
      leftAngle: leftAngle,
      rightAngle: rightAngle,
      challengeRetakeLimit: challengeRetakeLimit,
      duration: advancedDuration,
    );

    final nfcUiConfig = NfcUiConfig(
      idNumber: nfcCardNumber,
      expiredDate: nfcExpiredDate,
      birthDate: nfcBirthDate,
    );

    // const idCardTypesStr = idCardTypes.filter(item => item.checked).map(item => item.name as IdCardType);

    final fontConfig = FontConfig(
      regularFontName: 'RobotoMono-Regular',
      regularFontSize: 14,
      boldFontName: 'RobotoMono-Bold',
      boldFontSize: 14,
    );

    final config = EkycConfig(
      advancedGuideVideoUrl: faceGuideUrl,
      advancedLivenessConfig: advancedConfig,
      autoCaptureMode: autoCaptureMode,
      backgroundColor: isDefaultBackground ? '#66000000' : '#FFB84C',
      buttonColor: isDefaultButtonColor ? '#EE0033' : '#FFB84C',
      popupBackgroundColor: isDefaultPopupBackground ? '#EFEFEE' : '#EDE7F6',
      textColor: isDefaultText ? '#FFFFFF' : '#1B9C85',
      cardRetakeLimit: cardRetakeLimit,
      clientCode: clientCode,
      enableVoiceHelp: isEnableVoiceHelp,
      faceMaxRatio: faceMaxRatio,
      faceMinRatio: faceMinRatio,
      faceRetakeLimit: faceRetakeLimit,
      flash: flashMode,
      flowType: normalFlow,
      frontIdCardId: frontIdCardId,
      idCardAbbr: isIdCardAbbr,
      idCardBoxPercentage: idCardBoxPercentage,
      idCardCameraMode: idCardCameraMode,
      idCardMinRatio: idCardMinRatio,
      idCardTypes: idCardTypes,
      isAdvancedLiveness: isAdvancedLiveness,
      isAdvancedMatching: isAdvancedLivenessFaceMatching,
      isCacheImage: isCacheImage,
      isCardQualityCheck: isCardQualityCheck,
      isCardSpoofCheck: isCardSpoofCheck,
      isDebug: isDebug,
      isFaceLiveness: isFaceLiveness,
      isFaceQuality: isFaceQuality,
      isFaceSave: isFaceSave,
      isFaceSearch: isFaceSearch,
      isFaceUpdate: isFaceUpdate,
      isImageId: isImageId,
      isNfc: isNfc,
      isSaveVideo: isCacheVideo,
      nfcUiConfig: nfcUiConfig,
      nfcVerifyOption:
          isNfcChipVerify ? NfcVerifyOption.CHIP_DATA_VERIFY : NfcVerifyOption.FACE_VERIFY,
      proxyUrl: proxyUrl,
      requestId: requestId,
      sdkType: sdkType,
      selfieCameraMode: selfieCameraMode,
      showAutoCaptureButton: isShowAutoCaptureButton,
      showHelp: isShowHelp,
      skipConfirmScreen: isSkipConfirmScreen,
      uiFlowType: uiFlow,
      userId: userId,
      userIdType: userIdType,
      xRequestId: xRequestId,
      zoom: zoomLevel,
      token: token,
      iouThreshold: iouThreshold,
      iouCaptureTime: iouCaptureTime,
      fontConfig: isTestFont ? fontConfig : null,
      buttonCornerRadius: isSmallButtonRadius ? 12 : null,
    );

    try {
      if (sdkType == SdkType.UI_ONLY) {
        final result = await channel.startUIOnlyFlow(config);
        ekycUIResult = result;
      } else {
        final result = await channel.startNormalFlow(config);
        ekycResult = result;
      }
    } on Exception catch (e) {
      final a = e;
    }
  }

  void openResult(BuildContext context) {
    if (sdkType == SdkType.UI_ONLY) {
      showDialogForUIOnly();
    } else {
      showDialogForNormalOnly();
    }
  }

  void showDialogForNormalOnly() {
    if (ekycResult == null) {
      return;
    }

    final result = ekycResult!;

    final localFrontCardFullImage = result.localFrontCardFullImage ?? "";
    final localBackCardFullImage = result.localBackCardFullImage ?? "";
    final localFaceFullImage = result.localFaceFullImage ?? "";
    final localFrontIdCardUploadImage = result.localFrontIdCardUploadImage ?? "";
    final localBackIdCardUploadImage = result.localBackIdCardUploadImage ?? "";
    final localFaceUploadImage = result.localFaceUploadImage ?? "";

    result.localFrontCardFullImage = '';
    result.localBackCardFullImage = '';
    result.localFaceFullImage = '';
    result.localFrontIdCardUploadImage = '';
    result.localBackIdCardUploadImage = '';
    result.localFaceUploadImage = '';

    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext builder) {
        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          title: const Text("Kết quả EKYC"),
          content: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Text(
                  jsonEncode(result.toJson()),
                  textAlign: TextAlign.left,
                ),
                createImage("localFrontCardFullImage", localFrontCardFullImage),
                createImage("localBackCardFullImage", localBackCardFullImage),
                createImage("localFaceFullImage", localFaceFullImage),
                createImage("localFrontIdCardUploadImage", localFrontIdCardUploadImage),
                createImage("localBackIdCardUploadImage", localBackIdCardUploadImage),
                createImage("localFaceUploadImage", localFaceUploadImage),
              ],
            ),
          ),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('OK'),
            ),
          ],
        );
      },
    );
  }

  void showDialogForUIOnly() {
    if (ekycUIResult == null) {
      return;
    }

    final result = ekycUIResult!;

    final localCroppedImage = result.localCroppedImage ?? "";
    result.localCroppedImage = "";
    final localFullImage = result.localFullImage ?? "";
    result.localFullImage = "";

    String left = "";
    String right = "";
    if (result.advanceImageDataList != null && result.advanceImageDataList!.isNotEmpty) {
      left = result.advanceImageDataList![0].localImage ?? "";
      right = result.advanceImageDataList![1].localImage ?? "";

      result.advanceImageDataList![0].localImage = '';
      result.advanceImageDataList![1].localImage = '';
    }

    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext builder) {
        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          title: const Text("Kết quả EKYC"),
          content: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Text(
                  jsonEncode(result.toJson()),
                  textAlign: TextAlign.left,
                ),
                createImage("Ảnh crop", localCroppedImage),
                createImage("Ảnh Full", localFullImage),
                createImage("Ảnh Quay Trái", left),
                createImage("Ảnh Quay Phải", right),
              ],
            ),
          ),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('OK'),
            ),
          ],
        );
      },
    );
  }

  void showTracking() {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext builder) {
        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          title: const Text("Kết quả Tracking"),
          content: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: trackingLogs
                  .map(
                    (e) => Text(
                      e,
                      textAlign: TextAlign.left,
                    ),
                  )
                  .toList(),
            ),
          ),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('OK'),
            ),
          ],
        );
      },
    );
  }

  final normalFlows = FlowType.values.map((e) => e.name).toList(growable: false);

  final uiFlows = UiFlowType.values.map((e) => e.name).toList(growable: false);

  final sdkTypes = SdkType.values.map((e) => e.name).toList(growable: false);

  final userIdTypes = UserIdType.values.map((e) => e.name).toList(growable: false);

  final cameraModes = CameraMode.values.map((e) => e.name).toList(growable: false);

  final _items =
      IdCardType.values.map((card) => MultiSelectItem<String>(card.name, card.name)).toList();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Plugin example app'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              createButton("Start EKYC", startEkyc),
              createButton("Open Result", () {
                openResult(context);
              }),
              createButton("Show Tracking", showTracking),
              Container(
                width: double.infinity,
                color: Colors.yellow,
                padding: const EdgeInsets.only(top: 16, bottom: 8),
                child: const Text(
                  "Config chung",
                  style: TextStyle(fontSize: 20),
                ),
              ),
              createSelect("Normal Flow Type", normalFlow.name, normalFlows, (value) {
                normalFlow = FlowType.values.firstWhere((element) => element.name == value);
              }),
              createSelect("Ui Flow Type", uiFlow.name, uiFlows, (value) {
                uiFlow = UiFlowType.values.firstWhere((element) => element.name == value);
              }),
              createSelect("SDK Type", sdkType.name, sdkTypes, (value) {
                sdkType = SdkType.values.firstWhere((element) => element.name == value);
              }),
              createSwitch("Show Auto Capture Button", isShowAutoCaptureButton, (value) {
                isShowAutoCaptureButton = value;
              }),
              createSwitch("Auto Capture Mode", autoCaptureMode, (value) {
                autoCaptureMode = value;
              }),
              createSwitch("Debug", isDebug, (value) {
                isDebug = value;
              }),
              createSwitch("Show Help", isShowHelp, (value) {
                isShowHelp = value;
              }),
              createSwitch("Enable Voice Help", isEnableVoiceHelp, (value) {
                isEnableVoiceHelp = value;
              }),
              createSwitch("Flash Mode On", flashMode, (value) {
                flashMode = value;
              }),
              createSwitch("Default Background", isDefaultBackground, (value) {
                isDefaultBackground = value;
              }),
              createSwitch("Default Popup Background Color", isDefaultPopupBackground, (value) {
                isDefaultPopupBackground = value;
              }),
              createSwitch("Default Button Color", isDefaultButtonColor, (value) {
                isDefaultButtonColor = value;
              }),
              createSwitch("Default Text", isDefaultText, (value) {
                isDefaultText = value;
              }),
              createSwitch("Skip Confirm Screen", isSkipConfirmScreen, (value) {
                isSkipConfirmScreen = value;
              }),
              createSwitch("Image Id", isImageId, (value) {
                isImageId = value;
              }),
              createSwitch("Cache Image", isCacheImage, (value) {
                isCacheImage = value;
              }),
              createSwitch("Save Video", isCacheVideo, (value) {
                isCacheVideo = value;
              }),
              createSwitch("Test Small Button Radius", isSmallButtonRadius, (value) {
                isSmallButtonRadius = value;
              }),
              createSwitch("Test Another Font", isTestFont, (value) {
                isTestFont = value;
              }),
              createInput("Zoom Level", zoomLevel.toString(), (value) {
                zoomLevel = int.parse(value);
              }),
              createInput("IOU Threshold", iouThreshold.toString(), (value) {
                iouThreshold = double.parse(value);
              }),
              createInput("IOU Capture Time", iouCaptureTime.toString(), (value) {
                iouCaptureTime = int.parse(value);
              }),
              createInput("IdCard Capture Box", idCardBoxPercentage.toString(), (value) {
                idCardBoxPercentage = double.parse(value);
              }),
              createInput("IdCard Capture Box", idCardBoxPercentage.toString(), (value) {
                idCardBoxPercentage = double.parse(value);
              }),
              Container(
                width: double.infinity,
                color: Colors.yellow,
                padding: const EdgeInsets.only(top: 16, bottom: 16),
                margin: const EdgeInsets.only(top: 16, bottom: 16),
                child: const Text(
                  "Config Authentication",
                  style: TextStyle(fontSize: 20),
                ),
              ),
              createInput("Proxy Url", proxyUrl, (value) {
                proxyUrl = value;
              }),
              createInput("Client Code", clientCode, (value) {
                clientCode = value;
              }),
              createInput("Token", token, (value) {
                token = value;
              }),
              createInput("Request Id", requestId, (value) {
                requestId = value;
              }),
              createInput("X Request Id", xRequestId, (value) {
                xRequestId = value;
              }),
              createInput("User Id", userId, (value) {
                userId = value;
              }),
              createSelect("User Id Type", userIdType.name, userIdTypes, (value) {
                userIdType = UserIdType.values.firstWhere((element) => element.name == value);
              }),
              Container(
                width: double.infinity,
                color: Colors.yellow,
                padding: const EdgeInsets.only(top: 16, bottom: 16),
                margin: const EdgeInsets.only(top: 16, bottom: 16),
                child: const Text(
                  "Card Config",
                  style: TextStyle(fontSize: 20),
                ),
              ),
              MultiSelectDialogField(
                onConfirm: (val) {
                  idCardTypes = IdCardType.values
                      .where(
                          (element) => val.where((element1) => element1 == element.name).isNotEmpty)
                      .toList();
                  // _selectedAnimals5 = val;
                },
                // dialogWidth: MediaQuery.of(context).size.width * 0.7,
                items: _items,
                initialValue: idCardTypes
                    .map((e) => e.name)
                    .toList(), // setting the value of this in initState() to pre-select values.
              ),
              createSelect("Card Camera", idCardCameraMode.name, cameraModes, (value) {
                idCardCameraMode = CameraMode.values.firstWhere((element) => element.name == value);
              }),
              createSwitch("Card Quality Check", isCardQualityCheck, (value) {
                isCardQualityCheck = value;
              }),
              createSwitch("Card Spoof Check", isCardSpoofCheck, (value) {
                isCardSpoofCheck = value;
              }),
              createSwitch("Card Abbr", isIdCardAbbr, (value) {
                isIdCardAbbr = value;
              }),
              createInput("Card Retake Limit", cardRetakeLimit.toString(), (value) {
                cardRetakeLimit = int.parse(value);
              }),
              createInput("Card Min Ratio", idCardMinRatio.toString(), (value) {
                idCardMinRatio = double.parse(value);
              }),
              createInput("Front Card Image Id", frontIdCardId, (value) {
                frontIdCardId = value;
              }),
              Container(
                width: double.infinity,
                color: Colors.yellow,
                padding: const EdgeInsets.only(top: 16, bottom: 16),
                margin: const EdgeInsets.only(top: 16, bottom: 16),
                child: const Text(
                  "Face Config",
                  style: TextStyle(fontSize: 20),
                ),
              ),
              createSwitch("Face Quality Check", isFaceQuality, (value) {
                isFaceQuality = value;
              }),
              createSwitch("Face Liveness", isFaceLiveness, (value) {
                isFaceLiveness = value;
              }),
              createSwitch("Face Search", isFaceSearch, (value) {
                isFaceSearch = value;
              }),
              createSwitch("Face Save", isFaceSave, (value) {
                isFaceSave = value;
              }),
              createSwitch("Face Update", isFaceUpdate, (value) {
                isFaceUpdate = value;
              }),
              createSelect("Selfie Camera", selfieCameraMode.name, cameraModes, (value) {
                selfieCameraMode = CameraMode.values.firstWhere((element) => element.name == value);
              }),
              createInput("Face Retake Limit", faceRetakeLimit.toString(), (value) {
                faceRetakeLimit = int.parse(value);
              }),
              createInput("Face Min Ratio", faceMinRatio.toString(), (value) {
                faceMinRatio = double.parse(value);
              }),
              createInput("Face Max Ratio", faceMaxRatio.toString(), (value) {
                faceMaxRatio = double.parse(value);
              }),
              Container(
                width: double.infinity,
                color: Colors.yellow,
                padding: const EdgeInsets.only(top: 16, bottom: 16),
                margin: const EdgeInsets.only(top: 16, bottom: 16),
                child: const Text(
                  "Face Advanced Config",
                  style: TextStyle(fontSize: 20),
                ),
              ),
              createSwitch("Advanced Liveness", isAdvancedLiveness, (value) {
                isAdvancedLiveness = value;
              }),
              createSwitch("Advanced Liveness FaceMatching", isAdvancedLivenessFaceMatching,
                  (value) {
                isAdvancedLivenessFaceMatching = value;
              }),
              createInput("Left Angle", leftAngle.toString(), (value) {
                leftAngle = int.parse(value);
              }),
              createInput("Right Angle", rightAngle.toString(), (value) {
                rightAngle = int.parse(value);
              }),
              createInput("Challenge Retake Limit", challengeRetakeLimit.toString(), (value) {
                challengeRetakeLimit = int.parse(value);
              }),
              createInput("Advanced Liveness Duration", advancedDuration.toString(), (value) {
                advancedDuration = int.parse(value);
              }),
              createInput("Advanced Guide - Video URL", faceGuideUrl, (value) {
                faceGuideUrl = value;
              }),
              Container(
                width: double.infinity,
                color: Colors.yellow,
                padding: const EdgeInsets.only(top: 16, bottom: 16),
                margin: const EdgeInsets.only(top: 16, bottom: 16),
                child: const Text(
                  "NFC Config",
                  style: TextStyle(fontSize: 20),
                ),
              ),
              createSwitch("Nfc Chip Data Verify", isNfcChipVerify, (value) {
                isNfcChipVerify = value;
              }),
              createSwitch("Is NFC", isNfc, (value) {
                isNfc = value;
              }),
              createInput("NFC ID Card Number", nfcCardNumber, (value) {
                nfcCardNumber = value;
              }),
              createInput("Birthday dd/mm/yyyy", nfcBirthDate, (value) {
                nfcBirthDate = value;
              }),
              createInput("Expired Date dd/mm/yyyy", nfcExpiredDate, (value) {
                nfcExpiredDate = value;
              }),
            ],
          ),
        ),
      ),
    );
  }

  Widget createImage(String text, String imageData) {
    if (imageData.isEmpty) {
      return const SizedBox();
    }
    return Column(
      children: [Text(text), Image.memory(base64Decode(imageData))],
    );
  }

  Widget createButton(String text, VoidCallback t) {
    return SizedBox(
      width: double.infinity,
      child: ElevatedButton(onPressed: t, child: Text(text)),
    );
  }

  Widget createInput(String text, String initValue, ValueChanged<String> t) {
    return Column(
      children: [
        Text(text),
        TextFormField(
          initialValue: initValue,
          decoration: InputDecoration(
            hintText: text,
            border: OutlineInputBorder(borderSide: BorderSide(color: Colors.blue, width: 1)),
          ),
          onChanged: (value) {
            t.call(value);
          },
        ),
      ],
    );
  }

  Widget createSelect(
      String text, String selectedItem, List<String> values, ValueChanged<String> t) {
    return Row(children: [
      Expanded(
        flex: 2,
        child: Text(text),
      ),
      DropdownButton<String>(
        value: selectedItem,
        elevation: 16,
        style: const TextStyle(color: Colors.deepPurple),
        underline: Container(
          height: 2,
          color: Colors.deepPurpleAccent,
        ),
        onChanged: (String? value) {
          // This is called when the user selects an item.
          setState(() {
            if (value != null) {
              t.call(value);
            }
          });
        },
        items: values.map<DropdownMenuItem<String>>((String value) {
          return DropdownMenuItem<String>(
            value: value,
            child: Text(value),
          );
        }).toList(),
      )
    ]);
  }

  Widget createSwitch(String text, bool value, ValueChanged<bool> t) {
    return Row(
      children: [
        Expanded(
          flex: 4,
          child: Text(text, softWrap: true),
        ),
        Switch(
          // This bool value toggles the switch.
          value: value,
          activeColor: Colors.red,
          onChanged: (bool value) {
            // This is called when the user toggles the switch.
            setState(() {
              t.call(value);
            });
          },
        ),
      ],
    );
  }
}

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

1 回复

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


vtcc_ekyc_flutter 是一个用于在 Flutter 应用中集成身份验证和 KYC(Know Your Customer)功能的插件。这个插件通常与第三方服务(如 VTCC)集成,以提供身份验证、人脸识别、身份证验证等功能。以下是如何在 Flutter 应用中使用 vtcc_ekyc_flutter 插件的步骤。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  vtcc_ekyc_flutter: ^1.0.0  # 请根据实际情况使用最新版本

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

2. 配置插件

在使用插件之前,可能需要进行一些配置,例如设置 API 密钥或配置服务端地址。这些配置通常可以在插件的文档中找到。

3. 初始化插件

在应用的 main.dart 或适当的位置初始化插件:

import 'package:vtcc_ekyc_flutter/vtcc_ekyc_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化插件
  await VtccEkycFlutter.initialize(
    apiKey: 'your_api_key',  // 替换为你的 API 密钥
    baseUrl: 'https://your-api-endpoint.com',  // 替换为你的 API 地址
  );

  runApp(MyApp());
}

4. 使用插件进行身份验证和 KYC

在需要执行身份验证或 KYC 的地方调用插件的相应方法。以下是一些常见的操作示例:

4.1. 人脸识别

try {
  final result = await VtccEkycFlutter.faceRecognition(
    imagePath: 'path_to_image',  // 替换为图像路径
  );
  print('Face Recognition Result: $result');
} catch (e) {
  print('Error during face recognition: $e');
}

4.2. 身份证验证

try {
  final result = await VtccEkycFlutter.idCardVerification(
    frontImagePath: 'path_to_front_image',  // 替换为身份证正面图像路径
    backImagePath: 'path_to_back_image',  // 替换为身份证背面图像路径
  );
  print('ID Card Verification Result: $result');
} catch (e) {
  print('Error during ID card verification: $e');
}

4.3. 活体检测

try {
  final result = await VtccEkycFlutter.livenessDetection(
    imagePath: 'path_to_image',  // 替换为图像路径
  );
  print('Liveness Detection Result: $result');
} catch (e) {
  print('Error during liveness detection: $e');
}

5. 处理结果

插件通常会返回一个包含验证结果的 Map 或自定义对象。你可以根据这些结果来决定应用的下一步操作。

if (result['status'] == 'success') {
  // 验证成功,继续后续操作
} else {
  // 验证失败,显示错误信息
}

6. 错误处理

确保在使用插件时捕获并处理可能出现的错误。这有助于提高应用的健壮性。

try {
  final result = await VtccEkycFlutter.faceRecognition(
    imagePath: 'path_to_image',
  );
  print('Face Recognition Result: $result');
} catch (e) {
  print('Error during face recognition: $e');
}
回到顶部