IRONSOFTWAREHOME
VÍDEOS

Migrando do Veryfi para o IronOCR

Kannaopat Udonpant
Kannapat Udonpant
Updated: 1 de agosto de 2026

Este guia orienta os desenvolvedores .NET na substituição da API de processamento de documentos em nuvem da Muito bom pelo IronOCR , uma biblioteca OCR local. Este documento aborda a troca de pacotes, a limpeza do namespace e quatro exemplos completos de migração de código focados nos padrões mais comumente utilizados no Veryfi: inicialização do cliente, extração de campos baseada em região, categorização de despesas com dados estruturados e substituição de webhooks. Não é necessário ler o artigo comparativo previamente.

Por que migrar do Veryfi?

Os documentos financeiros fluem pelo sistema da Muito bom em uma única direção: da sua infraestrutura para a deles. Esse fato arquitetônico impulsiona a maioria das migrações. Aqui estão os principais problemas que levam as equipes a fazer a mudança.

Cada solicitação de documento transmite dados financeiros confidenciais para um servidor de terceiros. Os recibos contêm os quatro últimos dígitos do cartão e informações sobre o fornecedor. As faturas contêm números de contas bancárias, números de roteamento e números de identificação fiscal do fornecedor. Os extratos bancários contêm o histórico completo das transações. Com a Veryfi, cada chamada de ProcessDocumentAsync faz upload desses bytes para api.veryfi.com, processa-os na infraestrutura da Muito bom e retorna JSON. Seu controle sobre esses dados termina no momento em que a solicitação HTTP é enviada.

Quatro credenciais são necessárias e devem ser mantidas em sincronia em todos os ambientes. VeryfiClient requer clientId, clientSecret, username e apiKey—quatro segredos separados para armazenar na configuração, rodar conforme o cronograma, injetar em pipelines CI/CD e auditar quanto à exposição. Uma única falha de credencial compromete a autenticação de todos os documentos processados ​​em toda a aplicação. O IronOCR requer uma única chave de licença.

O preço por documento é cumulativo, sem limite máximo. Os recibos custam aproximadamente de US$ 0,05 a US$ 0,15 cada, as faturas de US$ 0,10 a US$ 0,25 e os extratos bancários de US$ 0,15 a US$ 0,30. Com 50.000 documentos por mês, isso representa um custo de US$ 5.000 a US$ 15.000 por mês em faturamento por consumo, sem redução no segundo ou terceiro ano. A licença IronOCR Professional , a US$ 2.999, cobre um número ilimitado de documentos de forma perpétua — o ponto de equilíbrio em relação aos US$ 5.000 gastos mensais com a Muito bom ocorre em menos de três semanas.

A API é exclusivamente assíncrona porque o trabalho subjacente é remoto. ProcessDocumentAsync não é assíncrono porque o processamento é computacionalmente longo; É assíncrono porque o documento precisa ser enviado para um servidor, entrar em fila atrás de outras solicitações, concluir a inferência e retornar uma resposta pela rede. A latência não é determinística. A limitação de taxa de requisições HTTP 429 requer lógica de repetição. Erros de pagamento HTTP 402 interrompem completamente o processamento em lote. Erros HTTP 500 na infraestrutura da Muito bom comprometem seu fluxo de trabalho.

O escopo de documentos do Muito bom termina no limite do documento de despesa. Os modelos treinados retornam campos estruturados de forma confiável para recibos, faturas, cheques, extratos bancários, formulários W-2 e cartões de visita. Fora dessa lista — documentos comerciais gerais, contratos, registros médicos, documentos de remessa, formulários internos personalizados — os resultados são inferiores ou exigem treinamento pago em modelos personalizados. Organizações que adotam o Muito bom para automação de despesas normalmente descobrem, dentro de 6 a 12 meses, que outras equipes precisam de OCR para documentos que o Muito bom não foi projetado para processar.

O esquema JSON proprietário da Muito bom acopla toda a lógica de extração a um único fornecedor. Cada linha de código que lê response.Vendor?.Name, response.BankAccount?.RoutingNumber ou response.LineItems é código que só funciona com a Veryfi. Mudar de fornecedor — ou optar por um sistema OCR local — significa reescrever toda a lógica de extração do zero.

O problema fundamental

// Veryfi: financial data leaves your infrastructure on every call
var client = new VeryfiClient(clientId, clientSecret, username, apiKey); // 4 secrets
var bytes = File.ReadAllBytes("invoice-with-routing-number.pdf");
var response = await client.ProcessDocumentAsync(bytes); // bank details transmitted
var routingNumber = response.BankAccount?.RoutingNumber; // arrived via Muito bom cloud
C#
// IronOCR: routing numbers never leave your server
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; // 1 key
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf("invoice-with-routing-number.pdf"); // processed locally
var result = ocr.Read(input);
var routingNumber = Regex.Match(result.Text, @"Routing\s*#?\s*:?\s*(\d{9})").Groups[1].Value;
C#

##IronOCR vs Veryfi: Comparação de Recursos

A tabela abaixo mapeia as funcionalidades de ambos os produtos para auxiliar na avaliação técnica.

