Ir para o conteúdo do rodapé
USANDO O IRONPDF

Recibos em PDF e registros de transações em C# para aplicativos de tecnologia financeira.

Um problema de conformidade, não apenas um problema de formatação.

! Página inicial do IronPDF A maioria das aplicações FinTech armazena dados de transações em um banco de dados relacional e gera recibos sob demanda; quando um cliente solicita um, a aplicação consulta novamente o registro e exibe uma visualização. Essa abordagem tem um problema fundamental: o PDF ou "recibo" resultante reflete o estado atual dos dados, não o que o cliente viu no momento em que a transação foi concluída.

Os registros do banco de dados podem ser corrigidos, alterados ou atualizados por meio de processos operacionais normais. Um recibo consultado novamente não é um documento histórico, mas sim um instantâneo atual com um registro de data e hora anterior. Quando um processador de pagamentos enfrenta um estorno, quando a equipe de compliance de um neobanco responde a um órgão regulador, quando o registro de auditoria de uma plataforma de empréstimos é solicitado por intimação ou quando uma corretora de criptomoedas precisa demonstrar a integridade de um documento a um examinador de KYC (Conheça Seu Cliente), é necessário haver um documento, não uma consulta.

Um documento PDF armazenado no momento da liquidação, criptografado para detecção de adulteração e gravado em armazenamento imutável é esse documento. Isso garante que os documentos PDF existentes permaneçam válidos por anos. Quer se trate de relatórios financeiros ou de um simples primeiro PDF, a geração do documento deve ser definitiva.

As obrigações de registro de acordo com as normas PCI-DSS, SOX e AML não exigem especificamente documentos em PDF, mas exigem registros demonstráveis ​​e auditáveis. Um arquivo PDF renderizado, com hash e registro de data e hora, atende a esse requisito de uma forma que uma linha de banco de dados sozinha não atende. Mais adiante neste artigo, veremos um exemplo do IronPDF para demonstrar como esse processo funciona na criação de um novo documento PDF.

A solução em resumo: Converter conteúdo HTML para PDF em C

A biblioteca IronPDF da Iron Software gera um recibo em PDF no exato momento em que uma transação é concluída, de forma síncrona, como parte do fluxo de transações. Você pode instalar o IronPDF através do Gerenciador de Pacotes NuGet ou do Console do Gerenciador de Pacotes no Visual Studio. Usando a CLI do .NET, basta executar o comando install package IronPDF.

O recibo é gerado a partir de um modelo HTML ou arquivo HTML , marcado com um ID de transação e um carimbo de data/hora, criptografado e gravado em um armazenamento imutável. Este se torna o documento final. Não há definição SSRS para manter, nenhuma API de documentos de terceiros para chamar e nenhum sidecar de navegador headless. O IronPDF é executado no mesmo processo como uma biblioteca NuGet para tarefas de PDF.

Principais benefícios da automatização de fluxos de trabalho de documentos:

  • Preservar a formatação em todos os tamanhos de página.

  • Suporte para assinaturas digitais para garantir a integridade dos documentos.

  • Capacidade de criar objetos PDF a partir de uma página da web ou de uma string HTML.

  • Os logotipos e a identidade visual dos clientes da Iron Software podem ser incorporados facilmente.

Como funciona um pipeline de transação a recibo

O Caminho Feliz

O pagamento é efetuado com sucesso e o registro da transação é gravado no banco de dados. O mesmo manipulador — antes de retornar uma resposta — preenche um modelo de recibo de conteúdo HTML com os detalhes da transação: ID, carimbo de data/hora UTC, valor e moeda, identificadores do remetente e do destinatário, detalhamento das taxas e conteúdo dinâmico.

O renderizador new ChromePdfRenderer (especificamente var renderer = new ChromePdfRenderer();) converte o conteúdo da web para o formato PDF. O array de bytes do PDF resultante é imediatamente criptografado usando o algoritmo SHA-256.

using IronPdf
using System.Security.Cryptography;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.MarginTop = 15;

renderer.RenderingOptions.MarginBottom = 15;

string receiptHtml = $@"
    <h1>Transaction Receipt</h1>
    <p><strong>Transaction ID:</strong> {tx.Id}</p>
    <p><strong>Timestamp (UTC):</strong> {tx.CompletedAt:u}</p>
    <p><strong>Amount:</strong> {tx.Amount:F2} {tx.Currency}</p>
    <p><strong>Fee:</strong> {tx.Fee:F2} {tx.Currency}</p>
    <p><strong>From:</strong> {tx.SenderRef} &rarr; <strong>To:</strong> {tx.ReceiverRef}</p>
    <p><strong>Resulting Balance:</strong> {tx.ClosingBalance:F2} {tx.Currency}</p>";

