OFD 签名与签章
本节介绍 OFD 文档的电子印章(OES)、数字证书签名、自定义签名及验签、脱敏与证书导出。整体链路为:打开文档 → 签署(输出新 OFD 文件)→ 重新打开并遍历签名 → 验证 / 处理。打开文件包请参阅 OFD 文件包。
- 签署输出:
SealDoc、CertificateSignDoc、CustomSignatureDoc的SignWith*方法通常直接写入dest_file(或WriterCallback),而非修改内存后调用OFDPackage::Save。- 验签方式:OFD 模块无 PDF 风格的
Progressive渐进验签;验证为同步调用Verify()、VerifyEx()等接口。
任务场景
- 加载 OES 印章库,对文档单页、多页或骑缝位置加盖电子印章。
- 使用 PFX 等证书进行不可见数字签名(
SignWithNone)或带图片外观的可见签名(SignWithImage)。 - 实现
SignatureCallback,以自定义摘要/签名算法完成签署与验签。 - 遍历文档内签名/签章,验证完整性;可选在线验证(
online = true)。 - 对已签署签名进行脱敏(马赛克、雾化、红章转黑等)或导出公钥证书。
API 概览
| 功能 | C++ API(foxit::ofd) | 核心参数 / 描述 |
|---|---|---|
| 枚举与读取签名 | OFDDoc::GetSignatureCount、GetSignature | 按索引取得 ofdseal::Signature |
| 印章库 | ofdseal::Oes | 传入 OES 库路径;Login(password);GetSealCount / GetSeal |
| 印章实体 | ofdseal::Seal | 印章 ID、名称、GetImage() 等元数据 |
| OES 签署 | ofdseal::SealDoc | 绑定 OFDDoc;SignWithPage / SignWithMultiPage、SignWithStraddle / SignWithMultiPosition |
| 证书签署 | ofdseal::CertificateSignDoc | (doc, cert_file, cert_password);SignWithNone / SignWithImage / SignWithStraddle |
| 自定义签署 | ofdseal::CustomSignatureDoc、ofdseal::SignatureCallback | 委托 Digest / Sign / Verify;SignWithMultiPage / SignWithStraddle |
| 布局 | ofdseal::ImagePosition、ofdseal::StraddlePosition | 页索引、坐标;骑缝方向、比例、起始页、page_count |
| 签署属性 | ofdseal::PublicProperties、ofdseal::SignatureProperties | 锁定类型、保护注释/附件、提供者信息等 |
| 签名对象 | ofdseal::Signature | GetType、GetVerifyMessage、Operate |
| 电子签章 | ofdseal::SealSignature | Verify / VerifyWithOes / VerifyWithoutOes / VerifyEx;ExportPublicCertificateFile |
| 数字签名 | ofdseal::SignSignature | Verify();GetImage();ExportPublicCertificateFile |
| 自定义验签 | ofdseal::CustomVerify::Verify | Signature + SignatureCallback |
| 脱敏处理 | ofdseal::OperateSignatureInfo | e_RemoveInfoOnly、e_ConvertToBlackImage、e_AtomizeImage、e_MosaicImage、e_RemoveAll |
| 验签上下文 | ofdseal::VerifyExtendInfo | application_name、user_login、file_name(UTF-8) |
签名类型(Signature::SignatureType)
| 枚举值 | 含义 |
|---|---|
e_SignatureTypeDefault (0) | 默认 |
e_SignatureTypeSeal (1) | 电子签章 |
e_SignatureTypeSign (2) | 证书数字签名 |
e_SignatureTypeTimeStamp (3) | 时间戳签名 |
遍历文档中的签名
通过 OFDDoc::GetSignatureCount 取得数量,再按索引调用 GetSignature。根据 GetType() 区分签章与证书签名,并使用 SealSignature / SignSignature 强类型接口(与 Signature 共享同一句柄)。
c++
#include "ofd/fs_ofdpackage.h"
#include "ofd/fs_ofddoc.h"
#include "ofd/signature/fs_ofdsignature.h"
using namespace foxit;
using namespace foxit::ofd;
void TraverseSignatures(OFDDoc& doc) {
if (doc.IsEmpty()) {
return;
}
int count = doc.GetSignatureCount();
for (int i = 0; i < count; ++i) {
ofdseal::Signature signature = doc.GetSignature(i);
if (signature.IsEmpty()) {
continue;
}
ofdseal::Signature::SignatureType type = signature.GetType();
WString provider = signature.GetProviderName();
WString digest_method = signature.GetDigestMethod();
(void)provider;
(void)digest_method;
if (type == ofdseal::Signature::e_SignatureTypeSign) {
// 证书数字签名:转为 SignSignature 调用 Verify 等接口
ofdseal::SignSignature sign_sig(signature.Handle());
(void)sign_sig;
} else if (type == ofdseal::Signature::e_SignatureTypeSeal) {
// 电子签章:转为 SealSignature
ofdseal::SealSignature seal_sig(signature.Handle());
(void)seal_sig;
}
}
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.Signature;
public class OFDTraverseSignatureExample {
public static void traverseSignatures(OFDDoc doc) throws Exception {
if (doc.isEmpty()) {
return;
}
int count = doc.getSignatureCount();
for (int i = 0; i < count; i++) {
Signature signature = doc.getSignature(i);
if (signature.isEmpty()) {
continue;
}
// 根据 getType() 区分签章与证书签名,再使用对应子类型接口
int type = signature.getType();
String provider = signature.getProviderName();
String digestMethod = signature.getDigestMethod();
}
}
}
基于 OES 印章库签署
使用 Oes 加载印章库文件;若库受密码保护,须先 Login 成功再 GetSeal。通过 SealDoc 绑定已打开的 OFDDoc,调用 SignWithPage 等在指定位置盖章并输出到新文件。
c++
#include "ofd/fs_ofdpackage.h"
#include "ofd/fs_ofddoc.h"
#include "ofd/signature/fs_ofdoesseal.h"
#include "ofd/signature/fs_ofdsign.h"
using namespace foxit;
using namespace foxit::ofd;
bool SignWithOesSeal(OFDDoc& doc, const char* oes_lib_path,
const char* oes_password, const char* output_path) {
if (doc.IsEmpty()) {
return false;
}
// 加载 OES 印章库(路径替换为实际部署的印章库文件)
ofdseal::Oes oes(oes_lib_path);
if (oes.IsEmpty()) {
return false;
}
// 受保护印章库须先登录
if (!oes.Login(oes_password)) {
return false;
}
if (oes.GetSealCount() <= 0) {
return false;
}
ofdseal::Seal seal = oes.GetSeal(0);
if (seal.IsEmpty()) {
return false;
}
// SealDoc 构造时绑定 OFDDoc,建议局部作用域使用
ofdseal::SealDoc seal_doc(doc);
if (seal_doc.IsEmpty()) {
return false;
}
// 在第 0 页 (50, 50) 处盖章,宽 100、高 50
ofdseal::ImagePosition position(0, 50.0f, 50.0f, true, 100.0f, 50.0f);
ofdseal::PublicProperties properties;
return seal_doc.SignWithPage(seal, position, output_path, properties);
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.ImagePosition;
import com.foxit.sdk.ofd.signature.Oes;
import com.foxit.sdk.ofd.signature.PublicProperties;
import com.foxit.sdk.ofd.signature.Seal;
import com.foxit.sdk.ofd.signature.SealDoc;
public class OFDOesSignExample {
public static boolean signWithOesSeal(OFDDoc doc, String oesLibPath,
String oesPassword, String outputPath) throws Exception {
if (doc.isEmpty()) {
return false;
}
// 加载 OES 印章库(路径替换为实际部署的印章库文件)
Oes oes = new Oes(oesLibPath);
if (oes.isEmpty()) {
return false;
}
// 受保护印章库须先登录
if (!oes.login(oesPassword)) {
return false;
}
if (oes.getSealCount() <= 0) {
return false;
}
Seal seal = oes.getSeal(0);
if (seal.isEmpty()) {
return false;
}
SealDoc sealDoc = new SealDoc(doc);
if (sealDoc.isEmpty()) {
return false;
}
// 在第 0 页 (50, 50) 处盖章
ImagePosition position = new ImagePosition(0, 50.0f, 50.0f, true, 100.0f, 50.0f);
PublicProperties properties = new PublicProperties();
return sealDoc.signWithPage(seal, position, outputPath, properties);
}
}
骑缝章与多页签署
OES 骑缝章使用 SealDoc::SignWithStraddle(seal, straddle_position, dest_file)。证书骑缝章使用 CertificateSignDoc::SignWithStraddle(image_path, straddle_position, …)。StraddlePosition 指定骑缝方向、高度比例、起始页与跨页数量,须保证文档页数足够。
c++
#include "ofd/signature/fs_ofdsign.h"
using namespace foxit;
using namespace foxit::ofd;
bool SignStraddleWithCertificate(OFDDoc& doc, const char* cert_file,
const char* cert_password,
const char* image_path,
const char* output_path) {
if (doc.IsEmpty()) {
return false;
}
ofdseal::CertificateSignDoc signer(doc, cert_file, cert_password);
if (signer.IsEmpty()) {
return false;
}
// 右侧骑缝,3/5 高度,从第 0 页起跨 2 页
ofdseal::StraddlePosition straddle(
ofdseal::StraddlePosition::e_StraddlePositionTypeRight,
ofdseal::StraddlePosition::e_StraddleProportionThreeFifth,
35.0f, 0, 2);
ofdseal::SignatureProperties sig_props("company", "provider", "1.0");
ofdseal::PublicProperties pub_props(
true,
ofdseal::PublicProperties::e_SealSignLockTypSignatureXmlAndOFDXml,
true, false, "sig-dir");
return signer.SignWithStraddle(image_path, straddle, output_path,
sig_props, pub_props);
}
bool SignStraddleWithOes(OFDDoc& doc, ofdseal::Seal& seal,
const char* output_path) {
if (doc.IsEmpty() || seal.IsEmpty()) {
return false;
}
ofdseal::SealDoc seal_doc(doc);
ofdseal::StraddlePosition straddle(
ofdseal::StraddlePosition::e_StraddlePositionTypeRight,
ofdseal::StraddlePosition::e_StraddleProportionThreeFifth,
35.0f, 0, 2);
return seal_doc.SignWithStraddle(seal, straddle, output_path);
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.CertificateSignDoc;
import com.foxit.sdk.ofd.signature.PublicProperties;
import com.foxit.sdk.ofd.signature.Seal;
import com.foxit.sdk.ofd.signature.SealDoc;
import com.foxit.sdk.ofd.signature.SignatureProperties;
import com.foxit.sdk.ofd.signature.StraddlePosition;
public class OFDStraddleSignExample {
public static boolean signStraddleWithCertificate(OFDDoc doc, String certFile,
String certPassword, String imagePath, String outputPath) throws Exception {
if (doc.isEmpty()) {
return false;
}
CertificateSignDoc signer = new CertificateSignDoc(doc, certFile, certPassword);
if (signer.isEmpty()) {
return false;
}
// 右侧骑缝,3/5 高度,从第 0 页起跨 2 页
StraddlePosition straddle = new StraddlePosition(
StraddlePosition.e_StraddlePositionTypeRight,
StraddlePosition.e_StraddleProportionThreeFifth,
35.0f, 0, 2);
SignatureProperties sigProps = new SignatureProperties("company", "provider", "1.0");
PublicProperties pubProps = new PublicProperties();
return signer.signWithStraddle(imagePath, straddle, outputPath, sigProps, pubProps);
}
public static boolean signStraddleWithOes(OFDDoc doc, Seal seal,
String outputPath) throws Exception {
if (doc.isEmpty() || seal.isEmpty()) {
return false;
}
SealDoc sealDoc = new SealDoc(doc);
StraddlePosition straddle = new StraddlePosition(
StraddlePosition.e_StraddlePositionTypeRight,
StraddlePosition.e_StraddleProportionThreeFifth,
35.0f, 0, 2);
return sealDoc.signWithStraddle(seal, straddle, outputPath);
}
}
多页相同位置盖章可使用 SignWithMultiPage(页面索引数组或 "0-10,35,50-" 形式的 page_scope 字符串);多位置盖章使用 SignWithMultiPosition 配合 ImagePositionArray。
基于数字证书签署
CertificateSignDoc 构造时传入 OFDDoc、证书文件路径(支持 String / WString)及证书密码。SignWithNone 为不可见签名;SignWithImage 在指定 ImagePosition 附加图片外观。
c++
#include "ofd/fs_ofdpackage.h"
#include "ofd/fs_ofddoc.h"
#include "ofd/signature/fs_ofdsign.h"
#include "ofd/signature/fs_ofdsignature.h"
using namespace foxit;
using namespace foxit::ofd;
bool SignWithCertificate(OFDDoc& doc, const wchar_t* cert_file,
const char* cert_password,
const char* image_path, const char* output_path,
bool with_image) {
if (doc.IsEmpty()) {
return false;
}
ofdseal::CertificateSignDoc signer(doc, WString(cert_file), cert_password);
if (signer.IsEmpty()) {
return false;
}
ofdseal::SignatureProperties sig_props("sig-company", "sig-provider", "1.0");
ofdseal::PublicProperties pub_props(
true, ofdseal::PublicProperties::e_SealSignLockTypeNone,
false, false, "sig-dir");
if (with_image) {
// 可见签名:指定页、坐标与图片尺寸
ofdseal::ImagePosition position(0, 50.0f, 50.0f, true, 100.0f, 50.0f);
return signer.SignWithImage(image_path, position, output_path,
sig_props, pub_props);
}
// 不可见数字签名
return signer.SignWithNone(output_path, sig_props, pub_props);
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.CertificateSignDoc;
import com.foxit.sdk.ofd.signature.ImagePosition;
import com.foxit.sdk.ofd.signature.PublicProperties;
import com.foxit.sdk.ofd.signature.SignatureProperties;
public class OFDCertificateSignExample {
public static boolean signWithCertificate(OFDDoc doc, String certFile,
String certPassword, String imagePath, String outputPath,
boolean withImage) throws Exception {
if (doc.isEmpty()) {
return false;
}
CertificateSignDoc signer = new CertificateSignDoc(doc, certFile, certPassword);
if (signer.isEmpty()) {
return false;
}
SignatureProperties sigProps = new SignatureProperties(
"sig-company", "sig-provider", "1.0");
PublicProperties pubProps = new PublicProperties();
if (withImage) {
// 可见签名:指定页、坐标与图片尺寸
ImagePosition position = new ImagePosition(
0, 50.0f, 50.0f, true, 100.0f, 50.0f);
return signer.signWithImage(imagePath, position, outputPath,
sigProps, pubProps);
}
// 不可见数字签名
return signer.signWithNone(outputPath, sigProps, pubProps);
}
}
自定义签名与验签
实现 SignatureCallback(Digest、Sign、Verify、GetSignMethod 等),通过 CustomSignatureDoc 完成签署;验签使用 CustomVerify::Verify。
c++
#include "ofd/signature/fs_ofdcustomsignature.h"
using namespace foxit;
using namespace foxit::ofd;
class MySignatureCallback : public ofdseal::SignatureCallback {
public:
String GetProviderName() override { return "my-provider"; }
String GetCompany() override { return "my-company"; }
String GetVersion() override { return "1.0"; }
String GetSignatureTime() override { return "2026-06-01T10:00:00"; }
String Digest(const void* data, int length) override {
// 实现摘要算法
return "";
}
String GetDigestMethod() override { return "SHA256"; }
String Sign(const void* data, int length) override {
// 实现签名
return "";
}
String GetSignMethod() override { return "RSA"; }
String GetSeal() override { return ""; }
bool Verify(const void* data, int length, const void* sign_value,
int sign_value_length) override {
// 实现验签
return false;
}
};
bool CustomSignDocument(OFDDoc& doc, MySignatureCallback* callback,
const char* output_path) {
if (doc.IsEmpty() || callback == nullptr) {
return false;
}
// 回调须在签署全流程内保持有效
ofdseal::CustomSignatureDoc custom_doc(doc, callback);
if (custom_doc.IsEmpty()) {
return false;
}
ofdseal::ImagePosition position(0, 50.0f, 50.0f, true, 80.0f, 40.0f);
ofdseal::PublicProperties properties;
// page_scope "0-" 表示全部页面
return custom_doc.SignWithMultiPage("0-", position, output_path, properties);
}
bool CustomVerifySignature(ofdseal::Signature& signature,
MySignatureCallback* callback) {
if (signature.IsEmpty() || callback == nullptr) {
return false;
}
return ofdseal::CustomVerify::Verify(signature, callback);
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.CustomSignatureDoc;
import com.foxit.sdk.ofd.signature.CustomVerify;
import com.foxit.sdk.ofd.signature.ImagePosition;
import com.foxit.sdk.ofd.signature.PublicProperties;
import com.foxit.sdk.ofd.signature.Signature;
import com.foxit.sdk.ofd.signature.SignatureCallback;
public class OFDCustomSignExample {
public static boolean customSignDocument(OFDDoc doc,
SignatureCallback callback, String outputPath) throws Exception {
if (doc.isEmpty() || callback == null) {
return false;
}
// 回调须在签署全流程内保持有效
CustomSignatureDoc customDoc = new CustomSignatureDoc(doc, callback);
if (customDoc.isEmpty()) {
return false;
}
ImagePosition position = new ImagePosition(0, 50.0f, 50.0f, true, 80.0f, 40.0f);
PublicProperties properties = new PublicProperties();
// pageScope "0-" 表示全部页面
return customDoc.signWithMultiPage("0-", position, outputPath, properties);
}
public static boolean customVerifySignature(Signature signature,
SignatureCallback callback) throws Exception {
if (signature.isEmpty() || callback == null) {
return false;
}
return CustomVerify.verify(signature, callback);
}
}
验证签名
SignSignature::Verify() 用于证书签名;SealSignature 提供 Verify(online)、VerifyWithOes、VerifyWithoutOes、VerifyEx(extend_info, online)。验证后可通过 GetVerifyMessage() 读取详细信息。
c++
#include "ofd/signature/fs_ofdsignature.h"
using namespace foxit;
using namespace foxit::ofd;
bool VerifyDocumentSignatures(OFDDoc& doc) {
if (doc.IsEmpty()) {
return false;
}
bool all_ok = true;
for (int i = 0; i < doc.GetSignatureCount(); ++i) {
ofdseal::Signature signature = doc.GetSignature(i);
if (signature.IsEmpty()) {
continue;
}
ofdseal::Signature::SignatureType type = signature.GetType();
bool verified = false;
if (type == ofdseal::Signature::e_SignatureTypeSign) {
ofdseal::SignSignature sign_sig(signature.Handle());
// 证书签名离线验证
verified = sign_sig.Verify();
} else if (type == ofdseal::Signature::e_SignatureTypeSeal) {
ofdseal::SealSignature seal_sig(signature.Handle());
// 电子签章:online=false 为离线验证
verified = seal_sig.Verify(false);
// 可选:传入业务上下文参与验章
ofdseal::VerifyExtendInfo extend_info("MyApp", "user01", "document.ofd");
verified = seal_sig.VerifyEx(extend_info, false);
}
WString message = signature.GetVerifyMessage();
(void)message;
if (!verified) {
all_ok = false;
}
}
return all_ok;
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.SealSignature;
import com.foxit.sdk.ofd.signature.SignSignature;
import com.foxit.sdk.ofd.signature.Signature;
import com.foxit.sdk.ofd.signature.VerifyExtendInfo;
public class OFDVerifySignatureExample {
public static boolean verifyDocumentSignatures(OFDDoc doc) throws Exception {
if (doc.isEmpty()) {
return false;
}
boolean allOk = true;
for (int i = 0; i < doc.getSignatureCount(); i++) {
Signature signature = doc.getSignature(i);
if (signature.isEmpty()) {
continue;
}
int type = signature.getType();
boolean verified = false;
if (signature instanceof SignSignature) {
// 证书签名验证
verified = ((SignSignature) signature).verify();
} else if (signature instanceof SealSignature) {
SealSignature sealSig = (SealSignature) signature;
// 电子签章:online=false 为离线验证
verified = sealSig.verify(false);
// 可选:传入业务上下文参与验章
VerifyExtendInfo extendInfo = new VerifyExtendInfo(
"MyApp", "user01", "document.ofd");
verified = sealSig.verifyEx(extendInfo, false);
}
String message = signature.getVerifyMessage();
if (!verified) {
allOk = false;
}
}
return allOk;
}
}
签名脱敏与处理
对已签署签名调用 Signature::Operate,传入 OperateSignatureInfo 指定脱敏模式。部分模式会删除签名信息;操作后须 OFDPackage::SaveAs 写回(若在原包上修改)。
c++
#include "ofd/signature/fs_ofdsignature.h"
using namespace foxit;
using namespace foxit::ofd;
bool DesensitizeSignature(OFDDoc& doc, int signature_index) {
if (doc.IsEmpty() || signature_index < 0 ||
signature_index >= doc.GetSignatureCount()) {
return false;
}
ofdseal::Signature signature = doc.GetSignature(signature_index);
if (signature.IsEmpty()) {
return false;
}
// 马赛克脱敏:mosaic_vector_length 控制马赛克粒度
ofdseal::OperateSignatureInfo info(
ofdseal::OperateSignatureInfo::e_MosaicImage, 5, 5, 9);
return signature.Operate(info);
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.OperateSignatureInfo;
import com.foxit.sdk.ofd.signature.Signature;
public class OFDOperateSignatureExample {
public static boolean desensitizeSignature(OFDDoc doc,
int signatureIndex) throws Exception {
if (doc.isEmpty() || signatureIndex < 0
|| signatureIndex >= doc.getSignatureCount()) {
return false;
}
Signature signature = doc.getSignature(signatureIndex);
if (signature.isEmpty()) {
return false;
}
// 马赛克脱敏
OperateSignatureInfo info = new OperateSignatureInfo(
OperateSignatureInfo.e_MosaicImage, 5, 5, 9);
return signature.operate(info);
}
}
OperateSignatureInfo 操作类型
| 枚举值 | 含义 |
|---|---|
e_RemoveInfoOnly | 仅删除签名/签章信息,保留图片 |
e_ConvertToBlackImage | 删除信息并将彩色图转灰度(红章转黑) |
e_AtomizeImage | 删除信息并雾化图片 |
e_MosaicImage | 删除信息并马赛克图片 |
e_RemoveAll | 完全删除签名/签章及图片 |
导出公钥证书
SignSignature 与 SealSignature 均支持 ExportPublicCertificateFile,将签名中的公钥证书导出为文件。
c++
#include "ofd/signature/fs_ofdsignature.h"
using namespace foxit;
using namespace foxit::ofd;
bool ExportSignatureCertificate(OFDDoc& doc, int index,
const char* cert_output_path) {
if (doc.IsEmpty() || index < 0 || index >= doc.GetSignatureCount()) {
return false;
}
ofdseal::Signature signature = doc.GetSignature(index);
if (signature.GetType() == ofdseal::Signature::e_SignatureTypeSign) {
ofdseal::SignSignature sign_sig(signature.Handle());
return sign_sig.ExportPublicCertificateFile(cert_output_path);
}
if (signature.GetType() == ofdseal::Signature::e_SignatureTypeSeal) {
ofdseal::SealSignature seal_sig(signature.Handle());
return seal_sig.ExportPublicCertificateFile(cert_output_path);
}
return false;
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.signature.SealSignature;
import com.foxit.sdk.ofd.signature.SignSignature;
import com.foxit.sdk.ofd.signature.Signature;
public class OFDExportCertExample {
public static boolean exportSignatureCertificate(OFDDoc doc, int index,
String certOutputPath) throws Exception {
if (doc.isEmpty() || index < 0 || index >= doc.getSignatureCount()) {
return false;
}
Signature signature = doc.getSignature(index);
if (signature instanceof SignSignature) {
return ((SignSignature) signature).exportPublicCertificateFile(certOutputPath);
}
if (signature instanceof SealSignature) {
return ((SealSignature) signature).exportPublicCertificateFile(certOutputPath);
}
return false;
}
}
注意事项
- 文档入口:读取签名统一通过
OFDDoc::GetSignatureCount/GetSignature;无 PDF 模块的Progressive渐进验签。 - 签署与保存:
SignWith*直接输出到目标路径;在原文件上继续编辑时,重新打开输出文件或调用OFDPackage::SaveAs。 - OES 登录:受保护印章库须
Oes::Login成功后再GetSeal;失败时可读GetLastErrorMessage()。 - 骑缝章页数:
StraddlePosition::page_count与start_page_index之和不得超过文档页数。 - 对象生命周期:
SealDoc/CertificateSignDoc/CustomSignatureDoc构造时绑定OFDDoc;SignatureCallback*须在签署/验签期间保持有效。 - 验证含义:
Verify()返回 true 表示完整性/数学验证通过;证书吊销、过期等须结合online参数与GetVerifyMessage()解读。 - 许可证与模块:OES、证书签名、国密算法依赖相应产品模块与许可证;文档加密或禁止签章权限可能影响签署,请参阅 安全与权限。
- 文档级权限:文档级
OFDPermission见 安全与权限。