RecursoMuito bomIronOCR
Local de processamentoServidores em nuvem Muito bomSua infraestrutura
Modelo de implantaçãoSomente API em nuvemLocal, Docker, Azure, AWS, Linux
Suporte offlineNãoSim
É necessário ter acesso à internet.Sim (todos os documentos)Não
Os dados saem da infraestrutura.Sim (em todas as chamadas)Nunca
Compatível com HIPAA sem BAANãoSim
Suporte para ambiente isolado (air-gapped)Não é possível.Suporte completo
Modelo de preçosPor documento (US$ 0,05 a US$ 0,30)Licença perpétua ($999–$2,399)
Credenciais necessárias4 (clientId, clientSecret, username, apiKey)1 chave de licença
API síncronaNão (somente assíncrono)Sim
Limitação de taxaSim (HTTP 429)None
Escopo do documentoRecibos, faturas, cheques, extratos bancários, formulários W-2, cartões de visita.Qualquer tipo de documento
Tipos de documentos personalizadosTreinamento remunerado para modelos é obrigatório.Qualquer layout via extração de regex/padrão
Entrada de PDFSim (upload de bytes)Sim (nativo, local)
Saída em PDF pesquisávelNãoSim (result.SaveAsSearchablePdf())
OCR baseado em regiãoNãoSim (CropRectangle)
Leitura de código de barrasNãoSim (mesma aprovação do OCR)
Acesso estruturado aos resultadosCampos JSON pré-analisadosPáginas, parágrafos, linhas, palavras com coordenadas
Pontuação de confiançaPor campo (proprietário)Por palavra e no geral (result.Confidence)
Suporte para mais de 125 idiomasLimitadoSim (pacotes de idiomas NuGet )
Processamento paralelo seguro para threadsAplicam-se limites de simultaneidade HTTP.Completo (um IronTesseract por thread)
Testes unitários sem mocksRequer simulação HTTPTestes locais diretos

Guia rápido: Migração do Muito bom para o IronOCR

Passo 1: Substitua o pacote NuGet

Remova o SDK Veryfi:

dotnet remove package Veryfi
SHELL

Instale o IronOCR a partir do NuGet :

dotnet add package IronOcr

Etapa 2: Atualizar Namespaces

Substitua os namespaces Muito bom pelo namespace IronOCR:

// Before (Veryfi)
using Veryfi;
using Veryfi.Models;

// After (IronOCR)
using IronOcr;
using System.Text.RegularExpressions;
C#

Etapa 3: Inicializar a licença

Adicione esta linha uma única vez na inicialização do aplicativo, antes de qualquer chamada de OCR:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

Exemplos de migração de código

Substituição de Cliente de Processamento de Documentos

Os serviços Muito bom são construídos em torno da injeção de construtores de VeryfiClient. O construtor de quatro credenciais é uma solução natural para injeção de dependência, mas cria quatro segredos que precisam ser gerenciados e rotacionados. Substituir isso pelo IronOCR consolida as credenciais em uma única chave de licença e move a instanciação do mecanismo de processamento para a própria classe de serviço.

Abordagem Veryfi:

using Veryfi;
using Microsoft.Extensions.Configuration;

public class ExpenseDocumentService
{
    private readonly VeryfiClient _client;

    // Four credentials injected — four secrets to manage, store, rotate
    public ExpenseDocumentService(IConfiguration config)
    {
        _client = new VeryfiClient(
            config["Veryfi:ClientId"],       // secret 1
            config["Veryfi:ClientSecret"],   // secret 2
            config["Veryfi:Username"],       // secret 3
            config["Veryfi:ApiKey"]          // secret 4
        );
    }

    public async Task<string> GetVendorNameAsync(string documentPath)
    {
        var bytes = File.ReadAllBytes(documentPath);
        // Document uploaded to Muito bom on this call
        var response = await _client.ProcessDocumentAsync(bytes);
        return response.Vendor?.Name;
    }

    public async Task<decimal?> GetTotalAsync(string documentPath)
    {
        var bytes = File.ReadAllBytes(documentPath);
        var response = await _client.ProcessDocumentAsync(bytes);
        return response.Total;
    }
}
C#

Abordagem IronOCR:

using IronOcr;
using System.Text.RegularExpressions;

public class ExpenseDocumentService
{
    private readonly IronTesseract _ocr;

    // One license key — set once at startup, not per-instance
    public ExpenseDocumentService()
    {
        _ocr = new IronTesseract();
    }

    public string GetVendorName(string documentPath)
    {
        // All processing local — document bytes never leave this server
        var result = _ocr.Read(documentPath);

        // Vendor is typically the first non-whitespace line on a receipt
        return result.Pages[0].Paragraphs
            .OrderBy(p => p.Y)
            .Select(p => p.Text.Trim())
            .FirstOrDefault(t => t.Length > 3);
    }

    public decimal? GetTotal(string documentPath)
    {
        var result = _ocr.Read(documentPath);
        var match = Regex.Match(result.Text,
            @"(?:Total|Grand Total|Amount Due):?\s*\$?\s*([\d,]+\.\d{2})",
            RegexOptions.IgnoreCase);
        return match.Success
            ? decimal.Parse(match.Groups[1].Value.Replace(",", ""))
            : (decimal?)null;
    }
}
C#

