A Laravel package for parsing and processing Identity Documents

Overview

Laravel Identity Documents

Latest Version on Packagist Total Downloads StyleCI

For general questions and suggestions join gitter:

Join the chat at https://gitter.im/werk365/identitydocuments

Package that allows you to handle documents like passports and other documents that contain a Machine Readable Zone (MRZ).

This package allows you to process images of documents to find the MRZ, parse the MRZ, parse the Visual Inspection Zone (VIZ) and also to find and return a crop of the passport picture (using face detection).

⚠️ Version 2.x is a complete rewrite of the package with a new MRZ detection algorithm and is not compatible with version 1.x

Installation

Via Composer

$ composer require werk365/identitydocuments

Publish config (optional)

$ php artisan vendor:publish --provider="Werk365\IdentityDocuments\IdentityDocumentsServiceProvider"

Configuration

Services

The first important thing to know about the package is that you can use any OCR and or Face Detection API that you want. This package is not doing any of those itself.

Google Vision Service

Included with the package is a Google service class that will be loaded for both OCR and Face Detection by default. If you wish to use the Google service, no further configuration is required besides providing your credentials. To do this, make a service account and download the JSON key file. Then convert the JSON to a PHP array so it can be used as a normal Laravel config file. Your config file would have to be called google_key.php, be placed in the config folder and look like this:

"service_account", "project_id" => "", "private_key_id" => "", "private_key" => "", "client_email" => "", "client_id" => "", "auth_uri" => "", "token_uri" => "", "auth_provider_x509_cert_url" => "", "client_x509_cert_url" => "", ]; ">
return [
"type" => "service_account",
"project_id" => "",
"private_key_id" => "",
"private_key" => "",
"client_email" => "",
"client_id" => "",
"auth_uri" => "",
"token_uri" => "",
"auth_provider_x509_cert_url" => "",
"client_x509_cert_url" => "",
];

Creating Custom Services

If you want to use any other API for OCR and/or Face Detection, you can make your own service, or take a look at our list of available services not included in the main package (WIP).

Making a service is relatively easy, if you want to make a service that does the OCR, all you have to do is create a class that implements Werk365\IdentityDocuments\Interfaces\OCR. Similarly, there is also a Werk365\IdentityDocuments\Interfaces\FaceDetection interface. To make creating custom services even easier you can use the following command:

$ php artisan id:service <name> <type>

Where name is the ClassName of the service you wish to create, and type is either OCR, FaceDetection or Both. This will create a new (empty) service for you in your App\Services namespace implementing the OCR, FaceDetection or both interfaces.

Usage

Basic usage

Create a new Identity Document with a maximum of 2 images (optional) in this example we'll use a POST request that includes 2 images on our example controller.

use Illuminate\Http\Request;
use Werk365\IdentityDocuments\IdentityDocument;

class ExampleController {
	public function id(Request $request){
		$document = new IdentityDocument($request->front, $request->back);
	}
}

⚠️ In this example I use uploaded files, but you can use any files supported by Intervention

There are now a few things we can do with this newly created Identity Document. First of all finding and returning the MRZ:

$mrz = $document->getMrz();

We can then also get a parsed version of the MRZ by using

$parsed = $document->getParsedMrz();

As the MRZ only allows for A-Z and 0-9 characters, anyone with accents in their name would not get a correct first or last name from the MRZ. To (attempt to) find the correct first and last name on the VIZ part of the document, use:

$viz = $document->getViz();

This will return an array containing both the found first and last names as well as a confidence score. The confidence score is a number between 0 and 1 and shows the similarity between the MRZ and VIZ version of the name. Please not that results can differ based on your system's iconv() implementation.

To get the passport picture from the document use:

$face = $document->getFace()

This returns an Intervention\Image\Image

Get all of the above

If you wish to use all of these in a simplified way, you can also use the static all() method, which also expects up to two images as argument. For example:

use Illuminate\Http\Request;
use Werk365\IdentityDocuments\IdentityDocument;

class ExampleController {
  public function id(Request $request){
  	$response = IdentityDocuments::all($request->front, $request->back);
  	return response()->json($response);
  }
}

The all() method returns an array that looks like this:

[
	'type' => 'string', // TD1, TD2, TD3, MRVA, MRVB
	'mrz' => 'string', // Full MRZ
	'parsed' => [], // Array containing parsed MRZ
	'viz' => [], // Array containing parsed VIZ
	'face' => 'string', // Base64 image string
]

