hyderkamran/laravel-zatca

Laravel package for ZATCA (Saudi Arabia) e-invoicing integration

Maintainers

Package info

github.com/haider-kamran/laravel-zatca

pkg:composer/hyderkamran/laravel-zatca

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-06-03 18:12 UTC

This package is auto-updated.

Last update: 2026-06-03 18:13:03 UTC


README

A production-grade, open-source Laravel package for complete compliance with Saudi Arabia's ZATCA E-Invoicing requirements (Phase 1 & Phase 2).

Features

  • E-Invoicing: Full support for B2B (Standard) and B2C (Simplified) invoices.
  • XML Generation: Robust UBL 2.1 XML building, correctly typed and schema-compliant.
  • QR Generation: Mandatory TLV (Tag-Length-Value) Base64 encoding for QR codes (all 9 tags supported).
  • Phase 1 Compliance: Generate XML and QR codes locally.
  • Phase 2 Compliance: Full API integration for Clearance (Standard) and Reporting (Simplified) workflows.
  • Sandbox Support: Switch seamlessly between ZATCA Developer Portal (Sandbox) and Core API (Production).
  • Cryptography Engine: Built-in support for ECDSA secp256k1 private keys, C14N XML canonicalization, and SHA-256 hashing.
  • CSID Lifecycle: Artisan commands for CSR generation, compliance checks, and CSID onboarding.
  • Eloquent Integration: A simple HasZatca trait to drop into your existing Invoice models.

Requirements

  • PHP 8.1+
  • Laravel 10.x / 11.x
  • ext-openssl
  • ext-simplexml

Installation

You can install the package via composer:

composer require hyderkamran/laravel-zatca

Publish the configuration file and migrations:

php artisan vendor:publish --tag="zatca-config"
php artisan vendor:publish --tag="zatca-migrations"

Run the migrations to create the zatca_certificates and zatca_submissions tables:

php artisan migrate

Configuration

Set your organization and seller details in config/zatca.php or your .env file:

ZATCA_ENVIRONMENT=sandbox
ZATCA_SELLER_NAME="Acme Corp"
ZATCA_SELLER_VAT_NUMBER="300000000000003"
ZATCA_SELLER_CR_NUMBER="1234567890"

ZATCA_ORG_NAME="Acme Corp"
ZATCA_ORG_UNIT="IT Department"
ZATCA_COMMON_NAME="acme-zatca-system"
ZATCA_EGIC="300000000000003"

Usage

1. Generate CSR & Private Key

Run the interactive command to generate a ZATCA-compliant CSR and secp256k1 private key.

php artisan zatca:generate-csr --env=sandbox --save-db

Submit this CSR to the ZATCA portal to retrieve an OTP.

(Note: Currently activate-csid command will be implemented to automatically store the CSID and secret from the OTP. For now, you can manually issue the API call via Zatca::client()->issueComplianceCsid() and store it in your DB).

2. Eloquent Trait Integration

Add the HasZatca trait to your existing Invoice model:

use Hyderkamran\LaravelZatca\Traits\HasZatca;
use Hyderkamran\LaravelZatca\Enums\InvoiceType;

class Invoice extends Model
{
    use HasZatca;

    public function getZatcaInvoiceType(): InvoiceType
    {
        return $this->is_b2b ? InvoiceType::STANDARD : InvoiceType::SIMPLIFIED;
    }

    public function toZatcaSeller(): array
    {
        return [
            'name'       => 'Acme Corp',
            'vat_number' => '300000000000003',
            // ...
        ];
    }

    public function toZatcaBuyer(): array
    {
        return [
            'name'       => $this->customer->name,
            'vat_number' => $this->customer->vat_number,
        ];
    }

    public function toZatcaItems(): array
    {
        return $this->items->map(fn($item) => [
            'name'     => $item->name,
            'quantity' => $item->qty,
            'price'    => $item->price,
        ])->toArray();
    }
}

3. Generate XML and Submit

Once your model is configured, submission is one method call away:

$invoice = Invoice::find(1);

// Phase 1: Generate XML locally
$xml = $invoice->generateZatcaXml();

// Phase 2: Submit to ZATCA directly (auto-signs and routes to Clearance or Reporting)
$response = $invoice->submitToZatca();

if ($response->isSuccessful()) {
    echo "Invoice submitted successfully!";
} else {
    print_r($response->errors);
}

Fluent API (Without Models)

You can also use the Facade to build and submit invoices manually:

use Hyderkamran\LaravelZatca\Facades\Zatca;

$invoiceService = Zatca::invoice()
    ->simplified()
    ->seller(['name' => 'Acme', 'vat_number' => '300000000000003'])
    ->buyer(['name' => 'John Doe'])
    ->items([
        ['name' => 'Service A', 'quantity' => 1, 'price' => 100],
    ])
    ->vat(15);

// Get Base64 QR Code Image
$qrBase64 = $invoiceService->generateQrCode();

// Get valid XML
$xml = $invoiceService->generate();

// Submit
$response = Zatca::submit($invoiceService);

Credits

Support

Please open an issue in GitHub if you encounter any problems or have feature requests.

Security Vulnerabilities

If you discover a security vulnerability within this package, please send an e-mail to the maintainer. All security vulnerabilities will be promptly addressed.

License

The MIT License (MIT).