跳過到頁腳內容
使用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。 使用 .NET CLI,只需執行 install package IronPDF 即可。

收據由 HTML 範本或 HTML 檔案生成,並附有交易 ID 和時間戳,經過雜湊處理後寫入不可變儲存。 它成為最終文件。 無需維護 SSRS 定義,無需呼叫第三方文件 API,也無需無頭瀏覽器邊車。 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 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我