hyderkamran / laravel-zatca
Laravel package for ZATCA (Saudi Arabia) e-invoicing integration
Requires
- php: ^8.1
- ext-openssl: *
- ext-simplexml: *
- bacon/bacon-qr-code: ^2.0
- guzzlehttp/guzzle: ^7.0
- illuminate/support: ^9.0|^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.5|^10.0
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
HasZatcatrait to drop into your existingInvoicemodels.
Requirements
- PHP 8.1+
- Laravel 10.x / 11.x
ext-opensslext-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).