A alteração do construtor elimina quatro entradas de configuração de cada ambiente: appsettings.json, segredos do Docker, referências do Azure Key Vault e variáveis de pipeline CI/CD. A instância IronTesseract é reutilizável em várias chamadas na mesma thread. Consulte o guia de configuração do IronTesseract para obter informações sobre padrões de registro singleton em contêineres de injeção de dependência do ASP.NET Core .

Extração de campos de recibo com OCR baseado em região

O Muito bom extrai os campos do recibo executando seus modelos de aprendizado de máquina treinados em toda a imagem do documento e retornando uma resposta JSON pré-estruturada. O equivalente do IronOCR é OCR baseado em região usando CropRectangle, que visa zonas específicas da imagem de recibo—zona de cabeçalho para fornecedor, zona de rodapé para totais—ao invés de executar uma passagem de página completa e procurar padrões na saída. Este método é mais rápido para layouts conhecidos e mais preciso quando a área de interesse está bem definida.

Abordagem Veryfi:

using Veryfi;

public class ReceiptFieldExtractor
{
    private readonly VeryfiClient _client;

    public ReceiptFieldExtractor(VeryfiClient client)
    {
        _client = client;
    }

    public async Task<(string Vendor, decimal? Total, decimal? Tax)>
        ExtractReceiptFieldsAsync(string imagePath)
    {
        var bytes = File.ReadAllBytes(imagePath);

        // Full document uploaded — Veryfi's ML returns structured fields
        var response = await _client.ProcessDocumentAsync(bytes);

        return (
            Vendor: response.Vendor?.Name,
            Total:  response.Total,
            Tax:    response.Tax
        );
    }
}
C#

Abordagem IronOCR:

using IronOcr;
using System.Text.RegularExpressions;

public class ReceiptFieldExtractor
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public (string Vendor, decimal? Total, decimal? Tax)
        ExtractReceiptFields(string imagePath)
    {
        // Region 1: Header zone — vendor name typically in top 15% of receipt
        var headerRegion = new CropRectangle(0, 0, 800, 150);
        using var headerInput = new OcrInput();
        headerInput.LoadImage(imagePath, headerRegion);
        headerInput.Deskew();
        var headerResult = _ocr.Read(headerInput);

        // Region 2: Footer zone — totals typically in bottom 20% of receipt
        var footerRegion = new CropRectangle(0, 650, 800, 200);
        using var footerInput = new OcrInput();
        footerInput.LoadImage(imagePath, footerRegion);
        footerInput.DeNoise();
        var footerResult = _ocr.Read(footerInput);

        var vendor = headerResult.Pages[0].Paragraphs
            .OrderBy(p => p.Y)
            .Select(p => p.Text.Trim())
            .FirstOrDefault(t => t.Length > 3);

        var footerText = footerResult.Text;

        var totalMatch = Regex.Match(footerText,
            @"(?:Total|Grand Total):?\s*\$?\s*([\d,]+\.\d{2})",
            RegexOptions.IgnoreCase);

        var taxMatch = Regex.Match(footerText,
            @"(?:Tax|Sales Tax|VAT):?\s*\$?\s*([\d,]+\.\d{2})",
            RegexOptions.IgnoreCase);

        return (
            Vendor: vendor,
            Total: totalMatch.Success
                ? decimal.Parse(totalMatch.Groups[1].Value.Replace(",", ""))
                : (decimal?)null,
            Tax: taxMatch.Success
                ? decimal.Parse(taxMatch.Groups[1].Value.Replace(",", ""))
                : (decimal?)null
        );
    }
}
C#

CropRectangle leva (x, y, width, height) em pixels. Processar apenas o cabeçalho e o rodapé é mais rápido do que ler a página inteira e evita correspondências falsas devido aos valores dos itens no corpo do recibo. O guia de OCR baseado em regiões aborda estratégias de medição de coordenadas para documentos de tamanho variável, e o exemplo de recorte de região mostra o padrão completo.

Categorização de despesas com dados estruturados em parágrafos

Veryfi retorna response.LineItems como um array pré-estruturado de objetos com Description, Quantity, UnitPrice, e Total já analisados.IronOCR fornece o equivalente através de result.Pages[0].Paragraphs e result.Lines, que expõem cada bloco de texto com suas coordenadas X/Y. A lógica de categorização de despesas — que decide se um item de linha é uma despesa com refeição, viagem, suprimentos ou software — opera no mesmo texto em ambos os casos. A diferença é que, com o IronOCR, a lógica de categorização é sua, você pode ajustá-la e estendê-la sem precisar pagar por um novo ciclo de treinamento de aprendizado de máquina.

Abordagem Veryfi:

using Veryfi;

public class ExpenseCategorizer
{
    private readonly VeryfiClient _client;

    public ExpenseCategorizer(VeryfiClient client)
    {
        _client = client;
    }

    public async Task<Dictionary<string, decimal>> CategorizeExpensesAsync(string receiptPath)
    {
        var bytes = File.ReadAllBytes(receiptPath);
        var response = await _client.ProcessDocumentAsync(bytes);

        var categories = new Dictionary<string, decimal>();

        // Line items arrive pre-parsed from Veryfi's ML pipeline
        foreach (var item in response.LineItems ?? Enumerable.Empty<dynamic>())
        {
            var category = response.Category ?? "Uncategorized";
            var amount   = (decimal)(item.Total ?? 0m);

            if (!categories.ContainsKey(category))
                categories[category] = 0m;

            categories[category] += amount;
        }

        return categories;
    }
}
C#

