capture 0.8.0 copy "capture: ^0.8.0" to clipboard
capture: ^0.8.0 copied to clipboard

Capture Nuptial plugin avec Wizidee SDK. Ce plugin met à disposition des fonctionnalités de reconnaissance de documents.

Capture NUPTIAL plugin for Flutter #

© Everial

Ceci est un projet exemple minimaliste utilisant le plugin Capture Everial : NUPTIAL

Le plug-in apporte des fonctionnalités de reconnaissance de documents officiels et d'extraction de données Il prend en charge l'intégralité des fonctions de capture.

Note sur le fonctionnement #

Le plugin est conçu pour effectuer les traitements sur le mobile. Cependant, il doit accèder à certains webservices périodiquement:

  • première utilisation de l'application
  • relevé d'utilisation
  • mise à jour des modèles de reconnaissance
  • mise à jour de la configuration
  • test de preuve de vie
  • accès à des webservices complémentaires pour les mobiles peu puissans

La détection de l'état de connection est automatique et transparente

Préalable à l’installation #

Demande d’identifiant #

Le SDK s’initialise à partir d’un login et d’un mot de passe fourni par Everial. Ce login est associé au nom du bundle de l’application embarquant le SDK (iOs, Android). Exemple : com.yourcompany.yourapp

L'application de test est pré-configuré avec vos identifiants. Voir le fichier "home.html"

Versions #

IOS Le plugin doit être compilé en swift version 5 pour la version iOS. La version minimale iOS est la 13.

Android Le plugin supporte Android SDK depuis la version 24.

Installation de l'application de test #

  • Dézipper le paquet puis à la racine exécutez:
     flutter pub get
    
    Cela permettra d'importer les dépendances.

iOS

Android

  • Ouvrir le répertoire ./android dans Android Studio. Dans le "build.gradle" de l'app, ajoutez le repository maven everial et https://jitpack.io:
repositories {
(...)
   maven {
        url 'https://pkgs.dev.azure.com/Everial/Doclab/_packaging/plugins/maven/v1'
        name 'Main_Feed'
    }
    maven {
        url  'https://jitpack.io'
    }   
}

Dans variables.gradle, montez le minSDK à la version 24 pour une compatibilité CameraX:

ext {
    minSdkVersion = 24
    compileSdkVersion = 29
    (...)
}

Utilisation #

Le plugin est disponible dans Flutter/Dart sous le nom 'capture':

import 'package:capture/capture.dart';

Il doit être ajouté dans le fichier 'pubspec.yaml' :

dependencies:
  flutter:
    sdk: flutter
    git:
        url: [adresse git azure]

Code d'exemple des fonctions principales : example/lib/initialization.dart et example/lib/home/home_page.dart

initialize({ login, password } success, error) #

Le SDK doit être initialisé en appelant la fonction initialize (login, mot de passe)

Lors de la première utilisation, le SDK va se connecter au serveur d’authentification et obtenir les noms des paquets applicatifs autorisés. Tant que cette première vérification n’aura pas été effectuée, le SDK sera inutilisable.

Objet retourné

Dans les deux cas, une trace JSON est renvoyée. Le JSON est un objet RTRLogs :

{
    RTRLogs :[RTRLog],
    Severity : int    
}

RTRLog
{  
    type : case info=0,warning=1,error=2,fatal=3
    caller:String,
    shortDescription: String,
    longDescription: String
}

La log est de type cumulative, il faut tester le champ severity afin de connaitre l’erreur la plus grave.

Classement des typologies d'erreurs:

  • 0: information: permet de suivre le traitement
  • 1: warning: une anomalie a été rencontrée mais n'empêche le déroulement de l'analyse. Il s'agit majoritairement du passage en mode offline de l'application.
  • 2: error: une erreur est survenue pendant le traitement d'une analyse (capture, ocr, validation). Cela ne compromet les analyses suivantes, ni la poursuite de la capture.
  • 3: fatal: erreur bloquante. Le SDK ne peut fonctionner. Majoritairement, une mauvaise authentification ou initialisation impossible de l'analyse.

Toute erreur de type 3 (fatale) rend l’usage de l’analyse inopérante. Le tableau de RTRLog est informatif.

Exemples :

	try {
      final res = await Capture().onInitialize(login, password);
      if (res != null) {
        (...)
      }
    } on PlatformException catch (err) {
      (...)
    }

