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

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

本示例展示了如何在Flutter项目中使用vtcc_ekyc_flutter插件来实现身份验证和KYC(Know Your Customer)功能。

开始使用

本项目是一个用于Flutter平台的插件包,包含适用于Android和/或iOS的平台特定实现代码。以下是一些帮助你开始使用Flutter开发的资源:

  • 官方文档:在线文档,提供教程、示例、移动开发指导以及完整的API参考。

示例代码

以下是使用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/models/config/ekyc_config.dart';
import 'package:vtcc_ekyc/models/kyc_result.dart';
import 'package:vtcc_ekyc/models/kyc_ui_result.dart';
import 'package:vtcc_ekyc/vtcc_ekyc_flutter.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 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 isRestricted = true;

  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();
    _vtccEkycFlutterPlugin.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));
  }

  // 平台消息异步,因此我们初始化在一个异步方法中。
  Future<void> initPlatformState() async {
    String platformVersion;
    // 平台消息可能会失败,所以我们使用一个try/catch PlatformException。
    // 我们还处理了消息可能返回null的情况。
    try {
      platformVersion = "Fuck";
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // 如果小部件在异步平台消息飞行时从树中被移除,我们应该丢弃回复而不是调用setState来更新我们的不存在的外观。
    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 faceAdvancedMode = isRestricted
        ? FaceAdvancedMode.RESTRICTED
        : FaceAdvancedMode.UNRESTRICTED;

    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,
      faceAdvancedMode: faceAdvancedMode,
      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 _vtccEkycFlutterPlugin.startUIOnlyFlow(config);
        ekycUIResult = result;
      } else {
        final result = await _vtccEkycFlutterPlugin.startNormalFlow(config);
        ekycResult = result;
      }

      openResult(context);
    } 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);
              }),
              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("Is Restricted Mode", isRestricted, (value) {
                isRestricted = value;
              }),
              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的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


在Flutter应用中集成身份验证和KYC(Know Your Customer)功能,通常需要使用第三方插件或SDK。vtcc_ekyc 是一个用于越南市场的KYC插件,它可以帮助开发者快速集成KYC功能到Flutter应用中。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 vtcc_ekyc 插件的依赖。

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

然后运行 flutter pub get 来获取依赖。

2. 初始化插件

在使用 vtcc_ekyc 之前,通常需要进行初始化。你可以在 main.dart 或其他适当的地方进行初始化。

import 'package:vtcc_ekyc/vtcc_ekyc.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化vtcc_ekyc
  await VtccEkyc.initialize(
    apiKey: 'your_api_key',
    apiSecret: 'your_api_secret',
  );
  
  runApp(MyApp());
}

3. 使用 vtcc_ekyc 进行身份验证和KYC

vtcc_ekyc 提供了多种方法来进行身份验证和KYC操作。以下是一个简单的示例,展示如何使用 vtcc_ekyc 进行身份证验证。

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

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

class _KYCVerifyPageState extends State<KYCVerifyPage> {
  String _verificationResult = '';

  Future<void> _verifyIDCard() async {
    try {
      // 调用vtcc_ekyc进行身份证验证
      final result = await VtccEkyc.verifyIDCard(
        frontImagePath: 'path_to_front_image',
        backImagePath: 'path_to_back_image',
      );

      setState(() {
        _verificationResult = result ? '验证成功' : '验证失败';
      });
    } catch (e) {
      setState(() {
        _verificationResult = '验证失败: $e';
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('KYC 验证'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: _verifyIDCard,
              child: Text('验证身份证'),
            ),
            SizedBox(height: 20),
            Text(_verificationResult),
          ],
        ),
      ),
    );
  }
}
回到顶部