Abordagem IronOCR:

using IronOcr;
using System.Text.RegularExpressions;

public class ExpenseCategorizer
{
    private readonly IronTesseract _ocr = new IronTesseract();

    // Keyword-based categorization — tune these for your expense policy
    private static readonly Dictionary<string, string[]> CategoryKeywords = new()
    {
        ["Meals & Entertainment"] = new[] { "restaurant", "cafe", "coffee", "lunch", "dinner", "food", "bar" },
        ["Travel"]                = new[] { "airline", "hotel", "uber", "lyft", "taxi", "parking", "gas", "fuel" },
        ["Office Supplies"]       = new[] { "staples", "office depot", "paper", "ink", "toner", "supplies" },
        ["Software & Subscriptions"] = new[] { "adobe", "microsoft", "github", "aws", "azure", "slack" }
    };

    public Dictionary<string, decimal> CategorizeExpenses(string receiptPath)
    {
        var result = _ocr.Read(receiptPath);

        // Use paragraph coordinates to isolate line items
        // Line items typically appear in the middle vertical band of the receipt
        var lineItemParagraphs = result.Pages[0].Paragraphs
            .Where(p => p.Y > 150 && p.Y < 650) // skip header/footer regions
            .OrderBy(p => p.Y)
            .ToList();

        var categories = new Dictionary<string, decimal>();
        var pricePattern = new Regex(@"\$?([\d,]+\.\d{2})$");
        var vendorText   = result.Text.ToLower();

        // Determine top-level category from vendor name
        var topCategory = "Uncategorized";
        foreach (var (cat, keywords) in CategoryKeywords)
        {
            if (keywords.Any(kw => vendorText.Contains(kw)))
            {
                topCategory = cat;
                break;
            }
        }

        // Extract individual line item amounts
        foreach (var para in lineItemParagraphs)
        {
            var priceMatch = pricePattern.Match(para.Text.Trim());
            if (!priceMatch.Success)
                continue;

            if (!decimal.TryParse(priceMatch.Groups[1].Value.Replace(",", ""), out var amount))
                continue;

            // Classify individual items where keywords appear in the description
            var itemCategory = topCategory;
            var descriptionText = para.Text.ToLower();
            foreach (var (cat, keywords) in CategoryKeywords)
            {
                if (keywords.Any(kw => descriptionText.Contains(kw)))
                {
                    itemCategory = cat;
                    break;
                }
            }

            if (!categories.ContainsKey(itemCategory))
                categories[itemCategory] = 0m;

            categories[itemCategory] += amount;
        }

        return categories;
    }
}
C#

A coleção Paragraphs fornece a coordenada Y de cada bloco de texto, o que facilita isolar a zona vertical onde os itens de linha aparecem em um layout padrão de recibo. O guia de acesso a dados estruturados explica a hierarquia completa de Pages, Paragraphs, Lines, Words, e Characters com suas propriedades de coordenadas. Para recibos com baixa qualidade de digitalização — papel amassado, impressão térmica de baixo contraste — o guia de correção da qualidade da imagem abrange filtros de pré-processamento que melhoram a precisão antes da execução da lógica de categorização.

Eliminação de Webhooks e Substituição Síncrona em Lote

Em situações de alto volume de documentos, a Muito bom recomenda notificações baseadas em webhooks em vez de polling. O padrão requer um endpoint HTTPS acessível publicamente, um segredo webhook para verificação de assinatura, uma fila para armazenar os resultados até que o webhook seja acionado e uma lógica de repetição para entregas perdidas. Trata-se de uma infraestrutura significativa para o que, em última análise, é uma solução alternativa para o fato de o OCR na nuvem ser lento em comparação com o processamento local. O IronOCR processa de forma síncrona. Não existe nenhuma lacuna assíncrona a ser preenchida com um webhook.

Abordagem Veryfi:

using Veryfi;
using Microsoft.AspNetCore.Mvc;

// Muito bom webhook receiver — required for high-volume reliable processing
[ApiController]
[Route("webhooks")]
public class VeryfiWebhookController : ControllerBase
{
    private readonly IDocumentResultQueue _queue;

    public VeryfiWebhookController(IDocumentResultQueue queue)
    {
        _queue = queue;
    }

    [HttpPost("veryfi")]
    public IActionResult ReceiveWebhook([FromBody] VeryfiWebhookPayload payload,
                                        [FromHeader(Name = "X-Veryfi-Token")] string token)
    {
        // Validate webhook signature — prevents spoofed payloads
        if (!IsValidSignature(token, payload))
            return Unauthorized();

        // Enqueue result for async downstream consumption
        _queue.Enqueue(new DocumentResult
        {
            DocumentId = payload.Id,
            Vendor     = payload.Data?.Vendor?.Name,
            Total      = payload.Data?.Total
        });

        return Ok();
    }

