get_verified 0.0.4 copy "get_verified: ^0.0.4" to clipboard
get_verified: ^0.0.4 copied to clipboard

This package will have the solution for destroying scalping

Flutter Get Verified #

A comprehensive Flutter package for identity verification and anti-scalping solutions. This package provides a complete verification flow including document scanning with OCR, face biometric matching, liveness detection, and user registration.

pub.dev GitHub

Overview #

This package integrates two industry-leading SDKs to provide secure identity verification:

  • Regula Document Reader SDK - For scanning and extracting data from identity documents (passports, driver's licenses, etc.)
  • FaceTec/Face SDK - For face verification, liveness detection, and face matching

The package includes pre-built UI screens, extensive customization options, and a unified verification flow that can be easily integrated into any Flutter application.

Features #

Document Scanning #

  • OCR data extraction from identity documents
  • Support for various document types (passports, driver's licenses, ID cards)
  • RFID/NFC reading for enhanced security and data verification
  • Authenticity checks to detect forged documents
  • Multi-page document support
  • Customizable scanning interface with camera frame, toolbar, and status messages

Face Biometrics #

  • Face liveness detection to prevent spoofing attacks
  • Face matching against document photos
  • Customizable onboarding, camera, processing, success, and retry screens
  • Color, font, and image customization for all face SDK screens

Complete Verification Flow #

  • OnboardingScreen - Intro and preparation screens with SDK initialization
  • LoadingScreen - Configurable loading indicator during processing
  • VerificationCompleteScreen - Display extracted data for user review
  • RegisterScreen - User registration with customizable form fields
  • EmailOTPScreen - Email verification support (placeholder for integration)

Customization #

  • Fluent API for configuring document reader and face SDK
  • Color themes, fonts, and image assets customization
  • Camera frame styling (border, corner radius, aspect ratio)
  • Toolbar controls (torch, camera switch, close button)
  • Progress indicators and loading states
  • Form validation with regex support

Architecture #

  • Centralized configuration management via SDKConfigManager
  • Clean separation between SDK initialization, steps, and customization
  • Callback-based flow control with GetVerifiedSolution
  • Reusable UI components (AdaptiveImage, CircularIconProgress)

Getting Started #

Prerequisites #

  • Flutter SDK >= 3.0.0
  • Dart SDK >= 3.0.0
  • Android: minSdkVersion 24+, targetSdkVersion 33+
  • iOS: iOS 13.0+

Installation #

Add this to your pubspec.yaml:

dependencies:
  get_verified: ^0.0.3

Platform Configuration #

Android

Add to android/app/build.gradle:

android {
    defaultConfig {
        minSdkVersion 24
    }
}

iOS

Add to ios/Podfile:

platform :ios, '13.0'

Quick Start #

Basic Integration #

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get_verified/get_verified.dart';
import 'package:get_verified/screen/onboarding/onboarding_screen.dart';
import 'package:get_verified/manager/sdk_config_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize SDK configuration
  SDKConfigManager.instance.initialize(
    license: await rootBundle.load('assets/regula.license'),
    faceApiUrl: 'https://your-face-api.com',
    documentReaderUrl: 'https://your-doc-reader.com',
  );
  
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Get Verified Demo',
      theme: ThemeData(primarySwatch: Colors.red),
      home: OnboardingScreen(onVerificationStart: () {}),
    );
  }
}

Core Components #

GetVerifiedSolution #

The main orchestrator class that manages the complete verification flow:

GetVerifiedSolution().startProcess(
  faceApiUrl: 'https://your-face-api.com',
  mode: 'match',
  documentReaderConfig: documentReaderConfig,
  faceSDKConfig: faceSDKConfig,
  onDocumentFetched: (scanResult) {
    // Document scanning completed
    print('Name: ${scanResult.name}');
    print('Passport: ${scanResult.passportNumber}');
  },
  onFaceMismatch: () {
    // Face verification failed
  },
  onVerificationSuccess: (scanResult) {
    // All verification steps passed
  },
);

ScanResult #

The result object containing extracted document data:

class ScanResult {
  final String name;
  final String passportNumber;
  final String nationality;
  final Uint8List imageBase64;
}

SDKConfigManager #

Centralized configuration manager for all SDK settings:

SDKConfigManager.instance.initialize(
  verifiedResultConfig: VerifiedResultScreenConfig(...),
  loadingScreenConfig: LoadingScreenConfig(...),
  onboardingConfig: OnboardingConfig(...),
  faceSDKConfig: faceSDKConfig,
  documentReaderConfig: documentReaderConfig,
  license: license,
  faceApiUrl: faceApiUrl,
  documentReaderUrl: documentReaderUrl,
);

Document Reader SDK #

Initialization #

final initializer = DocReaderSdkInitializer();

// Initialize with license and backend URL
final success = await initializer.initialize(
  license: license,
  webServiceUrl: 'https://your-doc-reader.com',
);

// Or prepare database and initialize (for first run)
final success = await initializer.prepareDatabaseAndInitialize(
  license: license,
  webServiceUrl: 'https://your-doc-reader.com',
);

