innova_id_verify 0.0.2 copy "innova_id_verify: ^0.0.2" to clipboard
innova_id_verify: ^0.0.2 copied to clipboard

A Flutter plugin for ID verification

example/lib/main.dart

import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'dart:math';
import 'package:innova_id_verify/innova_id_verify.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: HomeScreen());
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
          colors: [
            const Color(0xFF60CFFF),
            const Color.fromARGB(255, 197, 238, 255),
          ],
        ),
      ),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        appBar: AppBar(
          toolbarHeight: 100,
          backgroundColor: Colors.transparent,
          // centerTitle: true,
          actions: [
            SizedBox(height: 60, child: Image.asset('lib/assets/logo.png')),
            SizedBox(
              width: 15,
            )
          ],
          title: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(
                height: 15,
              ),
              const Text(
                'InnoKYC',
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: 32),
              ),
              const Text(
                'Secure, real-time identity verification.',
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: 16),
              ),
            ],
          ),
        ),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SizedBox(
                  height: 20,
                ),
                CarouselSlider(
                    items: [
                      _buildCarouselItem(
                          'lib/assets/liveliness.jpg',
                          'Liveliness Detection',
                          'Detects liveness through blink\nand head movements.'),
                      _buildCarouselItem('lib/assets/ocr.jpg', 'OCR Reading',
                          'Extracts key details like ID\nnumber and name.'),
                      _buildCarouselItem(
                          'lib/assets/tamper.jpg',
                          'Tamper Detection',
                          'Detects alterations made\nto the ID card.'),
                      _buildCarouselItem(
                          'lib/assets/image-extraction.jpg',
                          'Image Extraction',
                          'Extracts the face photo\nfrom the ID card.'),
                      _buildCarouselItem(
                          'lib/assets/face-matching.jpg',
                          'Face Matching',
                          'Compares ID card face\nphoto with selfie.'),
                    ],
                    options: CarouselOptions(
                      height: 200,
                      aspectRatio: 9 / 16,
                      viewportFraction: 0.85,
                      initialPage: 0,
                      enableInfiniteScroll: true,
                      reverse: false,
                      autoPlay: true,
                      autoPlayInterval: Duration(seconds: 3),
                      autoPlayAnimationDuration: Duration(seconds: 2),
                      autoPlayCurve: Curves.fastOutSlowIn,
                      enlargeCenterPage: true,
                      enlargeFactor: 0.2,
                      scrollDirection: Axis.horizontal,
                    )),
              ],
            )
          ],
        ),
        bottomNavigationBar: BottomAppBar(
          color: Colors.transparent,
          child: Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.15), // Shadow color
                  offset: Offset(0, 4), // Shadow position (x, y)
                  blurRadius: 3, // Spread of the shadow
                  spreadRadius: 0, // How much the shadow spreads (optional)
                ),
              ],
              gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [
                  const Color.fromARGB(255, 255, 162, 62),
                  const Color(0xFFFDBA74),
                ],
              ),
            ),
            width: double.infinity,
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(
                elevation: 0,
                backgroundColor: Colors.transparent,
                foregroundColor: Colors.white,
              ),
              onPressed: () {
                try {
                  Navigator.of(context, rootNavigator: true)
                      .pushReplacement(MaterialPageRoute(
                    builder: (context) => const ImageDisplayScreen(),
                  ));
                } catch (e) {
                  print("Error navigating to ImageDisplayScreen: $e");
                }
              },
              child: Text('Launch eKYC',
                  style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                      fontSize: 18)),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildCarouselItem(
      String imagePath, String title, String description) {
    return Stack(
      children: [
        ClipRRect(
          borderRadius: BorderRadius.circular(5),
          child: Image.asset(
            imagePath,
            fit: BoxFit.cover,
            height: double.infinity,
            width: double.infinity,
          ),
        ),
        Positioned(
          bottom: 0,
          left: 0,
          right: 0,
          child: Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
                colors: [Colors.transparent, Colors.black],
              ),
            ),
            child: Padding(
              padding: const EdgeInsets.all(10),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  SizedBox(
                    height: 40,
                  ),
                  Text(
                    title,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  SizedBox(height: 5),
                  Text(
                    description,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 16,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ],
    );
  }
}

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

  @override
  State<ImageDisplayScreen> createState() => _ImageDisplayScreenState();
}