    private bool IsValidSignature(string token, VeryfiWebhookPayload payload) =>
        // HMAC validation against webhook secret — infrastructure requirement
        token == ComputeHmac(payload, Environment.GetEnvironmentVariable("VERYFI_WEBHOOK_SECRET"));
}

// Document batch submission — fire and forget, results arrive via webhook
public class VeryfiDocumentBatchSubmitter
{
    private readonly VeryfiClient _client;

    public async Task SubmitBatchAsync(string[] documentPaths)
    {
        foreach (var path in documentPaths)
        {
            var bytes = File.ReadAllBytes(path);
            // Submit — result arrives asynchronously via webhook, not here
            await _client.ProcessDocumentAsync(bytes);
        }
    }
}
C#

Abordagem IronOCR:

using IronOcr;
using System.Text.RegularExpressions;
using System.Collections.Concurrent;

// Não webhook controller needed — results are synchronous and local
public class DocumentBatchProcessor
{
    // IronTesseract is thread-safe when one instance is created per thread
    public List<DocumentResult> ProcessBatch(string[] documentPaths)
    {
        var results = new ConcurrentBag<DocumentResult>();

        Parallel.ForEach(documentPaths, documentPath =>
        {
            // One IronTesseract per thread — thread-safe pattern
            var ocr    = new IronTesseract();
            var result = ocr.Read(documentPath);

            results.Add(new DocumentResult
            {
                FilePath   = documentPath,
                Vendor     = ExtractVendor(result),
                Total      = ExtractTotal(result.Text),
                Confidence = result.Confidence,
                // Result is available immediately — no queue, no webhook
                ProcessedAt = DateTime.UtcNow
            });
        });

        return results.OrderBy(r => r.FilePath).ToList();
    }

    private string ExtractVendor(OcrResult result)
    {
        // Vendor: first substantive paragraph ordered by vertical position
        return result.Pages[0].Paragraphs
            .OrderBy(p => p.Y)
            .Select(p => p.Text.Trim())
            .FirstOrDefault(t => !string.IsNullOrWhiteSpace(t) && t.Length > 3);
    }

    private decimal? ExtractTotal(string text)
    {
        var match = Regex.Match(text,
            @"(?:Total|Grand Total|Amount Due):?\s*\$?\s*([\d,]+\.\d{2})",
            RegexOptions.IgnoreCase);
        return match.Success
            ? decimal.Parse(match.Groups[1].Value.Replace(",", ""))
            : (decimal?)null;
    }
}

public class DocumentResult
{
    public string FilePath   { get; set; }
    public string Vendor     { get; set; }
    public decimal? Total    { get; set; }
    public double Confidence { get; set; }
    public DateTime ProcessedAt { get; set; }
}
C#

A remoção da camada de webhook elimina o endpoint HTTPS, a exigência de rotação do segredo do webhook, a fila de resultados, a lógica de validação HMAC e a configuração de repetição. Toda a infraestrutura subsequente só existe porque os resultados do Muito bom chegam de forma assíncrona de um servidor remoto. Com IronOCR, Parallel.ForEach substitui tudo isso. O exemplo de multithreading demonstra o padrão IronTesseract por thread em detalhes, e o guia de OCR assíncrono cobre a integração de Task.Run para a responsividade da interface do usuário. O guia de otimização de velocidade aborda a configuração da instância para obter o máximo desempenho em cargas de trabalho em lote.

Referência de mapeamento da API Muito bom para o IronOCR

Muito bomEquivalente de IronOCR
new VeryfiClient(clientId, clientSecret, username, apiKey)new IronTesseract() + IronOcr.License.LicenseKey = "key"
_client.ProcessDocumentAsync(bytes)ocr.Read(filePath) ou ocr.Read(ocrInput)
_client.ProcessDocumentAsync(bytes, categories: new[] { "invoices" })input.LoadPdf(caminho); ocr.Read(entrada)
_client.ProcessDocumentAsync(bytes, categories: new[] { "bank_statements" })input.LoadPdf(caminho); ocr.Read(entrada)
response.Vendor?.NamePrimeiro parágrafo ordenado por p.Y de result.Pages[0].Paragraphs
response.TotalRegex.Match(result.Text, @"Total:?\s*\$?([\d,]+\.\d{2})")
response.TaxRegex.Match(result.Text, @"Tax:?\s*\$?([\d,]+\.\d{2})")
response.DateRegex.Match(result.Text, @"\d{1,2}/\d{1,2}/\d{4}")
response.LineItemsresult.Pages[0].Paragraphs filtrado por intervalo de coordenadas Y
response.InvoiceNumberRegex.Match(result.Text, @"Invoice\s*#?\s*:?\s*(\w+[-\w]*)")
response.BankAccount?.AccountNumberRegex.Match(result.Text, @"Account\s*#?\s*:?\s*(\d{4,})")
response.BankAccount?.RoutingNumberRegex.Match(result.Text, @"Routing\s*#?\s*:?\s*(\d{9})")
response.ConfidenceScoreresult.Confidence (no geral) ou word.Confidence (por palavra)
response.Payment?.Last4Regex.Match(result.Text, @"\*{4}\s*(\d{4})")
VeryfiApiException (401/402/429/500)Exceções padrão do .NET — sem códigos de erro HTTP para processamento local.
Codificação Base64 antes do uploadNão requerido — ocr.Read(filePath) aceita caminhos de arquivos diretamente
response.CategoryCorrespondência de palavra-chave personalizada contra result.Text
desserialização da carga útil do webhookNão requerido — ocr.Read() retorna o resultado de forma síncrona
ProcessDocumentAsync com tentativa/recuperaçãoNão é necessário — não há limites de taxa para processamento local.

