validateMrzLineTd1 function
OcrMrzValidation
validateMrzLineTd1({
- required String l1,
- required String l2,
- required String l3,
- required List<
String> otherLines, - required String firstName,
- required String lastName,
- required OcrMrzSetting setting,
- required String country,
- required String nationality,
- required String personalNumber,
- List<
NameValidationData> ? nameValidations,
Implementation
OcrMrzValidation validateMrzLineTd1({
required String l1,
required String l2,
required String l3,
required List<String> otherLines,
required String firstName,
required String lastName,
required OcrMrzSetting setting,
required String country,
required String nationality,
required String personalNumber,
List<NameValidationData>? nameValidations,
}) {
OcrMrzValidation validation = OcrMrzValidation();
try {
final documentType = l1.substring(0, 1); // first char
final documentCode = l1.substring(0, 2); // first char
final issuingState = fixAlphaOnlyField(l1.substring(2, 5));
final docNo = l1.substring(5, 14);
final docChk = l1[14];
final opt1 = l1.substring(15, 30);
// Line2 (30):
// [0..6) birth, [6] birthChk, [7] sex, [8..14) expiry, [14] expiryChk,
// [15..18) nationality, [18..29) opt2, [29] finalComposite
final birth = l2.substring(0, 6);
final birthChk = l2[6];
final sex = l2[7];
final expiry = l2.substring(8, 14);
final expiryChk = l2[14];
final nationality = fixAlphaOnlyField(l2.substring(15, 18));
final opt2 = l2.substring(18, 29);
final finalComposite = l2[29];
log("Nationality ${nationality}");
// Line3 (30): names "LAST<<FIRST<MIDDLE..."
final nameField = l3;
final nameParts = nameField.split('<<');
String lastName = nameParts.isNotEmpty ? nameParts[0].replaceAll('<', ' ').trim() : '';
String firstName = nameParts.length > 1 ? nameParts[1].replaceAll('<', ' ').trim() : '';
lastName = _cleanName(lastName);
firstName = _cleanName(firstName);
// Validations
final vDoc = _computeMrzCheckDigit(docNo) == docChk;
final vBirth = RegExp(r'^\d{6}$').hasMatch(birth) && _computeMrzCheckDigit(birth) == birthChk;
final vExpiry = RegExp(r'^\d{6}$').hasMatch(expiry) && _computeMrzCheckDigit(expiry) == expiryChk;
validation.linesLengthValid = (l2.length == 44 && l1.length == 44);
// validation.docCodeValid = DocumentCodeHelper.isValid(documentCode);
validation.docCodeValid = DocumentCodeHelper.isValid(documentCode);
bool isDocNumberValid = _computeMrzCheckDigit(docNo) == docChk;
validation.docNumberValid = isDocNumberValid;
bool isBirthDateValid = (RegExp(r'^\d{6}$').hasMatch(birth) && _computeMrzCheckDigit(birth) == birthChk);
validation.birthDateValid = isBirthDateValid;
bool isExpiryDateValid = (RegExp(r'^\d{6}$').hasMatch(expiry) && _computeMrzCheckDigit(expiry) == expiryChk);
validation.expiryDateValid = isExpiryDateValid;
validation.personalNumberValid = true;
final compositeInput = docNo + docChk + birth + birthChk + expiry + expiryChk + opt2; // ICAO Doc 9303 specifies opt2 in composite
final vFinal = _computeMrzCheckDigit(compositeInput) == finalComposite;
validation.finalCheckValid = vFinal;
bool validNames = validateNames(firstName, lastName, otherLines);
bool isNamesValid = validNames;
validation.nameValid = isNamesValid;
if (!isNamesValid && nameValidations != null) {
if (nameValidations.any((a) => a.firstName.toLowerCase() == firstName.toLowerCase() && a.lastName.toLowerCase() == lastName.toLowerCase())) {
isNamesValid = true;
validation.nameValid = true;
}
}
bool validCountry = isValidMrzCountry(country);
bool isValidCountry = validCountry;
validation.countryValid = isValidCountry;
bool validNationality = isValidMrzCountry(nationality);
bool isValidNationality = validNationality;
validation.nationalityValid = isValidNationality;
return validation;
} catch (e) {
return validation;
}
}