zid/zatca 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

zid/zatca

Composer 安装命令:

composer require zid/zatca

包简介

ZATCA E-Invoicing integration tools

关键字:

README 文档

README

🧾 ZATCA E-Invoicing Phase 2

PHP Package for Saudi Arabia's ZATCA (Fatoora) Integration

Simplifies Phase 2 e-invoicing requirements including certificate generation, invoice signing, QR code generation, and submission to ZATCA's API

View ExamplesReport a Bug

Features

  • Certificate Management: Generate CSR (Certificate Signing Request) and obtain compliance/production certificates
  • Invoice Processing: Hash and sign XML invoices according to ZATCA specifications
  • QR Code Generation: Create compliant QR codes for both simplified and standard invoices
  • Compliance Validation: Check invoice compliance before production submission
  • Invoice Submission: Submit invoices to ZATCA via Reporting (simplified) or Clearance (standard) APIs
  • Multi-Environment Support: Sandbox, Simulation, and Production environments
  • Clean Architecture: Well-structured, maintainable, and testable code

Requirements

  • PHP 8.1 or higher
  • Required PHP extensions:
    • ext-openssl
    • ext-dom
    • ext-xsl
    • ext-json
    • ext-bcmath
    • ext-simplexml

Installation

Install the package via Composer:

composer require zid/zatca

Quick Start

1. Generate Certificate Signing Request (CSR)

First, generate a CSR and private key for your organization:

<?php
require_once 'vendor/autoload.php';

use Zid\Zatca\CertificateSigningRequestBuilder;

$csrBuilder = new CertificateSigningRequestBuilder();

$csrBuilder
    ->setCommonName('TST-886431145-311111111101113')
    ->setSerialNumber('TST', 'TST', 'ed22f1d8-e6a2-1118-9b58-d9a8f11e445f')
    ->setOrganizationIdentifier('311111111101113')
    ->setOrganizationalUnitName('Riyadh Branch')
    ->setOrganizationName('ABCD Limited')
    ->setCountry('SA')
    ->setInvoiceType('1100')
    ->setAddress('RRRD2929')
    ->setBusinessCategory('Technology')
    ->generate();

// Save CSR and private key
$csrBuilder->saveCsr('certificate.csr');
$csrBuilder->savePrivateKey('private.pem');

2. Request Compliance Certificate

Obtain a compliance certificate from ZATCA using your CSR and OTP:

<?php
use Zid\Zatca\ComplianceService;
use Zid\Zatca\Enums\ZatcaEnvironment;

$complianceService = new ComplianceService(ZatcaEnvironment::SANDBOX);

$csr = file_get_contents('certificate.csr');
$ccsid = $complianceService->requestComplianceCertificate(
    b64Csr: base64_encode($csr),
    otp: '123456'
);

// Save compliance certificate
$ccsid->saveAsJson('ccsid.json');

echo "Certificate: " . $ccsid->certificate . PHP_EOL;
echo "Secret: " . $ccsid->secret . PHP_EOL;

3. Hash Invoice XML

Hash your unsigned invoice XML:

<?php
use Zid\Zatca\InvoiceHashingService;

$xmlContent = file_get_contents('unsigned_invoice.xml');

$hashingService = new InvoiceHashingService();
$result = $hashingService->hash($xmlContent);

echo "Invoice Hash: " . $result->invoiceHash . PHP_EOL;
echo "UUID: " . $result->uuid . PHP_EOL;

// Save for later use
file_put_contents('invoice.json', json_encode($result, JSON_PRETTY_PRINT));

4. Sign Invoice

Sign the invoice with your private key and compliance certificate:

<?php
use Zid\Zatca\InvoiceSigningService;
use Zid\Zatca\GetDigitalSignatureService;
use Zid\Zatca\GetPublicKeyAndSignatureService;
use Zid\Zatca\QrCodeGeneratorService;
use Zid\Zatca\Entities\CSID;