Problemas e soluções comuns em migrações

Problema 1: Campos pré-analisados ​​ausentes

Veryfi: response.Vendor?.Name, response.Total, e response.LineItems chegam como campos estruturados de um modelo de ML pré-treinado. Nenhuma lógica de extração é necessária no lado do cliente.

Solução: Escreva padrões Regex para cada campo utilizado pela sua aplicação. O processo de migração normalmente leva de 8 a 24 horas, dependendo da quantidade de layouts de documentos distintos que você precisa processar. Para padrões comuns de recibos e faturas, o tutorial de OCR para faturas e o tutorial de digitalização de recibos fornecem implementações completas de padrões de extração.

// Map each Muito bom field to a Regex extraction
private static readonly Dictionary<string, string> FieldPatterns = new()
{
    ["InvoiceNumber"] = @"Invoice\s*#?\s*:?\s*(\w+[-\w]*)",
    ["PurchaseOrder"]  = @"(?:PO|P\.O\.|Purchase Order)\s*#?\s*:?\s*(\w+)",
    ["DueDate"]        = @"Due\s*(?:Date)?:?\s*(\d{1,2}/\d{1,2}/\d{4})",
    ["PaymentTerms"]   = @"(?:Terms|Net)\s*:?\s*(\w+\s*\d+)"
};

public string ExtractField(string text, string fieldName)
{
    if (!FieldPatterns.TryGetValue(fieldName, out var pattern))
        return null;
    var match = Regex.Match(text, pattern, RegexOptions.IgnoreCase);
    return match.Success ? match.Groups[1].Value.Trim() : null;
}
C#

Problema 2: Assinaturas de Métodos Assíncronos em Toda a Base de Código

Veryfi: ProcessDocumentAsync é assíncrono no nível do SDK da Veryfi. As equipes tipicamente propagam await através de cada método de chamada na pilha de chamadas, significando que classes de serviços, controladores e trabalhos em segundo plano todos carregam assinaturas async Task<t>.

Solução: O Read() do IronOCR é síncrono. As assinaturas de método async existentes podem ser preservadas envolvidas com Task.Run durante o período de transição. Isso evita alterações em massa nas assinaturas em toda a base de código, eliminando ao mesmo tempo a dependência da nuvem.

// Preserve async signature during transition — no codebase-wide refactor needed
public async Task<string> GetVendorNameAsync(string documentPath)
{
    return await Task.Run(() =>
    {
        var result = _ocr.Read(documentPath);
        return result.Pages[0].Paragraphs
            .OrderBy(p => p.Y)
            .Select(p => p.Text.Trim())
            .FirstOrDefault(t => t.Length > 3);
    });
}
C#

Problema 3: Configuração de credenciais dispersa em diferentes ambientes

Veryfi: Quatro credenciais (Veryfi:ClientId, Veryfi:ClientSecret, Veryfi:Username, Veryfi:ApiKey) aparecem em appsettings.json, blocos de variáveis de ambiente em arquivos Docker Compose, segredos de Ações GitHub, referências de Azure Key Vault e configurações de pipeline CI/CD.

Solução: Pesquise e remova todas as quatro entradas de credenciais de todos os ambientes. Adicionar uma única variável de ambiente IRONOCR_LICENSE_KEY. Carregue-o na inicialização.

# Find all Muito bom credential references
grep -r "Veryfi:ClientId\|Veryfi:ClientSecret\|Veryfi:Username\|Veryfi:ApiKey" \
    --include="*.json" --include="*.yml" --include="*.yaml" --include="*.env" .
SHELL
// Load from environment at startup
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
    ?? throw new InvalidOperationException("IRONOCR_LICENSE_KEY not set");
C#

Problema 4: Problemas de qualidade de digitalização não visíveis anteriormente

Veryfi: O processamento em nuvem inclui aprimoramento de imagem no servidor antes da execução da inferência de aprendizado de máquina. As digitalizações de recibos de baixa qualidade — papel amassado, impressão térmica desbotada, fotos distorcidas tiradas com celular — foram corrigidas silenciosamente antes da extração dos dados.

Solução: Aplique explicitamente o pipeline de pré-processamento do IronOCR. Deskew(), DeNoise(), e Contrast() cobrem a maioria dos problemas de qualidade de escaneamento de recibos do mundo real.

using var input = new OcrInput();
input.LoadImage("receipt-phone-photo.jpg");
input.Deskew();        // correct rotation from angled phone capture
input.DeNoise();       // remove compression artifacts
input.Contrast();      // improve faded thermal print
input.Sharpen();       // recover edge detail

var result = _ocr.Read(input);
C#

O guia de correção da qualidade da imagem e o tutorial de filtros de imagem abordam quais filtros aplicar para padrões específicos de degradação da digitalização.

Problema 5: Capacidade de Processamento em Lote de Alto Volume

