跳至页脚内容
使用IRONPDF

适用于金融科技应用的 C# PDF 收据和交易记录

这不仅是排版问题,更是合规问题

IronPDF 主页 大多数金融科技应用将交易数据存储在关系型数据库中,并按需生成收据:当客户提出请求时,应用会重新查询记录并生成视图。 这种方法存在一个根本性问题:生成的 PDF 或"收据"反映的是数据的当前状态,而非客户在交易完成时所看到的画面。

数据库记录可通过常规操作流程进行更正、修改或更新。 重新查询的收据并非历史文件,而是一个带有过去时间戳的当前快照。当支付处理商面临退款纠纷、数字银行的合规团队回应监管机构、贷款平台的审计日志被传唤,或加密货币交易所需要向 KYC 审查员证明文件完整性时,需要的是一份文件,而非查询结果。

在结算时存储、经过哈希处理以检测篡改、并写入不可变存储中的 PDF 文档,即为该文档。 这确保了现有 PDF 文档在未来数年内仍保持有效。 无论您处理的是财务报告还是简单的首份 PDF,文档生成都必须一蹴而就。

PCI-DSS、SOX 和 AML 的记录保存义务并未明确要求必须通过编程生成 PDF 文档,但确实要求提供可验证且可审计的记录。 经过渲染、哈希处理并带有时间戳的 PDF 文件,在满足这一要求方面,是仅凭数据库行无法比拟的。 本文后文将通过一个 IronPDF 示例,展示在创建新 PDF 文档时该流程的具体实现方式。

解决方案概览:使用 C# 将 HTML 内容转换为 PDF

Iron Software 提供的 IronPDF 库会在交易完成的确切时刻,作为交易流程的一部分,同步生成 PDF 收据。您可以通过 NuGet 包管理器或 Visual Studio 中的包管理器控制台安装 IronPDF。 使用 dot NET CLI,只需运行 install package IronPDF。

收据由 HTML 模板或 HTML 文件生成,标注交易 ID 和时间戳,经过哈希处理后写入不可变存储。 此文档即为最终版本。 无需维护 SSRS 定义,无需调用第三方文档 API,也无需使用无头浏览器 sidecar。 IronPDF 作为 NuGet 库在进程内运行,用于处理 PDF 相关任务。

自动化文档工作流的主要优势:

  • 确保在所有页面尺寸下保持格式一致。

  • 支持数字签名以确保文档完整性。

  • 能够从网页或 HTML 字符串创建 PDF 对象。

  • Iron Software 的客户徽标和品牌标识可轻松嵌入

交易到收据的处理流程如何运作

正常流程

支付成功后,交易记录将写入数据库。 同一处理程序在返回响应之前,会将交易详情填入 HTML 内容收据模板中:ID、UTC 时间戳、金额和货币、发件人和收件人标识符、手续费明细以及动态内容。

渲染器 new ChromePdfRenderer(具体为 var renderer = new ChromePdfRenderer();)将网页内容转换为 PDF 格式。 生成的 PDF 字节数组将立即使用 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

生成的 PDF 文档示例

IronPDF 示例 PDF 输出 随后,新的 PDF 文档将存储在不可变存储中。 无论是创建首个 PDF 文件,还是合并现有 PDF 文件,操作流程均保持一致。 一份副本将通过 PDF 阅读器呈现给客户。 在 Iron Software 产品演示中,演示团队常会重点展示:仅需几行代码即可处理动态报表,并完成 HTML 转 PDF 或 PDF 生成等任务。

为辅助 UI/UX 设计,您可能会在仪表盘中看到蓝色圆圈内的钥匙、灰色圆圈内的钥匙或蓝色圆圈内的钥匙图标,这些图标表示文件已加密或经过哈希处理。与下载链接相关的右箭头图标可帮助用户进行导航。

每页添加带水印的页眉或页脚,可强化文档的来源可信度:

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

示例页脚

示例页脚 收据的每一页都包含交易 ID、生成时间戳和截断的哈希值,这些信息足以让合规专员在无需访问数据库的情况下对完整性进行抽查。

特殊情况

交易撤销与退款。即使交易失败或被撤销,仍需提供相关文件。 为撤销交易生成一份独立的 PDF 文件,其中需引用原始交易 ID 和收据哈希值。 退货凭证作为独立记录,仅用于记录发生的情况,不会替代或修改原始凭证。

多币种交易。HTML 模板必须根据不同地区设置,正确处理货币符号的位置、小数点分隔符以及汇率披露。 C# 格式字符串可处理其中大部分情况:例如,针对德语小数格式规范,可使用 {amount.ToString("F2", CultureInfo.GetCultureInfo("de-DE"))};对于像 JPY 这样不使用小数点的货币,则需显式放置货币符号。 汇率及其时间戳应作为单独列示的项目呈现,而非通过金额推算得出。

法规水印。某些司法管辖区要求在特定类型的文档上添加特定文本,例如"非税务发票"、"非正式副本"或该管辖区特有的披露声明。 这些内容可通过模板中的 HTML 叠加层或样式化标题条带进行处理,且不修改底层交易数据。

为何这不仅关乎合规

利益相关方 他们将获得
合规 / 法律 不可变的哈希收据,可在数分钟内满足审计请求,无需重新查询、无需重建,也无需解释当前数据库记录为何与客户所见内容存在差异
客户支持 客户在交易时收到的确切文件,使争议解决基于事实而非主观诠释
客户 每次交易完成后数秒内,客户收件箱中便会收到一份Professional且带有品牌标识的收据,该文档与公司存档的版本完全一致
工程 只需维护一个 HTML 模板,在进程内渲染,无需依赖外部服务,无需监控 API 契约,也无需追踪按文档计费
财务 / 会计 PDF/A 归档输出,用于长期保存,既符合文档保留政策,又满足财务记录保存要求,且无需单独的归档工作流

提示通过单个渲染选项启用 PDF/A 输出 — renderer.RenderingOptions.PdfArchiveFormat = IronPdf.Rendering.PdfArchiveFormat.PDF_A_3B — 以生成符合 ISO 标准的归档文档,该格式适用于长期财务记录的保存。

结语

"我们存储交易数据"与"我们拥有可审计的记录"之间的差距其实比表面看起来要小,这仅仅是在交易提交流程中增加了一个渲染步骤。 这一步骤生成的文档具有数据库行本身无法提供的溯源信息:无法倒填的时间戳、可检测篡改的哈希值,以及无论是由客户打开还是审计员调取,外观都完全一致的物理凭证。

IronPDF 使 .NET 团队能够完全掌控这一流程,从渲染 HTML 收据、添加页脚水印、对输出进行哈希处理,到流式传输至不可变存储,所有操作均可通过 ironpdf.com 上的单一库完成。 如果您正在构建或强化交易管道,请立即开始 30 天试用,并在投入生产环境前,根据您的合规要求验证收据输出是否符合规范

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我