As you can see this includes all the above mentioned methods, plus the $document->type variable. The detected face will be returned as a base64 image string, with an image height of 200px.

Merging images

There are a couple of methods that will configure how the Identity Document is handled. First of all there's the mergeBackAndFrontImages() method. This method can be used to reduce the amount of OCR API calls have to be made. Images will be stacked on top of each other when this method is used. Please note that this method would have to be used before the getMrz() method. Example:

use Illuminate\Http\Request;
use Werk365\IdentityDocuments\IdentityDocument;

class ExampleController {
	public function id(Request $request){
		$document = new IdentityDocument($request->front, $request->back);
		$document->mergeBackAndFrontImages();
		$mrz = $document->getMrz();
	}
}

⚠️ Please note that merging images might cause high memory usage, depending on the size of your images

If you wish to use the static all() method and merge the images, publish the package's config file and enable it in there. Note that changing the option in the config will only apply to the all() method. Default config value:

	'mergeImages' => false, // bool

Setting an OCR service

If you have made a custom OCR service or are using one different than the default Google service, you can use the setOcrService() method. For example let's say we've creating a new TesseractService using the methods described above, we can use it for OCR like this:

use Illuminate\Http\Request;
use App\Services\TesseractService;
use Werk365\IdentityDocuments\IdentityDocument;

class ExampleController {
	public function id(Request $request){
		$document = new IdentityDocument($request->front, $request->back);
		$document->setOcrService(TesseractService::class);
		$mrz = $document->getMrz();
	}
}

If you wish to use the all() method, publish the package's config and set the correct service class there.

Setting a Face Detection Service

This can be done in a similar way as the OCR service, using the setFaceDetectionService() method. For example:

use Illuminate\Http\Request;
use App\Services\AmazonFdService;
use Werk365\IdentityDocuments\IdentityDocument;

class ExampleController {
	public function id(Request $request){
		$document = new IdentityDocument($request->front, $request->back);
		$document->setFaceDetectionService(AmazonFdService::class);
		$mrz = $document->getFace();
	}
}

If you wish to use the all() method, publish the package's config and set the correct service class there.

Other methods

addBackImage() sets the back image of the IdentityDocument. addFrontImage() sets the front image of the IdentityDocument. setMrz() sets the IdentityDcoument MRZ, for if you just wish to use the parsing functionality.

More information

If you're interested in how some things work internally, or if you would like to see an example of how to build a custom service within the package, I've written a blog post about all of that which you can find here: hergen.nl

Change log

Please see the changelog for more information on what has changed recently.

Contributing

Please see contributing.md for details and a todolist.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

. Please see the license file for more information.