Veryfi: Os limites de taxa restringem a velocidade de envio de documentos. As respostas HTTP 429 exigem lógica de recuo exponencial. A taxa de transferência é limitada pelo limite de taxa por plano da Veryfi, não pelo seu hardware.

Solução: O IronOCR é limitado apenas pelos núcleos da CPU. Use Parallel.ForEach com uma instância IronTesseract por thread. Em um servidor de 8 núcleos, a taxa de transferência aumenta aproximadamente de forma linear com o número de núcleos.

// One IronTesseract per thread — do not share instances across threads
Parallel.ForEach(
    documentPaths,
    new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
    path =>
    {
        var ocr    = new IronTesseract();
        var result = ocr.Read(path);
        SaveResult(path, result.Text, result.Confidence);
    });
C#

Problema 6: Esquema JSON proprietário bloqueado para Veryfi

Veryfi: Todo o código de extração lê do esquema de resposta da Veryfi: response.Vendor?.Name, response.LineItems, response.BankAccount?.RoutingNumber. Este código funciona apenas com o SDK da Veryfi. Qualquer alteração no nome de um campo durante uma atualização da API Muito bom quebra o código do aplicativo.

Solução: A extração do IronOCR usa System.Text.RegularExpressions.Regex padrão do .NET contra texto simples. Os padrões são portáteis, testáveis ​​sem a necessidade de simular nenhum SDK e estão sob seu controle. Os testes unitários são executados sem qualquer conexão de rede.

// Extraction logic that is fully portable and unit-testable
[Fact]
public void ExtractsRoutingNumberFromInvoiceText()
{
    const string sampleText = "Routing Number: 021000021\nAccount: 1234567890";
    var match = Regex.Match(sampleText, @"Routing\s*(?:Number)?:?\s*(\d{9})",
                            RegexOptions.IgnoreCase);
    Assert.True(match.Success);
    Assert.Equal("021000021", match.Groups[1].Value);
}
C#

Lista de verificação para migração Veryfi

Pré-migração

Antes de modificar qualquer código, faça uma auditoria do código-fonte para inventariar todo o uso do Veryfi:

# Find all Muito bom using statements
grep -rn "using Veryfi" --include="*.cs" .

# Find all VeryfiClient instantiations
grep -rn "VeryfiClient\|ProcessDocumentAsync" --include="*.cs" .

# Find all Muito bom response field accesses
grep -rn "response\.Vendor\|response\.Total\|response\.LineItems\|response\.BankAccount" --include="*.cs" .

# Find all credential configuration references
grep -r "Veryfi:ClientId\|Veryfi:ClientSecret\|Veryfi:Username\|Veryfi:ApiKey" \
    --include="*.json" --include="*.yml" --include="*.yaml" --include="*.env" .

# Find all webhook-related code
grep -rn "VeryfiWebhook\|X-Veryfi-Token\|webhook" --include="*.cs" .
SHELL

Grave o total de sites de chamadas ProcessDocumentAsync, a lista de campos de resposta acessados por site de chamada e a lista de ambientes contendo credenciais Veryfi.

Migração de código

  1. Remova o pacote NuGet Veryfi de todos os projetos na solução.
  2. Instale o pacote NuGet IronOcr em todos os projetos que anteriormente referenciavam Veryfi.
  3. Adicione IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; ao início do aplicativo (antes de qualquer chamada OCR).
  4. Substitua todas as declarações using Veryfi; e using Veryfi.Models; por using IronOcr;.
  5. Substitua a injeção de construtor VeryfiClient por inicialização de campo IronTesseract.
  6. Remova todas as quatro entradas de credenciais Muito bom de cada appsettings.json, appsettings.*.json, e arquivo de configuração de segredos.
  7. Converta chamadas ProcessDocumentAsync(bytes) para ocr.Read(filePath) ou ocr.Read(ocrInput).
  8. Substitua os acessos response.Vendor?.Name por extração de texto ordenado por parágrafo de result.Pages[0].Paragraphs.
  9. Substitua os acessos aos campos estruturados response.Total, response.Tax, response.InvoiceNumber e outros, por padrões Regex contra result.Text.
  10. Substitua a iteração response.LineItems por iteração result.Pages[0].Paragraphs filtrado por coordenada Y.
  11. Exclua as classes do controlador de webhook e remova os registros de endpoints de webhook.
  12. Remova as variáveis ​​de ambiente secretas do webhook de todos os ambientes.
  13. Adicione OcrInput com pré-processamento (Deskew(), DeNoise(), Contrast()) para entradas de imagem escaneadas.
  14. Substitua os loops sequenciais single-threaded por Parallel.ForEach usando um IronTesseract por thread.
  15. Adicione IRONOCR_LICENSE_KEY a todas as configurações de variáveis de ambiente e armazenamentos de segredos de CI/CD.

