You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Delphi项目中为生成的PDF发票添加数字签名?求免费Delphi组件方案

可行的免费Delphi PDF数字签名方案(适配加密锁签名)

针对你的需求,完全有靠谱的免费方案实现给生成的PDF添加带加密锁(dongle)的数字签名,结合你用的RAD Studio 10.4,我整理了几个实用的思路和组件:

一、优先推荐:SynPDF + Windows CryptoAPI

SynPDF是Delphi圈里口碑极好的开源免费PDF处理库,原生支持PDF数字签名,而且体积小、集成简单。加密锁的签名可以通过Windows系统自带的CryptoAPI调用,因为大多数加密锁会被系统识别为证书存储的一部分,能直接通过API获取证书。

实现步骤&示例代码

  1. 先确保加密锁驱动安装正常,在Windows「证书管理器」里能看到对应的证书(通常在「个人」存储下)
  2. 用SynPDF加载生成好的PDF,结合CryptoAPI获取加密锁证书,完成签名:
uses SynPDF, SynCrypto, Winapi.WinCrypt, Winapi.Windows;

// 辅助函数:从证书存储中找到加密锁对应的证书
function GetDongleCertificate: PCCERT_CONTEXT;
var
  hStore: HCERTSTORE;
  CertFindPara: CERT_FIND_PARAMS;
begin
  Result := nil;
  // 打开当前用户的个人证书存储
  hStore := CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, 'MY');
  if hStore <> 0 then
  try
    // 这里可以根据证书主题、序列号等条件查找,替换成你的加密锁证书标识
    FillChar(CertFindPara, SizeOf(CertFindPara), 0);
    CertFindPara.dwFindType := CERT_FIND_SUBJECT_STR;
    CertFindPara.pwszFindString := '你的加密锁证书主题名称';
    Result := CertFindCertificateInStore(hStore, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, @CertFindPara, nil);
  finally
    CertCloseStore(hStore, 0);
  end;
end;

// 给PDF添加数字签名
procedure SignInvoicePDF(const InputPDFPath, OutputPDFPath: string);
var
  PDFDoc: TPdfDocument;
  PdfSigner: TPdfSigner;
  DongleCert: PCCERT_CONTEXT;
begin
  PDFDoc := TPdfDocument.Create(nil);
  try
    PDFDoc.LoadFromFile(InputPDFPath);
    
    DongleCert := GetDongleCertificate;
    if Assigned(DongleCert) then
    begin
      PdfSigner := TPdfSigner.Create(PDFDoc);
      try
        // 绑定加密锁证书
        PdfSigner.Certificate := DongleCert;
        // 设置签名在PDF上的位置(左下到右上坐标,单位是PDF点)
        PdfSigner.Rect := TRectF.Create(50, 50, 250, 100);
        // 添加签名的附加信息
        PdfSigner.Reason := '发票合法性验证';
        PdfSigner.Location := 'XX公司财务部';
        PdfSigner.ContactInfo := 'contact@example.com';
        // 签名并保存到输出文件
        PDFDoc.SaveToFile(OutputPDFPath, True);
        ShowMessage('PDF签名完成!');
      finally
        PdfSigner.Free;
        CertFreeCertificateContext(DongleCert);
      end;
    end
    else
      ShowMessage('未找到加密锁证书,请检查驱动!');
  finally
    PDFDoc.Free;
  end;
end;

二、备选方案:iText for Delphi

iText是全球知名的PDF处理库,有开源的Delphi端口(可以在Delphi的组件仓库或开源平台找到)。它同样支持PDF签名,实现逻辑和SynPDF类似:通过CryptoAPI获取加密锁证书,再调用iText的签名接口完成嵌入。

这个方案适合已经熟悉iText生态的开发者,功能比SynPDF更丰富,但集成复杂度稍高一点。

三、关于Adobe Acrobat组件的可行性

你提到的Acrobat COM组件确实能模拟手动签名操作,但有几个硬伤:

  • 必须安装完整版Adobe Acrobat(Reader不行),用户机器部署成本高
  • 商用场景可能涉及Adobe的授权问题
  • COM组件的自动化操作容易受Acrobat版本更新影响,稳定性不如原生Delphi组件

如果是内部小范围使用且已安装Acrobat,可以尝试,但不推荐作为通用解决方案。

关键注意事项

  • 加密锁的驱动一定要安装正确,确保系统能识别到证书(可以在「运行」里输入certmgr.msc查看)
  • 如果你的加密锁用的是PKCS#11接口(而非系统证书存储),可以找开源的Delphi PKCS#11封装库来调用,再结合SynPDF/iText完成签名
  • 测试时先单独验证能获取到加密锁证书,再集成PDF签名逻辑,分步排查问题

内容的提问来源于stack exchange,提问作者Allie

火山引擎 最新活动