class _ImageDisplayScreenState extends State<ImageDisplayScreen> {
  Uint8List? _capturedImage;
  Uint8List? _frontImage;
  Uint8List? _backImage;
  String? _fullName;
  String? _fcn;
  String? _dob;
  String? _gender;
  String? _nationality;
  String? _dateOfExpiry;
  String? _phoneNumber;
  String? _region;
  String? _zone;
  String? _woreda;
  String? _fin;
  final _innovaIDVerify = InnovaIDVerify();

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

  Future<void> launchKyc() async {
    try {
      print("\n=== Starting KYC Process ===");
      await _innovaIDVerify.processIDVerification(
        onVerificationComplete: (verificationData) {
          print("\n=== Verification Data Received ===");
          print("Raw verification data: $verificationData");

          // Handle Front OCR Data
          print("\n=== Front ID OCR Data ===");
          final frontData = verificationData['ocrDataFront'];
          if (frontData != null) {
            setState(() {
              _fullName = frontData['fullName'];
              _dob = frontData['dateOfBirth'];
              _fcn = frontData['fcn'];
              _nationality = frontData['nationality'];
              _gender = frontData['sex'];
              // Add other state updates as needed
            });
          } else {
            print("✗ No front OCR data received");
          }

          // Handle Back OCR Data
          print("\n=== Back ID OCR Data ===");
          final backData = verificationData['ocrDataBack'];
          if (backData != null) {
            _dateOfExpiry = backData['dateOfExpiry'];
            _phoneNumber = backData['phoneNumber'];
            _region = backData['regionCityAdmin'];
            _zone = backData['zoneCityAdminSubCity'];
            _woreda = backData['woredaCityAdminKebele'];
            _fin = backData['fin'];
          } else {
            print("✗ No back OCR data received");
          }

          // Handle Selfie Image if needed
          if (verificationData['selfieImage'] != null) {
            final selfieImage = verificationData['selfieImage'] as Uint8List;
            print("✓ Selfie Image received (${selfieImage.length} bytes)");
            setState(() {
              _capturedImage = selfieImage;
            });
          } else {
            print("✗ No selfie image received");
          }
          if (verificationData['frontImage'] != null) {
            final frontImage = verificationData['frontImage'] as Uint8List;
            print("✓ Front Image received (${frontImage.length} bytes)");
            setState(() {
              _frontImage = frontImage;
            });
          } else {
            print("✗ No Front image received");
          }
          if (verificationData['backImage'] != null) {
            final backImage = verificationData['backImage'] as Uint8List;
            print("✓ Front Image received (${backImage.length} bytes)");
            setState(() {
              _backImage = backImage;
            });
          } else {
            print("✗ No Front image received");
          }

          print("\n=== Verification Process Complete ===");
        },
      );
      print("✓ Camera launched successfully!");
    } catch (e, stackTrace) {
      print("\n=== Error in KYC Process ===");
      print("Error: $e");
      print("Stack trace:\n$stackTrace");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
          colors: [
            const Color(0xFF60CFFF),
            const Color.fromARGB(255, 197, 238, 255),
          ],
        ),
      ),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        appBar: AppBar(
          title: Text(
            _capturedImage != null ? "eKYC Details" : '',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          centerTitle: true,
          backgroundColor: Colors.transparent,
          foregroundColor: Colors.white,
        ),
        body: SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          child: Padding(
            padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20),
            child: _capturedImage != null
                ? Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Name:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _fullName ?? "N/A",
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'FCN:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _fcn ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Gender:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _gender ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Date of Birth:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _dob ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Nationality:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _nationality ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Date of Expiry:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _dateOfExpiry ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Phone Number:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _phoneNumber ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Region:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _region ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Zone:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _zone ?? 'N/A',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'Woreda:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _woreda ?? 'NA',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 13,
                      ),
                      Text(
                        'FIN:',
                        style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                        ),
                      ),
                      Text(
                        _fin ?? 'N/a',
                        style: TextStyle(
                            fontSize: 20,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 5,
                      ),
                      Divider(
                        color: Colors.white,
                      ),
                      SizedBox(
                        height: 5,
                      ),
                      Text(
                        'ID Card:',
                        style: TextStyle(
                            fontSize: 17,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 7,
                      ),
                      Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          if (_frontImage != null)
                            ClipRRect(
                              borderRadius: BorderRadius.circular(10),
                              child: AspectRatio(
                                aspectRatio: 4 /
                                    3, // Set an aspect ratio if you want to maintain a square box
                                child: Transform.rotate(
                                  angle: pi /
                                      2, // Rotate the front image by -90 degrees
                                  child: Image.memory(
                                    _frontImage!,
                                    fit: BoxFit
                                        .contain, // Ensures the entire image fits without cropping
                                  ),
                                ),
                              ),
                            ),
                          SizedBox(
                            height: 10,
                          ),
                          if (_backImage != null)
                            ClipRRect(
                              borderRadius: BorderRadius.circular(10),
                              child: AspectRatio(
                                aspectRatio: 4 /
                                    3, // Set an aspect ratio if you want to maintain a square box
                                child: Transform.rotate(
                                  angle: pi /
                                      2, // Rotate the back image by -90 degrees
                                  child: Image.memory(
                                    _backImage!,
                                    fit: BoxFit
                                        .contain, // Ensures the entire image fits without cropping
                                  ),
                                ),
                              ),
                            ),
                        ],
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      Divider(
                        color: Colors.white,
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      Text(
                        'Selfie:',
                        style: TextStyle(
                            fontSize: 17,
                            color: Colors.white,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 7,
                      ),
                      if (_capturedImage != null)
                        ClipRRect(
                          borderRadius: BorderRadius.circular(10),
                          child: SizedBox(
                            width: MediaQuery.of(context).size.width / 1.8,
                            child: Image.memory(_capturedImage!),
                          ),
                        ),
                    ],
                  )
                : Center(
                    child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const Text(
                        "eKyc Failed",
                        style: TextStyle(
                            fontWeight: FontWeight.bold,
                            color: Colors.white,
                            fontSize: 30),
                      ),
                      SizedBox(
                        height: 40,
                      ),
                      Image.asset(
                        'lib/assets/fail.png',
                        scale: 3,
                      )
                    ],
                  )),
          ),
        ),
        bottomNavigationBar: BottomAppBar(
          color: Colors.transparent,
          child: Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.15),
                  offset: Offset(0, 4),
                  blurRadius: 3,
                  spreadRadius: 0,
                ),
              ],
              gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [
                  const Color.fromARGB(255, 255, 162, 62),
                  const Color(0xFFFDBA74),
                ],
              ),
            ),
            width: double.infinity,
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(
                elevation: 0,
                backgroundColor: Colors.transparent,
                foregroundColor: Colors.white,
              ),
              onPressed: () {
                try {
                  Navigator.of(context, rootNavigator: true)
                      .pushReplacement(MaterialPageRoute(
                    builder: (context) => const HomeScreen(),
                  ));
                } catch (e) {
                  print("Error navigating to ImageDisplayScreen: $e");
                }
              },
              child: Text(_capturedImage != null ? 'Go Home' : 'Retry',
                  style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                      fontSize: 18)),
            ),
          ),
        ),
      ),
    );
  }
}
0
likes
140
points
12
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for ID verification

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on innova_id_verify

Packages that implement innova_id_verify