Pós-migração

  • Verifique se não há chamadas de rede Muito bom nos registros de tráfego HTTP após a implantação da migração.
  • Confirme se os nomes dos fornecedores extraídos correspondem aos valores esperados em uma amostra de 20 a 50 recibos.
  • Confirme se os totais extraídos correspondem aos valores esperados dentro de uma tolerância de US$ 0,01 para o mesmo conjunto de amostras.
  • Verificar se a extração do número da fatura é bem-sucedida para cada formato de fatura no conjunto de documentos.
  • Testar a taxa de transferência do processamento em lote em comparação com a taxa de transferência de referência do Muito bom para confirmar a remoção do limite de taxa.
  • Execute o Suite completo de testes sem qualquer conexão de rede para confirmar a ausência de dependência da nuvem.
  • Confirme que as pontuações result.Confidence excedem 80% para escaneamentos de documentos limpos; Valores abaixo de 80% indicam que uma etapa de pré-processamento deve ser adicionada.
  • Verifique se todas as quatro credenciais do Muito bom foram removidas de todos os ambientes (desenvolvimento, teste e produção).
  • Confirme se os endpoints do webhook retornam 404 ou se foram removidos da tabela de roteamento.
  • Testar o comportamento em digitalizações de recibos de baixa qualidade (amassados, desbotados, tortos) com o pipeline de pré-processamento ativo.

Principais benefícios da migração para o IronOCR

Os documentos financeiros processados ​​localmente são documentos que não podem ser acessados ​​por terceiros. Após a migração, os números de contas bancárias extraídos de faturas, os números de roteamento obtidos de cheques e os históricos de transações lidos de extratos bancários são todos processados ​​em seu hardware. Nenhum incidente de segurança de terceiros, acesso a dados de subcontratados ou violação da infraestrutura da Muito bom pode expor documentos que nunca saíram dos seus servidores.

Os custos por documento caem para zero no dia em que a migração é implementada. Com 50.000 documentos por mês, o item de custo mensal do Veryfi, que variava de US$ 5.000 a US$ 15.000, desaparece. A licença IronOCR Professional , que custa US$ 2.999 e é adquirida uma única vez, é recuperada na primeira semana do primeiro mês. Em volumes maiores, as economias se acumulam a cada ano, sem necessidade de negociação de descontos por volume ou renovação de contrato.

A capacidade de processamento escala com o hardware, não com os limites de taxa do fornecedor. Respostas HTTP 429, limites de taxa de transferência por plano e cobranças sazonais por excesso de uso são artefatos arquitetônicos de APIs em nuvem. Com o IronOCR, adicionar núcleos de CPU aumenta a capacidade de processamento proporcionalmente. Um lote de 10.000 recibos é processado de acordo com o seu cronograma, e não com base na programação de limite de taxa da Veryfi.

Qualquer tipo de documento é processado com a mesma API. A organização não precisa mais de uma segunda ferramenta de OCR quando o RH solicita o processamento de formulários de integração, o departamento jurídico precisa extrair o texto de contratos ou a área de operações precisa de dados de documentos de remessa. ocr.Read() lida com todos eles. O tutorial de leitura de texto em imagens e os guias de documentos especializados abrangem toda a gama de formatos de documentos que o IronOCR suporta.

A lógica de extração torna-se parte integrante do código-fonte. Os padrões de expressões regulares estão no controle de versão, podem ser revisados ​​em pull requests, testados em testes unitários sem a necessidade de simular nenhum SDK e ajustados com base no feedback da produção. Quando o modelo pré-treinado da Muito bom retorna um nome de fornecedor incorreto, não há nada para ajustar. Quando o padrão de extração do IronOCR retorna um nome de fornecedor incorreto, a correção consiste em uma alteração de expressão regular de uma linha com um teste unitário. A página de licenciamento do IronOCR aborda as opções de planos, incluindo a assinatura SaaS para equipes que preferem o faturamento anual em vez da compra perpétua.

A infraestrutura de implantação é reduzida a um único pacote NuGet que pode ser executado em qualquer lugar. O IronOCR é instalado como um único pacote, sem dependências externas, sem gerenciamento de binários nativos e sem configuração da pasta tessdata. A mesma referência de pacote é resolvida no Windows, Linux, macOS, Docker, Azure App Service e AWS Lambda sem código condicional à plataforma. Consulte o guia de implantação do Docker e o guia de implantação do Linux para ambientes conteinerizados onde o requisito de saída de rede do Muito bom representa um obstáculo à implantação.

Observe: Tesseract e Muito bom são marcas registradas de seus respectivos proprietários. Este site não é afiliado, endossado ou patrocinado pelo Google ou Veryfi. Todos os nomes de produtos, logotipos e marcas são propriedade de seus respectivos proprietários. As comparações são apenas para fins informativos e refletem informações disponíveis publicamente no momento da redação.

Artigos relacionados

Key in blue circle

Obtenha sua chave de avaliação gratuita de 30 dias instantaneamente.

Your trial license will be sent to your email address

Sem limitações. 100% desbloqueado. Sem cartão de crédito.

bullet_checkedNão é necessário cartão de crédito nem criação de conta.Sem limitações. 100% desbloqueado. Sem cartão de crédito.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Agende sua consulta sem compromisso.
Preencha o formulário abaixo ou envie um e-mail para sales@ironsoftware.com
Os seus dados serão sempre mantidos em sigilo.
Aprovado por milhões de engenheiros em todo o mundo.
Logotipos dos clientes da Iron Software
Obtenha sua chave de avaliação gratuita de 30 dias instantaneamente.
Não é necessário cartão de crédito nem criação de conta.