$invoiceData = json_decode(file_get_contents('invoice.json'), true);
$canonicalXml = base64_decode($invoiceData['base64CanonicalXml']);
$invoiceHash = $invoiceData['invoiceHash'];

$ccsid = CSID::loadFromJson('ccsid.json');
$privateKey = file_get_contents('private.pem');
$privateKey = str_replace(["\n", "\t", "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----"], '', $privateKey);

$digitalSignatureService = new GetDigitalSignatureService();
$publicKeyService = new GetPublicKeyAndSignatureService();
$qrCodeService = new QrCodeGeneratorService($publicKeyService);

$signingService = new InvoiceSigningService($digitalSignatureService, $qrCodeService);

$result = $signingService->sign(
    csid: $ccsid,
    privateKeyContent: $privateKey,
    canonicalXml: $canonicalXml,
    invoiceHash: $invoiceHash
);

echo "Signed Invoice (Base64): " . $result->b64SignedInvoice . PHP_EOL;
echo "QR Code (Base64): " . $result->b64QrCode . PHP_EOL;

5. Check Compliance

Validate your signed invoice against ZATCA's compliance checks:

<?php
use Zid\Zatca\ComplianceService;
use Zid\Zatca\Enums\ZatcaEnvironment;
use Zid\Zatca\Entities\CSID;

$complianceService = new ComplianceService(ZatcaEnvironment::SANDBOX);
$ccsid = CSID::loadFromJson('ccsid.json');

$result = $complianceService->checkCompliance(
    binarySecurityToken: $ccsid->certificate,
    secret: $ccsid->secret,
    invoiceHash: 'YOUR_INVOICE_HASH',
    invoiceUuid: 'YOUR_INVOICE_UUID',
    signedInvoice: 'BASE64_SIGNED_INVOICE'
);

echo "Validation Status: " . $result->validationResults->status . PHP_EOL;
echo "Clearance Status: " . $result->clearanceStatus . PHP_EOL;

if (!empty($result->validationResults->errorMessages)) {
    echo "Errors:" . PHP_EOL;
    print_r($result->validationResults->errorMessages);
}

6. Generate Production Certificate

After successful compliance validation, request a production certificate:

<?php
use Zid\Zatca\ProductionCsidGeneratorService;
use Zid\Zatca\Enums\ZatcaEnvironment;
use Zid\Zatca\Entities\CSID;

$productionService = new ProductionCsidGeneratorService(ZatcaEnvironment::SANDBOX);
$ccsid = CSID::loadFromJson('ccsid.json');

$pcsid = $productionService->requestProductionCertificate(
    binarySecurityToken: $ccsid->certificate,
    secret: $ccsid->secret,
    ccsidRequestId: $ccsid->requestId
);

// Save production certificate
$pcsid->saveAsJson('pcsid.json');

7. Submit Invoice to ZATCA

Submit your signed invoice to ZATCA (Reporting for simplified, Clearance for standard):

<?php
use Zid\Zatca\InvoiceSubmissionService;
use Zid\Zatca\Enums\ZatcaEnvironment;
use Zid\Zatca\Entities\CSID;

$submissionService = new InvoiceSubmissionService(ZatcaEnvironment::PRODUCTION);
$pcsid = CSID::loadFromJson('pcsid.json');

$response = $submissionService->submit(
    csid: $pcsid,
    isSimplified: true, // false for standard invoices
    invoiceHash: 'YOUR_INVOICE_HASH',
    invoiceUuid: 'YOUR_INVOICE_UUID',
    invoiceXml: 'YOUR_SIGNED_INVOICE_XML'
);

if ($response->isSubmitted) {
    echo "Invoice submitted successfully!" . PHP_EOL;
    echo "Status: " . $response->status . PHP_EOL;
} else {
    echo "Submission failed!" . PHP_EOL;
    print_r($response->validationResults->errorMessages);
}

Environment Configuration

The package supports three ZATCA environments:

use Zid\Zatca\Enums\ZatcaEnvironment;

// Sandbox - For development and testing
ZatcaEnvironment::SANDBOX

// Simulation - For pre-production testing
ZatcaEnvironment::SIMULATION

// Production - For live invoices
ZatcaEnvironment::PRODUCTION

Using the Facade (Alternative Approach)

The Zatca facade provides a cleaner, more convenient API for accessing all services. Instead of manually instantiating services and their dependencies, you can use the facade as a single entry point.

Benefits of Using the Facade

  • Simplified API: Single entry point for all ZATCA operations
  • Lazy Loading: Services are only instantiated when needed
  • Dependency Management: Automatically handles service dependencies
  • Cleaner Code: Less boilerplate, more readable

Facade Example: Complete Workflow

<?php
require_once 'vendor/autoload.php';

use Zid\Zatca\Zatca;
use Zid\Zatca\Enums\ZatcaEnvironment;

// Initialize the facade
$zatca = new Zatca(ZatcaEnvironment::SANDBOX);

// 1. Generate CSR
$csrBuilder = $zatca->csrBuilder()
    ->setCommonName('TST-886431145-311111111101113')
    ->setSerialNumber('TST', 'TST', 'ed22f1d8-e6a2-1118-9b58-d9a8f11e445f')
    ->setOrganizationIdentifier('311111111101113')
    ->setOrganizationalUnitName('Riyadh Branch')
    ->setOrganizationName('ABCD Limited')
    ->setCountry('SA')
    ->setInvoiceType('1100')
    ->setAddress('RRRD2929')
    ->setBusinessCategory('Technology')
    ->generate();

$csrBuilder->saveCsr('certificate.csr');
$csrBuilder->savePrivateKey('private.pem');

// 2. Request compliance certificate
$csr = file_get_contents('certificate.csr');
$ccsid = $zatca->compliance()->requestComplianceCertificate(
    b64Csr: base64_encode($csr),
    otp: '123456'
);
$ccsid->saveAsJson('ccsid.json');

// 3. Hash invoice
$invoiceXml = file_get_contents('unsigned_invoice.xml');
$hashingResult = $zatca->hashing()->hash($invoiceXml);

// 4. Sign invoice
$privateKey = file_get_contents('private.pem');
$privateKey = str_replace(["\n", "\t", "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----"], '', $privateKey);

$signingResult = $zatca->signing()->sign(
    csid: $ccsid,
    privateKeyContent: $privateKey,
    canonicalXml: base64_decode($hashingResult->b64CanonicalXml),
    invoiceHash: $hashingResult->invoiceHash
);

// 5. Check compliance
$validationResponse = $zatca->compliance()->checkCompliance(
    binarySecurityToken: $ccsid->certificate,
    secret: $ccsid->secret,
    invoiceHash: $hashingResult->invoiceHash,
    invoiceUuid: $hashingResult->uuid,
    signedInvoice: $signingResult->b64SignedInvoice
);

if ($validationResponse->validationResults->status === 'PASS') {
    // 6. Request production certificate
    $pcsid = $zatca->production()->requestProductionCertificate(
        binarySecurityToken: $ccsid->certificate,
        secret: $ccsid->secret,
        ccsidRequestId: $ccsid->requestId
    );
    $pcsid->saveAsJson('pcsid.json');
    
    // 7. Submit invoice to production
    $submissionResult = $zatca->submission()->submit(
        csid: $pcsid,
        isSimplified: true,
        invoiceHash: $hashingResult->invoiceHash,
        invoiceUuid: $hashingResult->uuid,
        invoiceXml: base64_decode($signingResult->b64SignedInvoice)
    );
    
    if ($submissionResult->isSubmitted) {
        echo "Invoice submitted successfully!" . PHP_EOL;
    }
}

Facade API Methods

The Zatca facade provides the following methods:

// Access services
$zatca->compliance()    // ComplianceService
$zatca->production()    // ProductionCsidGeneratorService
$zatca->submission()    // InvoiceSubmissionService
$zatca->hashing()       // InvoiceHashingService
$zatca->signing()       // InvoiceSigningService
$zatca->qrCode()        // QrCodeGeneratorService
$zatca->csrBuilder()    // CertificateSigningRequestBuilder
$zatca->client()        // ZatcaClient (for direct API access)

Comparison: Traditional vs Facade

Traditional Approach:

// Manual dependency injection
$digitalSignatureService = new GetDigitalSignatureService();
$publicKeyService = new GetPublicKeyAndSignatureService();
$qrCodeService = new QrCodeGeneratorService($publicKeyService);
$signingService = new InvoiceSigningService($digitalSignatureService, $qrCodeService);

$result = $signingService->sign(...);

Facade Approach:

// Clean and simple
$zatca = new Zatca(ZatcaEnvironment::SANDBOX);
$result = $zatca->signing()->sign(...);

The facade handles all dependency injection automatically, making your code cleaner and easier to maintain.

Invoice Types

When generating CSR, specify the invoice type using a 4-digit code:

  • 1100 - Standard & Simplified Invoices
  • 0100 - Simplified Invoice Only (B2C)
  • 1000 - Standard Invoice Only (B2B) Each digit acts as a boolean flag: [Standard, Simplified, Future Use, Future Use]

API Reference

Core Services

CertificateSigningRequestBuilder

Generates CSR and private key for ZATCA onboarding.

Methods:

  • setCommonName(string $name) - Set common name
  • setSerialNumber(string $solutionProvider, string $solutionName, string $serialNumber) - Set device serial number
  • setOrganizationIdentifier(string $id) - Set organization tax ID
  • setOrganizationalUnitName(string $name) - Set organizational unit
  • setOrganizationName(string $name) - Set organization name
  • setCountry(string $country) - Set country code (SA)
  • setInvoiceType(string $type) - Set invoice type (e.g., '1100')
  • setAddress(string $address) - Set business address
  • setBusinessCategory(string $category) - Set business category
  • generate() - Generate CSR and private key
  • getCsr() - Get generated CSR
  • getPrivateKey() - Get generated private key
  • saveCsr(string $path) - Save CSR to file
  • savePrivateKey(string $path) - Save private key to file

ComplianceService

Handles compliance certificate requests and validation.

Methods:

  • requestComplianceCertificate(string $b64Csr, string $otp): CSID
  • checkCompliance(string $binarySecurityToken, string $secret, string $invoiceHash, string $invoiceUuid, string $signedInvoice): ValidationResponse

InvoiceHashingService

Hashes invoice XML according to ZATCA specifications.

Methods:

  • hash(string $unsignedInvoiceXml): InvoiceHashingResult

InvoiceSigningService

Signs invoices with digital signature and generates QR codes.

Methods:

  • sign(CSID $csid, string $privateKeyContent, string $canonicalXml, string $invoiceHash): InvoiceSigningResult

QrCodeGeneratorService

Generates ZATCA-compliant QR codes.

Methods:

  • generate(CSID $csid, string $invoiceHash, string $canonicalXml, string $signatureValue): string

ProductionCsidGeneratorService

Requests production certificates after compliance validation.

Methods:

  • requestProductionCertificate(string $binarySecurityToken, string $secret, string $ccsidRequestId): CSID

InvoiceSubmissionService

Submits invoices to ZATCA via Reporting or Clearance APIs.

Methods:

  • submit(CSID $csid, bool $isSimplified, string $invoiceHash, string $invoiceUuid, string $invoiceXml): SubmissionResponse

Entities

CSID

Represents a Certificate Signing ID (compliance or production certificate).

Properties:

  • string $certificate - Base64 encoded certificate
  • string $secret - Certificate secret
  • string $requestId - Request ID from ZATCA