Scanning #

final steps = DocReaderSdkSteps();

steps.scan(
  faceApiUrl: 'https://your-face-api.com',
  mode: 'match',
  handleCompletion: (action, result, error) {
    if (action == DocReaderAction.COMPLETE && result != null) {
      // Handle successful scan
    }
  },
);

Customization #

Use the fluent API to configure the document reader:

final config = DocumentReaderConfig()
  .withColorTheme(
    ColorThemeConfig(
      primaryColor: '#4CAF50',
      onPrimaryColor: '#FFFFFF',
      backgroundColor: '#000000',
      reticleSuccessColor: '#4CAF50',
      reticleErrorColor: '#F44336',
    ),
  )
  .withCameraFrame(
    CameraFrameConfig(
      show: true,
      lineWidth: 3,
      borderColor: Colors.red,
      cornerRadius: 10.0,
      aspectRatio: 1.5,
    ),
  )
  .withToolbar(
    ToolbarConfig(
      showCloseButton: true,
      showTorchButton: true,
      showCameraSwitchButton: true,
    ),
  )
  .withMessages(
    MessagesConfig(
      showStatus: true,
      showResultStatus: true,
      hintMessages: {
        'moveCloser': 'Move closer to document',
        'holdSteady': 'Hold device steady',
      },
    ),
  )
  .withFunctionality(
    FunctionalityConfig(
      cameraMode: CameraMode.AUTO,
      zoomEnabled: true,
      isVibration: true,
    ),
  )
  .withProcessParams(
    ProcessParamsConfig(
      scenario: 'FullAuth',
      returnCroppedImage: true,
      imageQuality: ImageQualityConfig(
        dpiThreshold: 150,
        focusCheck: true,
        glaresCheck: true,
      ),
    ),
  );

await config.apply();

Configuration Classes #

Class Description
ColorThemeConfig Primary, background, text, and UI element colors
CameraFrameConfig Camera frame styling (border, corner radius, aspect ratio)
ToolbarConfig Toolbar buttons visibility and styling
MessagesConfig Status messages, hints, and fonts
FunctionalityConfig Camera mode, zoom, capture mode, exposure
ProcessParamsConfig Scanning scenario, image quality, date format
LivenessCustomConfig Liveness check motion control and capture button
RFIDConfig RFID reading UI and timeout configuration
MultipageConfig Multi-page document scanning settings
IndicatorsConfig Activity indicator positioning
InstructionsConfig Help animation settings
BackgroundConfig Background mask and border styling

Face SDK #

Initialization #

final success = await FaceSdkInitializer.initialize(
  webServiceUrl: 'https://your-face-api.com',
);

Face Verification Steps #

final steps = FaceSdkSteps();

// Start liveness check
final liveFaceImage = await steps.startLiveness();

// Match faces (document photo vs live photo)
final isMatched = await steps.matchFaces(
  documentFaceImage,
  liveFaceImage,
);

Customization #

final faceConfig = FaceSDKConfig()
  .withColors(
    FaceColorsConfig(
      onboardingScreenBackground: Colors.black,
      onboardingScreenTitleLabelText: Colors.white,
      cameraScreenStrokeActive: Colors.green,
      cameraScreenStrokeNormal: Colors.white,
      processingScreenBackground: Colors.black,
      successScreenBackground: Colors.green,
      retryScreenBackground: Colors.red,
    ),
  )
  .withFonts(
    FaceFontsConfig(
      fontFamily: 'Roboto',
      onboardingScreenTitleLabelSize: 24,
      onboardingScreenSubtitleLabelSize: 16,
      cameraScreenHintLabelSize: 14,
    ),
  )
  .withImages(
    FaceImagesConfig(
      successScreenImage: successImageByteData,
      retryScreenHintSubject: hintSubjectByteData,
    ),
  );

await faceConfig.apply();

Configuration Classes #

Class Description
FaceColorsConfig Colors for all face SDK screens
FaceFontsConfig Font family and sizes for all screens
FaceImagesConfig Custom images for success and retry screens

Pre-built Screens #

OnboardingScreen #

The entry point for the verification flow with SDK initialization:

OnboardingScreen(
  config: OnboardingConfig(
    buttonColor: Colors.red,
    buttonTextColor: Colors.white,
    imageWidth: 500,
    imageHeight: 500,
  ),
  introContent: const OnboardingContent(
    title: 'Welcome',
    subtitle: 'Get started with identity verification',
    imagePath: 'https://example.com/intro.png',
  ),
  preparationContent: const OnboardingContent(
    title: 'Prepare Documents',
    subtitle: 'Have your ID ready for scanning',
    imagePath: 'https://example.com/prep.png',
  ),
  onVerificationStart: () {
    // Called when user clicks Continue
  },
)

LoadingScreen #

A configurable loading screen for processing states:

LoadingScreen(
  config: LoadingScreenConfig(
    backgroundColor: Colors.white,
    progressColor: Colors.red,
    textColor: Colors.black,
    loadingText: 'Processing...',
    logoSize: 40,
    logoWidget: Icon(Icons.security, size: 40),
  ),
)