Comments
  • Unsupported image type. GD driver is only able to decode JPG, PNG, GIF or WebP files.

    Unsupported image type. GD driver is only able to decode JPG, PNG, GIF or WebP files.

    Getting "Unsupported image type. GD driver is only able to decode JPG, PNG, GIF or WebP files."

    File was a JPEG.

    Intervention\Image\Gd\Decoder::initFromPath vendor/intervention/image/src/Intervention/Image/Gd/Decoder.php:59

    Looking at stack trace it can't get the file type because it being given the path. Not the image (it seems). It pulls it from here..

    vendor/intervention/image/src/Intervention/Image/AbstractDecoder.php:324

    case $this->isSplFileInfo():
    return $this->initFromPath($this->data->getRealPath());
    

    Though I wonder if it's on my end, as on "request files" I see this ...

    front
    { "pathname": "", "size": false, "mimeType": "undefined" }
    back
    { "pathname": "", "size": false, "mimeType": "undefined" }
    
    opened by MPJHorner 6
  • Laravel 9 support

    Laravel 9 support

    Hi, found your blog post on reddit /r/laravel really interesting and made for a great read!

    I've ran into a problem when installing your package via composer. I get the following error:

    Problem 1
        - werk365/identitydocuments[2.0.0-beta, ..., 2.0.4] require illuminate/support ~5|~6|~7|~8 -> found illuminate/support[v5.0.0, ..., 5.8.x-dev, v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev] but it conflicts with your root composer.json require (^9.2).
        - Root composer.json requires werk365/identitydocuments ^2.0 -> satisfiable by werk365/identitydocuments[2.0.0-beta, ..., 2.0.4].
    

    Which i've narrowed down to the illuminate/support in composer.json

    "illuminate/support": "~5|~6|~7|~8"

    Would i be right in thinking that adding in "illuminate/support": "~5|~6|~7|~8|~9" would solve the issue? I've checked and laravel 9 is using v9.2 for illuminate/support.

    I've not got a lot of experience working with open source and PRs. However I'd be happy to create one, but i'm unsure of how to test this with it being a package? Would appreicate any help in getting this fixed, if you have the time.

    Thanks.

    opened by danord24 4
  • Converting O to Zero

    Converting O to Zero

    Seems like converting the letter 'O' to number zero with $document->parsed->document_number is not enough, it needs to be done as well with $document->parsed->check_document_number. I had this issue with a document_number that ended with 7910 followed by check_document_number '0' (zero) which was returned as letter 'O' from the google api.

    I was able to fix that by adding the following line as line 249 in src/IdentityDocuments.php $document->parsed->check_document_number = preg_replace($re, $subst, $document->parsed->check_document_number);

    I haven't done any exhaustive testing so I don't create a pull request, but this seems to have fixed the problem for me anyway.

    2.0.0 
    opened by callingearth 2
  • file_get_contents(): read of 8192 bytes failed with errno=21 Is a directory

    file_get_contents(): read of 8192 bytes failed with errno=21 Is a directory

    private function createImage($file): IdentityImage { file_get_contents($file->getRealPath()); return new IdentityImage(Img::make($file), $this->ocrService, $this->faceDetectionService); }

    -getRealPath() returns a path excluding the image name. Then file_get_contents fails.

    • Using Laravel 8 /w php 7.4. Anyone else get this issue?
    opened by MPJHorner 0
  • Feature/parse document number viz

    Feature/parse document number viz

    To support cases where additional characters are added to the document number (for example the addition of NLD to the document number for residence permits).

    opened by HergenD 0
  • Feature/add exceptions to services

    Feature/add exceptions to services

    Replaces some dd() that were left from development with Exceptions when trying to use a service that does not implement the correct interface.

    This closes #27

    Thanks to @Mul-tiMedia for the issue

    opened by HergenD 0
  • Development leftovers

    Development leftovers

    Perhaps a try catch with a custom exception would be a little cleaner.

    Not going to open a pull request for such a minor thing ;)

    https://github.com/365Werk/identitydocuments/blob/bfefdc570e667f5989164a49e070a5d5db5346a5/src/IdentityImage.php#L41

    p.s amazing work! 👍🏻

    opened by Mul-tiMedia 0
  • Release/2.0.0

    Release/2.0.0

    Version 2.0.0 is a complete rewrite of the package. This version includes

    • A new MRZ searching algorithm
    • Improved MRZ parsing
    • Compatible with more document types
    • Improved VIZ parsing and confidence score
    • Face detection to find passport picture
    • Configurable ORC and Face Detection services
    • Improved interaction with the package through oop, instead of having everything static

    Closes #10 Closes #15

    opened by HergenD 0
  • Release/2.0.0

    Release/2.0.0

    Version 2.0.0 is a complete rewrite of the package. This version includes

    • A new MRZ searching algorithm
    • Improved MRZ parsing
    • Compatible with more document types
    • Improved VIZ parsing and confidence score
    • Face detection to find passport picture
    • Configurable ORC and Face Detection services
    • Improved interaction with the package through oop, instead of having everything static

    Closes #10 Closes #15

    opened by HergenD 0
  • Only one last name supported

    Only one last name supported

    Some passports have more then one last name eg Portugese. The MRZ parser assumes only one lastname is present.

    Possibly modify getFirstLastName to explode the lastName

    private function getFirstLastName(string $fullName): array
     {
         [$lastName, $firstName] = explode('<<', $fullName);
    
         return [explode('<', $lastName), explode('<', $firstName)];
     } 
    
    opened by unsized2 0
Releases(2.0.5)
Owner
365Werk
365Werk
Laravel package for creating Word documents with Eloquent ORM dependencies.

Laravel Eloquent Word This package provides an elegant way to generate Word documents with Eloquent Models. Uses PHPOffice/PHPWord package to generate

Marvin Quezon 6 Aug 5, 2022
Data Table package with server-side processing, unlimited exporting and VueJS components

Data Table package with server-side processing, unlimited exporting and VueJS components. Quickly build any complex table based on a JSON template.

Laravel Enso 618 Dec 28, 2022
Livewire trait (throttling). Limiting request processing speed

Livewire Throttling Installation You can install the package via composer: composer require f1uder/livewire-throttling Usage Livewire component <?php