Methods:

  • static loadFromJson(string $filepath): self
  • saveAsJson(string $filepath): void

InvoiceHashingResult

Result of invoice hashing operation.

Properties:

  • string $invoiceHash - Base64 encoded SHA-256 hash
  • string $uuid - Invoice UUID
  • string $b64Invoice - Base64 encoded invoice
  • string $b64CanonicalXml - Base64 encoded canonical XML

InvoiceSigningResult

Result of invoice signing operation.

Properties:

  • string $signature - Digital signature
  • string $b64SignedInvoice - Base64 encoded signed invoice
  • string $b64QrCode - Base64 encoded QR code

SubmissionResponse

Response from invoice submission to ZATCA.

Properties:

  • ValidationResults $validationResults - Validation messages
  • string $status - Submission status (REPORTED/CLEARED)
  • bool $isSubmitted - Whether submission was successful

ValidationResponse

Response from compliance validation.

Properties:

  • ValidationResults $validationResults - Validation messages
  • string|null $reportingStatus - Reporting status
  • string|null $clearanceStatus - Clearance status
  • string|null $qrSellerStatus - QR seller status
  • string|null $qrBuyerStatus - QR buyer status

ValidationResults

Validation messages from ZATCA.

Properties:

  • array $infoMessages - Informational messages
  • array $warningMessages - Warning messages
  • array $errorMessages - Error messages
  • string $status - Overall validation status

Examples

Complete working examples are available in the examples/ directory:

  1. 0_using_facade.php - Using the Zatca Facade (Recommended)
  2. 1_generate_csr.php - Generate CSR and private key
  3. 2_generate_compliance_csid.php - Request compliance certificate
  4. 3_hash_invoice_xml.php - Hash invoice XML
  5. 4_generate_qr_code_xml.php - Generate QR code
  6. 5_sign_invoice_xml.php - Sign invoice
  7. 6_check_compliance.php - Validate compliance
  8. 7_generate_production_csid.php - Request production certificate

Testing

Run the test suite:

composer test

Or use PHPUnit directly:

vendor/bin/phpunit

Error Handling

The package throws specific exceptions for different error scenarios:

use Zid\Zatca\Exceptions\ZatcaApiException;
use Zid\Zatca\Exceptions\InvoiceHashingException;
use Zid\Zatca\Exceptions\QrGenerationException;

try {
    // Your code here
} catch (ZatcaApiException $e) {
    // Handle API errors
    echo "API Error: " . $e->getMessage();
} catch (InvoiceHashingException $e) {
    // Handle hashing errors
    echo "Hashing Error: " . $e->getMessage();
} catch (QrGenerationException $e) {
    // Handle QR generation errors
    echo "QR Error: " . $e->getMessage();
}

Best Practices

  1. Store Certificates Securely: Keep your private keys and certificates in secure storage
  2. Use Environment Variables: Store sensitive data like OTPs and secrets in environment variables
  3. Validate Before Submission: Always check compliance before submitting to production
  4. Handle Errors Gracefully: Implement proper error handling and logging
  5. Test in Sandbox: Thoroughly test your integration in the sandbox environment
  6. Keep Certificates Updated: Monitor certificate expiration and renew as needed

ZATCA Integration Workflow

1. Generate CSR + Private Key
   ↓
2. Request Compliance Certificate (with OTP)
   ↓
3. Hash Invoice XML
   ↓
4. Sign Invoice
   ↓
5. Generate QR Code
   ↓
6. Check Compliance
   ↓
7. Request Production Certificate
   ↓
8. Submit Invoices to Production

Resources

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This package is open-sourced software licensed under the MIT License.

Credits

Developed and maintained by Zid

Support

For issues, questions, or contributions, please visit the GitHub repository.

Disclaimer: This is an unofficial package and is not affiliated with or endorsed by ZATCA. Use at your own risk and ensure compliance with all ZATCA regulations.

统计信息

  • 总下载量: 6
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 7
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 6
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-09

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固