VerificationCompleteScreen #

Displays extracted document data for user review:

VerificationCompleteScreen(
  scanResult: scanResult,
  uiConfigOverride: VerifiedResultScreenConfig(
    primaryColor: Colors.red,
    buttonColor: Colors.red,
  ),
  onContinue: () {
    // Navigate to registration
  },
)

RegisterScreen #

A customizable registration form with validation:

RegisterScreen(
  config: RegisterScreenConfig(
    formConfig: FormConfig(
      title: 'Create Account',
      subtitle: 'Join our community',
      showTerms: true,
      navigationType: NavigationType.otp,
      fields: [
        FieldConfig(key: 'email', label: 'Email', inputType: TextInputType.emailAddress),
        FieldConfig(key: 'name', label: 'Full Name'),
        FieldConfig(key: 'dob', label: 'Date of Birth', isDate: true),
        FieldConfig(key: 'password', label: 'Password', inputType: TextInputType.visiblePassword),
      ],
    ),
    uiConfig: UIConfig(
      scaffoldBackgroundColor: Colors.white,
      submitButtonStyle: ElevatedButton.styleFrom(backgroundColor: Colors.red),
    ),
  ),
  onSubmit: (formData) {
    // Handle form submission
    print(formData);
  },
)

Usage Example #

See the example directory for a complete implementation:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get_verified/get_verified.dart';
import 'package:get_verified/screen/onboarding/onboarding_screen.dart';
import 'package:get_verified/manager/sdk_config_manager.dart';
import 'package:get_verified/config/loading_screen_config.dart';
import 'package:get_verified/config/onboarding_config.dart';
import 'package:get_verified/config/verified_result_config.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  SDKConfigManager.instance.initialize(
    verifiedResultConfig: VerifiedResultScreenConfig(
      primaryColor: Colors.red,
      buttonColor: Colors.red,
    ),
    loadingScreenConfig: LoadingScreenConfig(
      progressIndicatorSize: 100,
      logoWidget: FlutterLogo(size: 30),
    ),
    onboardingConfig: OnboardingConfig(
      buttonColor: Colors.red,
      buttonTextColor: Colors.white,
    ),
    faceApiUrl: 'https://poc.ticketrecipe.com:41101',
    documentReaderUrl: 'https://poc.ticketrecipe.com',
    license: await rootBundle.load('assets/regula.license'),
  );
  
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Get Verified Demo',
      theme: ThemeData(primarySwatch: Colors.red),
      home: OnboardingScreen(onVerificationStart: () {}),
    );
  }
}

Sending Results to Backend #

After verification, you can send the transaction ID to your backend:

// Static method to send transaction ID
final success = await GetVerifiedSolution.sendToCustomerBackend(
  transactionId: 'transaction-id',
  customerApiUrl: 'https://your-api.com/verify',
  customHeaders: {'Authorization': 'Bearer token'},
);

// Or use the combined finalize and send method
await GetVerifiedSolution.finalizeAndSendToCustomer(
  customerApiUrl: 'https://your-api.com/verify',
  customHeaders: {'Authorization': 'Bearer token'},
);

UI Components #

AdaptiveImage #

A widget that automatically handles both local assets and network images:

AdaptiveImage(
  imagePath: 'https://example.com/image.png', // or 'assets/images/logo.png'
  width: 200,
  height: 200,
  fit: BoxFit.contain,
  borderRadius: BorderRadius.circular(12),
)

CircularIconProgress #

An animated circular progress indicator with a customizable icon:

CircularIconProgress(
  icon: Icon(Icons.security, size: 40),
  progressColor: Colors.red,
  backgroundColor: Colors.white,
  size: 100,
  strokeWidth: 4,
  duration: Duration(seconds: 2),
)

Testing #

Run tests with:

flutter test

The package includes test coverage for:

  • Registration screen validation logic
  • Form field validation (regex, match keys)

Troubleshooting #

Logs for Document Reader #

# Get device ID
adb devices

# Pull logs
adb -s {device_id} pull -a storage/emulated/0/Android/data/com.ticketrecipe.example/files/Regula/ ~/regula/

Reprocessing Transactions #

curl --request POST \
  --url "https://poc.ticketrecipe.com/api/v2/transaction/bee28087-3574-44ed-8741-c65465732bf6/process" \
  --header "Content-Type: application/json" \
  --data '{ "processParam": { "scenario": "FullAuth" } }'

Common Issues #

  1. Database preparation takes too long: This is normal for first-time initialization. The SDK downloads document definition files.

  2. Face matching fails: Ensure good lighting and that the document photo is clearly visible.

  3. License not found: Make sure the license file is properly loaded in rootBundle.load().

Additional Information #

License #

MIT License - see LICENSE for details.

curl -X POST
"https://poc.ticketrecipe.com/api/v1/transactions/54cf7e22-1309-472a-b97f-f9934ff1ccd4/reprocess"
-H "Content-Type: application/json"
-d '{ "faceLivenessTransactionId": "d9f00532-4fea-47c2-81ef-6cfb8d940fd8" }'