Quand l’initialisation est OK :

       {  
		    "RTRLogs":[  
			    {  
			    "caller":"<EverialRT.ConfigurationManager: 0x102f129c0>",  
			    "longDescription":"remote config loaded for: bundle",  
			    "type":0,  
			    "shortDescription":"remote config loaded"  
			    },  
			    {  
			    "caller":"<EverialRT.ConfigurationManager: 0x102f129c0>",  
			    "longDescription":"remote config loaded for: schema",  
			    "type":0,  
			    "shortDescription":"remote config loaded"  
			    }  
		    ],  
		    "severityFlag":0  
    }

Exemple de retour avec connection internet coupée :

    {  
    "RTRLogs":[  
	    {  
	    "caller":"<EverialRT.ConfigurationManager: 0x1056052c0>",  
	    "longDescription":"Error while authenticating: Optional(Error Domain=NSURLErrorDomain Code=-1009 \"The Internet connection appears to be offline.\" UserInfo={NSUnderlyingError=0x282b57870 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 \"(null)\" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https:\/\/auth.devlab.everial.com\/auth\/realms\/quota\/protocol\/openid-connect\/token, NSErrorFailingURLKey=https:\/\/auth.devlab.everial.com\/auth\/realms\/quota\/protocol\/openid-connect\/token, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50, NSLocalizedDescription=The Internet connection appears to be offline.})",  
	    "type":2,  
	    "shortDescription":"Error while authenticating"  
	    }  
    ],  
    "severityFlag":2  
    }

Autre exemple, lors du premier usage, l’initialisation peut renvoyer ce genre de réponse, si la connection internet n’est pas activée


    {  
    "caller":"<EverialRT.RTR: 0x133e03af0>:processHiRes",  
    "longDescription":"User or SDK not granted for this application",  
    "type":3,  
    "shortDescription":"User or SDK not granted"  
    }

process({}, success, error) #

La fonction instancie une vue de capture dans la vue parente et démarre le scan. Il est possible d'interrompre l'analyse en touchant la vue.

L'analyse est relançable sans repasser par la méthode d'initialisation. Lorsque la capture est achevée (match ou interruption) , la vue est supprimée de la vue parente.

Exemple:

dynamic result = await Capture().onProcess();

result contient des données : SUCCESS: JSON: données extraites de la pièces" result contient une erreur / try-catch : ERROR: message d'erreur

Réponse #

La réponse a pour content-type : application/json; charset=utf-8 La structure du champ validation est la suivante.

La structure de la réponse est hiérarchiquement:

  • subscriber -> cela correspond au niveau inter-document, c'est la notion de dossier
  • un tableau de documents -> un document: CNI, JUDO
  • pour chaque document, un tableau de pages -> les pages de ce document, un recto/verso par exemple

Chaque niveau est structuré: result -> "errors", "descriptions", "value" + "fields" au niveau page

En cas d'échec, la log d'erreur restitue l'image dans l'entrée de tableau suivante:

{  
    "caller":"analyse",  
    "longDescription":"base64 image url encodée",  
    "type":0,  
    "shortDescription":"Document"  
    }

Utilisation pour la manipulation de la réponse #

la réponse est de la forme

{value:"JSON_DOC_STRING"}

Il faut donc procéder de la sorte

try {
  dynamic result = await Capture().onProcess();
  // Cette fonction est équivalente à : json.decode(docToFormat)['value'];
  dynamic resValue = _getDocValue(result);

  if (resValue != '') {
  (...)
  } else {
   throw Exception("Nothing to add.");
  }
} on PlatformException catch (err) {
  (...)
}

consolidate({array of json documents}, success, error) #

Cette méthode permet d'effectuer les contrôles de cohérences entre plusieurs documents.

await Capture().onConsolidate({ documents: docs })

IOS Si le tableau fournit est vide, l'application compare les documents qu'elle a déjà analysés c'est à dire à partir de la liste constituée par les analyses précédentes. La constitution de cette liste est de type LIFO: chaque document de même type vient écraser le précédent. Cependant dans le cas d'une gestion des documents côté applicatif client, il est possible de stocker les documents analysés dans l'application cliente, puis de demander une validation en refournissant ceux qui sont appropriés. Dans ce cas, les json de documents doivent être fournis dans un tableau.

Attention: dans ce cas, la liste du moteur d'analyse est remplacée par celle refournie.

