PagoMovilOCR
npm library that extracts, normalizes and validates Venezuelan Pago Móvil receipts via OCR.
The Problem
In Venezuela, confirming a Pago Móvil payment usually means asking the customer for a screenshot and reading it by hand (amount, reference, date, bank), which is slow, error-prone, and doesn't scale for a business processing many payments a day.
The Solution
PagoMovilOCR automates that reading: it takes an image of the receipt and returns structured data along with a set of consistency validations, with no backend of its own and without ever sending the image to a server.
Architecture / Engineering
- Designed a 4-stage pipeline, each independently testable: OCR → normalization → parsing → validation.
- Implemented a swappable OCR engine (Tesseract.js by default, running 100% client-side/locally via WebAssembly).
- Built a registrable bank-profile system (`registerBankProfile`) to detect, and when it's safe, parse each bank's format.
- Developed a USD/VES conversion module using the official BCV rate (via pydolarve.org), with a configurable in-memory cache and explicit `stale` handling.
- Covered all the logic with unit and integration tests in Vitest: normalization, parsers, individual validators, the currency module with mocked providers, and end-to-end `verifyPayment` with a mocked OCR engine.
Key Features
- `verifyPayment()`: full pipeline from image to structured result with validations.
- Amount, reference, date, time and bank validation against optional expected values.
- On-demand USD/VES conversion using the official BCV rate, with configurable caching.
- Extensible bank-profile system without touching the library's core.
- Works in the browser (WASM OCR, image never leaves the client) and in Node.js 18+.
- Shipped as ESM, CJS and an IIFE build for CDNs (unpkg/jsDelivr), with TypeScript types included.
Engineering Challenges
- Designing honest validations: the library never outputs a `fraud: true` field or promises bank-grade verification — it only flags inconsistencies observable in the extracted text for a human to decide.
- Separating execution errors (corrupt image, network down) from receipt-validation errors, so an invalid receipt is never treated as a program failure.
- Keeping extraction and validation deterministic and testable with Vitest without relying on a real OCR engine in CI.
Result / Current State
Full pipeline working end to end, with a Vitest test suite covering normalization, parsing, validators and the `verifyPayment` orchestrator. Documented with a complete README, runnable examples and a layered architecture.
Known limitation
Bank profiles (other than the generic one) only provide detection by name; no bank-specific `parse` was included because a single, stable layout could not be reliably verified for each one — the generic parser covers the common format.