var pdf = renderer.RenderHtmlAsPdf(receiptHtml);

string hash = Convert.ToHexString(SHA256.HashData(pdf.BinaryData));

await _db.StoreReceiptHashAsync(tx.Id, hash);

await _blobStorage.UploadImmutableAsync($"receipts/{tx.Id}.pdf", pdf.BinaryData);
using IronPdf
using System.Security.Cryptography;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.MarginTop = 15;

renderer.RenderingOptions.MarginBottom = 15;

string receiptHtml = $@"
    <h1>Transaction Receipt</h1>
    <p><strong>Transaction ID:</strong> {tx.Id}</p>
    <p><strong>Timestamp (UTC):</strong> {tx.CompletedAt:u}</p>
    <p><strong>Amount:</strong> {tx.Amount:F2} {tx.Currency}</p>
    <p><strong>Fee:</strong> {tx.Fee:F2} {tx.Currency}</p>
    <p><strong>From:</strong> {tx.SenderRef} &rarr; <strong>To:</strong> {tx.ReceiverRef}</p>
    <p><strong>Resulting Balance:</strong> {tx.ClosingBalance:F2} {tx.Currency}</p>";

var pdf = renderer.RenderHtmlAsPdf(receiptHtml);

string hash = Convert.ToHexString(SHA256.HashData(pdf.BinaryData));

await _db.StoreReceiptHashAsync(tx.Id, hash);

await _blobStorage.UploadImmutableAsync($"receipts/{tx.Id}.pdf", pdf.BinaryData);
Imports IronPdf
Imports System.Security.Cryptography

Dim renderer As New ChromePdfRenderer()

renderer.RenderingOptions.MarginTop = 15

renderer.RenderingOptions.MarginBottom = 15

Dim receiptHtml As String = $"
    <h1>Transaction Receipt</h1>
    <p><strong>Transaction ID:</strong> {tx.Id}</p>
    <p><strong>Timestamp (UTC):</strong> {tx.CompletedAt:u}</p>
    <p><strong>Amount:</strong> {tx.Amount:F2} {tx.Currency}</p>
    <p><strong>Fee:</strong> {tx.Fee:F2} {tx.Currency}</p>
    <p><strong>From:</strong> {tx.SenderRef} &rarr; <strong>To:</strong> {tx.ReceiverRef}</p>
    <p><strong>Resulting Balance:</strong> {tx.ClosingBalance:F2} {tx.Currency}</p>"

Dim pdf = renderer.RenderHtmlAsPdf(receiptHtml)

Dim hash As String = Convert.ToHexString(SHA256.HashData(pdf.BinaryData))

Await _db.StoreReceiptHashAsync(tx.Id, hash)

Await _blobStorage.UploadImmutableAsync($"receipts/{tx.Id}.pdf", pdf.BinaryData)
$vbLabelText   $csharpLabel

Exemplo de documento PDF gerado

! Exemplo de saída em PDF do IronPDF O novo documento PDF é então armazenado em um local imutável. Quer seja seu primeiro PDF ou se você estiver mesclando PDFs existentes, o processo permanece o mesmo. Uma cópia é exibida em um visualizador de PDF para o cliente. Durante uma demonstração de produto da Iron Software , a equipe de demonstração costuma destacar como apenas algumas linhas de código podem lidar com relatórios dinâmicos e tarefas como conversão de HTML para PDF ou geração de PDFs.

Para auxiliar na experiência do usuário (UI/UX), você poderá ver uma chave dentro de um círculo azul, uma chave dentro de um círculo cinza ou uma chave dentro de um círculo azul no painel para indicar um arquivo criptografado e seguro. Um ícone de seta à direita, relacionado ao link de download, ajuda os usuários a navegar.

Um cabeçalho ou rodapé carimbado reforça a proveniência do documento em todas as páginas:

