PHP code example of thesmarter / zatca

1. Go to this page and download the library: Download thesmarter/zatca library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

thesmarter / zatca example snippets



Smart\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');


use Smart\Zatca\ComplianceService;
use Smart\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;


use Smart\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));


use Smart\Zatca\InvoiceSigningService;
use Smart\Zatca\GetDigitalSignatureService;
use Smart\Zatca\GetPublicKeyAndSignatureService;
use Smart\Zatca\QrCodeGeneratorService;
use Smart\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;


use Smart\Zatca\ComplianceService;
use Smart\Zatca\Enums\ZatcaEnvironment;
use Smart\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);
}


use Smart\Zatca\ProductionCsidGeneratorService;
use Smart\Zatca\Enums\ZatcaEnvironment;
use Smart\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');


use Smart\Zatca\InvoiceSubmissionService;
use Smart\Zatca\Enums\ZatcaEnvironment;
use Smart\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);
}

use Smart\Zatca\Enums\ZatcaEnvironment;

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

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

// Production - For live invoices
ZatcaEnvironment::PRODUCTION


Smart\Zatca\Zatca;
use Smart\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;
    }
}

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

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

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

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

use Smart\Zatca\InvoiceBuilder;

$xml = InvoiceBuilder::simplified([
    'id' => 'SME-0001',
    'uuid' => 'a9ea6c06-1a83-432c-8854-dd023a1753d1',
    'issueDate' => '2026-09-23',
    'issueTime' => '10:00:00',
    'currency' => 'SAR',
    'icv' => 1,          // invoice counter, sequential per EGS device
    'pih' => '...',      // previous invoice hash (base64)
    'seller' => [
        'name' => 'Test Seller', 'vatNumber' => '310122393500003',
        'crNumber' => '1010010000', 'street' => 'Test St',
        'city' => 'Riyadh', 'postalCode' => '11564', 'countryCode' => 'SA',
    ],
    'lines' => [
        ['name' => 'Item A', 'quantity' => 2, 'unitPrice' => 100.0, 'vatPercent' => 15.0],
    ],
]);

// B2B invoices requiring clearance:
$xml = InvoiceBuilder::standard([...$data, 'buyer' => ['name' => '...', 'vatNumber' => '...', ...]]);

$service = (new \Smart\Zatca\Zatca(\Smart\Zatca\Enums\ZatcaEnvironment::PRODUCTION))->production();

$csid = $service->renewProductionCertificate(
    binarySecurityToken: $pcsid->certificate,
    secret: $pcsid->secret,
    otp: 'renewal-otp-from-fatoora-portal',
    b64Csr: $newCsr,
);

use Smart\Zatca\Exceptions\ZatcaApiException;
use Smart\Zatca\Exceptions\InvoiceHashingException;
use Smart\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();
}