ekyc

Electronic KYC process with uploading ID document using OAuth 2.1 (experimental)
Log | Files | Refs | README | LICENSE

mrz_scan.ts (1962B)


      1 import { IDDocumentMRZScan, MRZInfo } from "#core/application/id_document/mrzscan.ts";
      2 import { parse } from "mrz";
      3 
      4 const PREFIX = "data:image/png;base64,";
      5 
      6 export class TesseractIDDocumentMRZScanAdapter implements IDDocumentMRZScan {
      7   constructor(private readonly path: string) {
      8   }
      9 
     10   async scan(image: string): Promise<MRZInfo> {
     11     if (!image.startsWith(PREFIX)) {
     12       throw new Error("invalid image");
     13     }
     14 
     15     try {
     16       const buffer = Uint8Array.from(
     17         atob(image.substring(PREFIX.length)),
     18         (c) => c.charCodeAt(0),
     19       );
     20       const command = new Deno.Command(this.path, {
     21         args: [
     22           "-l",
     23           "ocrb",
     24           "stdin",
     25           "stdout",
     26         ],
     27         env: {
     28           TESSDATA_PREFIX: new URL("./models", import.meta.url).pathname,
     29         },
     30         stdin: "piped",
     31         stderr: "null",
     32         stdout: "piped",
     33       });
     34       const process = command.spawn();
     35       const writer = process.stdin.getWriter();
     36       await writer.ready;
     37       await writer.write(buffer);
     38       await writer.close();
     39       const content = new TextDecoder().decode(
     40         (await process.output()).stdout!,
     41       );
     42 
     43       const lines = content
     44         .split("\n")
     45         .filter((line) => line.includes("<") && !line.includes(" "));
     46 
     47       const result = parse(
     48         lines,
     49         { autocorrect: true },
     50       );
     51 
     52       if (result.valid) {
     53         console.log(result.fields);
     54         return {
     55           firstName: result.fields.firstName!,
     56           lastName: result.fields.lastName!,
     57           birthDate: new Date(
     58             result.fields.birthDate!.split(/([0-9]{2})/).filter((i) => !!i)
     59               .join("/"),
     60           ),
     61           sex: result.fields.sex!,
     62           nationality: result.fields.nationality!,
     63           country: result.fields.issuingState!,
     64         };
     65       }
     66       throw new Error("Invalid scan");
     67     } catch (cause) {
     68       throw new Error("Invalid MRZ", { cause });
     69     }
     70   }
     71 }