Enterprise 版本
NextPDF Enterprise 快速入门
本教程带你从一个空项目走到两个可用的 Enterprise 结果。首先你验证一个已有的已签名 PDF 并读取它的 MainIndication。然后你用长期生成器把一个已签名文档提升到 PAdES B-LT。每一步都会展示你应当预期的确切输出或异常。NextPDF 记录的是能力,而非认证:它不持有任何 PAdES 或 eIDAS 认证,也不授予任何认证。
该能力随 NextPDF Enterprise(nextpdf/enterprise)一同发布,并通过 Enterprise 级别的许可证信封激活。没有该授权的部署不会加载此能力的类。比较各版本并获取许可证。
前置条件
标题为“前置条件”的章节- Composer 已配置好私有 NextPDF 仓库。请先按照 安装与认证 操作。
- 你已拥有从 app.getnextpdf.com 账户下载的 Enterprise 许可证信封。许可与激活 说明了该信封是什么以及它放在哪里。
- 第 3 步需要一个用于验证的已签名 PDF。B-LT 部分还需要你的签名者证书以及访问 OCSP/CRL 响应器的网络权限。
1. 安装并激活
标题为“1. 安装并激活”的章节引入 Enterprise 包。它依赖 nextpdf/core 和 nextpdf/pro,因此 Composer 会带上整个技术栈:
composer require nextpdf/enterprisecomposer show nextpdf/enterprise如果 composer show 打印出该包及其版本,说明安装成功。现在按照 许可与激活 的描述,把已签名的许可证信封放到你的部署会加载它的位置。仅安装该包并不授予 Enterprise 能力;激活的许可证才会选定版本。
2. 验证你的授权
标题为“2. 验证你的授权”的章节向授权评估器询问你的许可证授予了什么。你的引导流程会在激活期间获得经过验证的 NextPDF\Enterprise\Licensing\LicenseKey;把它传入:
<?phprequire __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Licensing\EntitlementEvaluator;use NextPDF\Enterprise\Licensing\LicenseKey;
/** @var LicenseKey|null $license The verified license from activation. */$result = (new EntitlementEvaluator())->evaluate($license);
echo 'status: ' . $result->status->value . PHP_EOL;echo 'edition: ' . ($result->edition?->value ?? 'none') . PHP_EOL;echo 'runtime: ' . ($result->runtimeAllowed ? 'allowed' : 'disabled') . PHP_EOL;在拥有有效 Enterprise 许可证时,你会看到:
status: activeedition: enterpriseruntime: allowed该步骤背后的方法:
public function evaluate(?LicenseKey $license, ?DateTimeImmutable $now = null): EntitlementResult抛出或失败方式:它从不抛出异常。缺失许可证会返回一个失败即关闭的 EntitlementResult,其 EntitlementStatus::NoLicense,且 runtimeAllowed 为 false(见第 4 步)。
3. 首个结果
标题为“3. 首个结果”的章节验证一个已有的已签名 PDF
标题为“验证一个已有的已签名 PDF”的章节从已签名的 PDF 中提取签名,然后运行基础 AdES 验证。该引擎实现了 ETSI EN 319 102-1 的各个验证级别;validateBasic() 是第 5.2 条的流程——结构、摘要、签名密码学以及证书链:
<?phprequire __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;use NextPDF\Enterprise\Security\Validation\CmsSignatureDataExtractor;use NextPDF\Enterprise\Signature\SignatureExtractor;
$pdf = file_get_contents(__DIR__ . '/contract-signed.pdf');if ($pdf === false) { throw new RuntimeException('Could not read contract-signed.pdf');}
$signatures = (new SignatureExtractor())->extract($pdf);if ($signatures === []) { throw new RuntimeException('The PDF carries no signature dictionary.');}
$engine = new AdESValidationEngine(extractor: new CmsSignatureDataExtractor());$report = $engine->validateBasic( $signatures[0]['signedBytes'], // the exact /ByteRange-covered bytes $signatures[0]['contents'], // the DER CMS SignedData from /Contents);
echo $report->mainIndication->name . PHP_EOL;echo ($report->subIndication?->name ?? '(none)') . PHP_EOL;对于一个格式良好、通过了本示例中配置的基础结构、摘要、密码学与链检查的签名,你会看到:
TOTAL_PASSED(none)MainIndication 恰好有三种情形:TOTAL_PASSED、TOTAL_FAILED 和 INDETERMINATE。该引擎是失败即关闭的:一项它无法肯定确立的检查会得到 INDETERMINATE,绝不会静默通过。这里的通过是本引擎各项检查下的验证结果,而非信任或认证声明——信任锚与长期证据属于 验证页面 上更深入的级别。
public function extract(string $pdfData): array抛出或失败方式:如果输入不是有效的 PDF,则抛出 InvalidArgumentException。格式错误的 /ByteRange 或 /Contents 会产生空字符串(失败即关闭),绝不会得到肯定的结果。
public function validateBasic(string $signedData, string $signature): ValidationReport抛出或失败方式:在验证失败时它从不抛出异常。每一个缺陷都映射为一个 ValidationReport 指示,例如 HASH_FAILURE 或 SIG_CRYPTO_FAILURE。
生成一个 PAdES B-LT
标题为“生成一个 PAdES B-LT”的章节现在把一个刚签名的文档升级到 B-LT。长期生成器会收集证书链外加 OCSP/CRL 证据,并写入文档安全存储(DSS)。它延续了 签名页面 所描述的签名流程,该流程为你提供输出缓冲区、对象注册表以及签名的 /Contents 十六进制:
use NextPDF\Enterprise\Security\Ltv\LtvManager;use NextPDF\Security\Signature\CertificateInfo;use NextPDF\Security\Signature\SignatureLevel;
$certInfo = CertificateInfo::fromPkcs12('/secure/signer.p12', $p12Password);
// $httpClient is any PSR-18 client; it fetches OCSP responses and CRLs.$ltv = new LtvManager($certInfo, $httpClient, level: SignatureLevel::PAdES_B_LT);
// $buffer, $registry, and $signatureContentsHex come from the signing pass.$dssObjectNumber = $ltv->enableLtv($buffer, $registry, $signatureContentsHex);返回值是用于文档目录 /DSS 条目的 DSS 对象编号。该生成器默认采用 strict 吊销强制执行:缺失吊销材料会抛出异常,而不是静默地生成一个空洞的 “B-LT” 文件。
public function enableLtv(BinaryBuffer $buffer, ObjectRegistry $registry, string $signatureContentsHex): int抛出或失败方式:当链验证失败、证书被吊销,或在 strict 默认下缺失吊销材料时,抛出 NextPDF\Enterprise\Security\Ltv\LtvException。
4. 当出现失败时
标题为“4. 当出现失败时”的章节status: no_license——信封未加载
标题为“status: no_license——信封未加载”的章节第 2 步打印 status: no_license 和 runtime: disabled,且结果会携带警告 No license configured. Enterprise runtime is disabled. Install a license or purchase one at https://nextpdf.dev/pricing。随后,一次受授权限制的调用会抛出 NextPDF\Accelerator\Exception\SpectrumAuthenticationException,其代码为 SPEC-LIC-001,例如 Capability '...' requires a valid license.。解决方法:按照 许可与激活 放置并激活信封,然后重新运行第 2 步。
InvalidArgumentException: Input does not start with %PDF header
标题为“InvalidArgumentException: Input does not start with %PDF header”的章节SignatureExtractor::extract() 收到了某个并非 PDF 的东西——错误的路径、空读取,或一个压缩过的下载文件。请检查你加载的文件。空的 $signatures 列表则是另一回事:文件是 PDF,但它不携带 /Type /Sig 字典,所以没有可验证的内容。
LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0
标题为“LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0”的章节enableLtv() 无法为某个链证书获得 OCSP 响应或 CRL,而 strict 默认拒绝在没有证据的情况下写出 B-LT 声明。请检查主机对响应器的可达性,或仅在你明确接受仅告警运行时才传入 enforcementMode: RevocationEnforcementMode::PERMISSIVE——除非缺失的吊销证据被明确接受并记录在案,否则绝不要在生产或合规工作流中把这类输出标记为 B-LT。相关:在没有 TSA 客户端的情况下请求 B-LTA 会失败并抛出 LtvException: TSA client required for document timestamps。
下一步去哪里
标题为“下一步去哪里”的章节- 签名:PAdES B-LT / B-LTA、DSS、文档时间戳 —— 完整的生成器行为、排序规则以及归档循环。
- 签名验证 —— 基于时间的与长期的验证、信任锚、归档链。
- 许可 —— NextPDF Enterprise —— 授权状态、宽限期、能力门控。
- NextPDF Enterprise 模块索引 —— 该版本随附的其余一切。