ANDROID Il est de la responsabilité de l'applicatif de gérer les documents analysés. Le plugin ne conserve aucune trace des analyses précédentes. Les documents analysés doivent être stockés dans l'application cliente qui peut demander une consolidation sur ceux qu'elle estime appropriés. Les documents sont à refournir dans la chaine JSON telle que reçue de l'analyse et stockés dans un tableau

Réponse #

La réponse a pour content-type : application/json; charset=utf-8 La structure du champ validation est la même que pour analyze des contrôles supplémentaire sont présent dans la clé "subscriber"

analyze({ fileuri: file }, success, error) #

Cette méthode permet de réaliser l'analyse d'un document sans appeler la fonction de capture. Dans ce cas, on suppose que l'applicatif prend en charge la collecte du fichier. Il faut fournir le chemin du fichier sur le device. La réponse est identique à "process" Les types acceptés sont image/* et application/pdf. Dans le cas d'un PDF seule la première page est analysée

await Capture().onAnalyze({ fileuri: file })

Android La chaine attendue est de type Uri (android.net.Uri: Uri.toString())

iOS: La chaine attendu est de type URL (url.absolutestring())

selfie({ baseimage: extractedPhoto }, success, error) #

    await Capture().onSelfie({ baseimage: extractedPhoto })

Cette méthode effectue 2 contrôles:

  • comparaison de l'image fournie en paramètre "imgBase" (image base 64) avec le visage de l'utilisateur
  • test de preuve de vie

Lors de l'appel de cette fonction la caméra est déclenchée et l'utilisateur est invité à placer son visage dans un cadre quelques secondes. Sur Ios, l'expérience est légèrement différente avec l'affichage de landmarks. L'analyse ne prend que quelques secondes, sans aucun scénario pour l'utilisateur.

La réponse est de type json avec une seule clé:

     {"valid": "true" | "false"}

Note: L'application enregistre toutes les photos liées aux documents précédemment enregistrés.

SSL Pinning #

Un contrôle de type "Man in the middle" peut être effectué par le plugin. Pour cela, Everial active le paramètre au niveau de votre user.

 {"RTRContext" : "2.3.0:capsule-dev", "caller" : "com.everial.rtr.Configuration", "longDescription" : "SSL pinning enabled", "shortDescription" : "SSL pinning enabled", "type" : 0}

Si le contrôle est activé, le plugin au moment de son initialisation s'assurera que la clé publique du certificat présenté est bien celle d'Everial.

L'initialisation renvoie alors une erreur.

Cette erreur n'est pas bloquante et il appartient à l'applicatif de décider de stopper ou non la poursuite de l'application.

{"RTRContext" : "2.3.0:capsule-dev", "caller" : "com.everial.rtr.Configuration", "longDescription" : "user=capsule-dev,pub=CBSA08mY+VfrZrjVgkDDpFbz6JBBavdW6TPgbCYde58=, received certificate: Certificate pinning failure!\n  Peer certificate chain:\n    sha256/tJqnS+/9e9HeWUtNxnTbdpfA0oCOC9ka30l8fGiE4p0=: CN=k8s.doclab.fr\n    sha256/Ns1wdAOg3MUrrOICXWYlMXelaJL9M6n/Y9nuYfZawsM=: C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (4 Nov 2021\\, MacBook-Pro-de-Sebastien.local)\n  Pinned certificates for log.k8s.doclab.fr:\n    sha256/CBSA08mY+VfrZrjVgkDDpFbz6JBBavdW6TPgbCYde58=", "shortDescription" : "Error while pinning certificate", "type" : 2}

NOTE

Pour des raisons de réactivité, le plugin n'embarque aucune valeur de clé. La clé est téléchargée depuis la configuration. Elle n'est pas falsifiable dans le transport (HMAC256).

Ainsi Everial peut mettre à jour la clé "à chaud" sans relivrer le plugin en cas par exemple de mise à jour des certificats.

En cas d'échec de vérification, une alerte est générée sur les serveurs Everial. Everial peut dans ce cas intervenir et soit mettre à jour la clé en cas de renouvellement automatique du certificat ou avertir le client s'il s'agit d'une tentative de fraude.

1
likes
0
pub points
19%
popularity

Publisher

verified publisherdev.wizidee.com

Capture Nuptial plugin avec Wizidee SDK. Ce plugin met à disposition des fonctionnalités de reconnaissance de documents.

Homepage

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on capture