Fluder 5 Dec 7, 2022
Jetstrap is a lightweight laravel 8 package that focuses on the VIEW side of Jetstream / Breeze package installed in your Laravel application

A Laravel 8 package to easily switch TailwindCSS resources generated by Laravel Jetstream and Breeze to Bootstrap 4.

null 686 Dec 28, 2022
A Laravel chat package. You can use this package to create a chat/messaging Laravel application.

Chat Create a Chat application for your multiple Models Table of Contents Click to expand Introduction Installation Usage Adding the ability to partic

Tinashe Musonza 931 Dec 24, 2022
GeoLocation-Package - This package helps you to know the current language of the user, the country from which he is browsing, the currency of his country, and also whether he is using it vpn

GeoLocation in PHP (API) ?? ?? ?? This package helps you to know a lot of information about the current user by his ip address ?? ?? ?? This package h

Abdullah Karam 4 Dec 8, 2022
This package provides extended support for our spatie/enum package in Laravel.

Laravel support for spatie/enum This package provides extended support for our spatie/enum package in Laravel. Installation You can install the packag

Spatie 264 Dec 23, 2022
Testbench Component is the de-facto package that has been designed to help you write tests for your Laravel package

Laravel Testing Helper for Packages Development Testbench Component is the de-facto package that has been designed to help you write tests for your La

Orchestra Platform 1.9k Dec 29, 2022
🥳🔐 This package is a Laravel package that checks if an email address is a spammer

This package is a Laravel package that checks if an email address is a spammer. It verifies your signups and form submissions to confirm that they are legitimate.

Endurance, the Martian 15 Dec 19, 2022
List of 77 languages for Laravel Framework 4, 5, 6, 7 and 8, Laravel Jetstream , Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova and Laravel Spark.

Laravel Lang In this repository, you can find the lang files for the Laravel Framework 4/5/6/7/8, Laravel Jetstream , Laravel Fortify, Laravel Cashier

Laravel Lang 6.9k Jan 2, 2023
Laravel package to generate and to validate a UUID according to the RFC 4122 standard. Only support for version 1, 3, 4 and 5 UUID are built-in.

Laravel Uuid Laravel package to generate and to validate a universally unique identifier (UUID) according to the RFC 4122 standard. Support for versio

Christoph Kempen 1.7k Dec 28, 2022
An opinionated support package for Laravel, that provides flexible and reusable helper methods and traits for commonly used functionality.

Support An opinionated support package for Laravel, that provides flexible and reusable helper methods and traits for commonly used functionality. Ins

Ian Olson 3 Apr 14, 2021
Otpify is a Laravel package that provides a simple and elegant way to generate and validate one time passwords.

Laravel Otpify ?? Introduction Otpify is a Laravel package that provides a simple and elegant way to generate and validate one time passwords. Install

Prasanth Jayakumar 2 Sep 2, 2022
A light weight laravel package that facilitates dealing with arabic concepts using a set of classes and methods to make laravel speaks arabic

A light weight laravel package that facilitates dealing with arabic concepts using a set of classes and methods to make laravel speaks arabic! concepts like , Hijri Dates & Arabic strings and so on ..

Adnane Kadri 49 Jun 22, 2022
Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud Messaging (FCM).

Laravel-FCM Introduction Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud M

Rahul Thapa 2 Oct 16, 2022
Easily add a full Laravel blog (with built in admin panel and public views) to your laravel project with this simple package.

Webdevetc BlogEtc - Complete Laravel Blog Package Quickly add a blog with admin panel to your existing Laravel project. It has everything included (ro

WebDevEtc. 227 Dec 25, 2022
Laravel-Mediable is a package for easily uploading and attaching media files to models with Laravel 5.

Laravel-Mediable Laravel-Mediable is a package for easily uploading and attaching media files to models with Laravel. Features Filesystem-driven appro

Plank Design 654 Dec 30, 2022
This Laravel package merges staudenmeir/eloquent-param-limit-fix and staudenmeir/laravel-adjacency-list to allow them being used in the same model.

This Laravel package merges staudenmeir/eloquent-param-limit-fix and staudenmeir/laravel-adjacency-list to allow them being used in the same model.

Jonas Staudenmeir 5 Jan 6, 2023
Laravel Responder - a package for building API responses, integrating Fractal into Laravel and Lumen

A Laravel Fractal package for building API responses, giving you the power of Fractal with Laravel's elegancy.

Alexander Tømmerås 776 Dec 25, 2022