var shortHash = hash[..12];

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = $@"
        <div style='font-size:9px; color:#666; text-align:center;'>
            Generated: {tx.CompletedAt:u} &nbsp;|&nbsp;
            TX: {tx.Id} &nbsp;|&nbsp;
            SHA-256: {shortHash}...
        </div>"
};
var shortHash = hash[..12];

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = $@"
        <div style='font-size:9px; color:#666; text-align:center;'>
            Generated: {tx.CompletedAt:u} &nbsp;|&nbsp;
            TX: {tx.Id} &nbsp;|&nbsp;
            SHA-256: {shortHash}...
        </div>"
};
HTML

Exemplo de rodapé

! Exemplo de rodapé Cada página do recibo contém o ID da transação, o carimbo de data/hora de geração e um hash truncado, o suficiente para que um responsável pela conformidade verifique a integridade sem precisar acessar o banco de dados.

Os casos extremos

Estornos e reembolsos. Mesmo uma transação falhada ou estornada requer um documento. Gere um PDF separado para o evento de estorno, fazendo referência ao ID da transação original e ao hash do recibo. O recibo de estorno serve como registro independente do ocorrido, não substituindo nem modificando o original.

Transações em múltiplas moedas. O modelo HTML deve lidar corretamente com a colocação dos símbolos das moedas, os separadores decimais e a exibição das taxas de câmbio de acordo com a localidade. As strings de formatação do C# lidam com a maior parte disso: {amount.ToString("F2", CultureInfo.GetCultureInfo("de-DE"))} para convenções decimais alemãs, colocação explícita de símbolos para moedas como o JPY que não usam casas decimais. A taxa de câmbio e seu registro de data e hora devem aparecer como um item discriminado, e não inferidos a partir dos valores.

Marcas d'água regulamentares. Algumas jurisdições exigem textos específicos em determinados tipos de documentos, como "NÃO É UMA NOTA FISCAL", "CÓPIA NÃO OFICIAL" ou linguagem de divulgação específica da jurisdição. Esses elementos são tratados de forma clara como uma sobreposição HTML no modelo ou como uma faixa de cabeçalho estilizada, sem modificar os dados de transação subjacentes.

Por que isso importa além da conformidade?

Parte interessada O que eles recebem
Conformidade/Jurídico Recibos imutáveis ​​e criptografados que atendem às solicitações de auditoria em minutos, sem necessidade de novas consultas, reconstruções ou explicações sobre a diferença entre o registro atual do banco de dados e o que o cliente visualizou.
Suporte ao Cliente O documento exato que o cliente recebeu no momento da transação, tornando a resolução de disputas factual em vez de interpretativa.
Clientes Um recibo Professional e personalizado na caixa de entrada do cliente em segundos após cada transação, o mesmo documento que a empresa mantém em seus arquivos.
Engenharia Um único modelo HTML para manter, renderizado em tempo real, sem dependência de serviços externos, sem contrato de API para monitorar e sem cobrança por documento para acompanhar.
Finanças / Contabilidade PDF/A: Saída arquivística para retenção a longo prazo, alinhada às políticas de retenção de documentos e que atende aos requisitos de registro financeiro sem a necessidade de um fluxo de trabalho de arquivamento separado.

PontasHabilite a saída em PDF/A com uma única opção de renderização — renderer.RenderingOptions.PdfArchiveFormat = IronPDF— para produzir documentos arquivísticos padronizados pela ISO, aceitáveis ​​para a retenção de registros financeiros a longo prazo.

Encerramento

A diferença entre "armazenamos dados de transação" e "temos um registro auditável" é menor do que parece; trata-se de uma única etapa de renderização adicionada ao fluxo de confirmação da transação. Essa etapa produz um documento com uma procedência que uma linha de banco de dados sozinha não pode fornecer: um carimbo de data/hora que não pode ser retrodatado, um hash que detecta adulterações e um artefato físico que tem a mesma aparência, seja quando aberto por um cliente ou quando solicitado por um auditor.

O IronPDF oferece às equipes .NET controle total sobre essa etapa, desde a renderização do recibo HTML até a inclusão do rodapé, o cálculo do hash da saída e o envio para armazenamento imutável, tudo a partir de uma única biblioteca em IronPDF . Se você estiver criando ou reforçando um fluxo de transações, inicie seu teste gratuito de 30 dias e valide a saída do recibo em relação aos seus requisitos de conformidade antes de entrar em produção.

Curtis Chau
Redator Técnico

Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais ...

Leia mais

Equipe de suporte de ferro

Estamos online 24 horas por dia, 5 dias por semana.
Bater papo
E-mail
Liga para mim