PHP code example of aghfatehi / laravel-zatca
1. Go to this page and download the library: Download aghfatehi/laravel-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/ */
aghfatehi / laravel-zatca example snippets
use Aghfatehi\Zatca\Facades\Zatca;
// Simple QR text generation
$qrText = Zatca::phase1()->generateQrCodeText(
sellerName: 'شركة التقنية',
vatNumber: '300000000000003',
invoiceDate: '2024-01-01T12:00:00Z',
totalAmount: '115.00',
taxAmount: '15.00',
);
// Base64-encoded TLV string ready for embedding
echo $qrText;
use Aghfatehi\Zatca\DTO\InvoiceDTO;
$invoice = InvoiceDTO::fromArray([
'invoice_serial_number' => 'INV-001',
'issue_date' => '2024-01-01',
'issue_time' => '12:00:00',
'line_items' => [
[
'id' => '1',
'name' => 'Product A',
'quantity' => 2,
'tax_exclusive_price' => 100.00,
'vat_percent' => 0.15,
],
],
]);
$egsUnit = [
'vat_name' => 'شركة التقنية',
'vat_number' => '300000000000003',
];
$qrText = Zatca::phase1()->generateQrCodeFromInvoice($invoice, $egsUnit);
// Generate keys & CSR
$keys = Zatca::phase2()->generateKeysAndCsr($egsUnit, 'ERP');
// Issue compliance certificate with OTP from ZATCA portal
$result = Zatca::phase2()->issueComplianceCertificate($keys['csr'], $otp);
if ($result->success) {
// Save these securely
$certificate = $result->binarySecurityToken;
$secret = $result->secret;
$privateKey = $keys['private_key'];
// Store in .env or database
\Illuminate\Support\Facades\Env::set('ZATCA_CERTIFICATE', base64_encode($certificate));
\Illuminate\Support\Facades\Env::set('ZATCA_SECRET', $secret);
\Illuminate\Support\Facades\Env::set('ZATCA_PRIVATE_KEY', base64_encode($privateKey));
}
// Build invoice data
$invoice = InvoiceDTO::fromArray([
'invoice_serial_number' => 'EGS1-886431145-1',
'invoice_counter_number' => 2,
'issue_date' => '2024-01-01',
'issue_time' => '14:40:40',
'previous_invoice_hash' => '',
'line_items' => [
[
'id' => '1',
'name' => 'Product A',
'quantity' => 10,
'tax_exclusive_price' => 100.00,
'vat_percent' => 0.15,
],
],
]);
$egsUnit = [
'uuid' => '6f4d20e0-6bfe-4a80-9389-7dabe6620f12',
'custom_id' => 'EGS1-886431145',
'model' => 'Desktop',
'vat_number' => '300000000000003',
'vat_name' => 'شركة التقنية',
'crn_number' => '454634645645654',
'location' => [
'city' => 'Riyadh',
'city_subdivision' => 'West',
'street' => 'King Fahd Road',
'building' => '1234',
'plot_identification' => '0000',
'postal_zone' => '11564',
],
'branch_name' => 'Main Branch',
'branch_industry' => 'Retail',
];
// 1. Sign invoice (generates XML + hash + QR)
$signed = Zatca::phase2()->signInvoice(
invoice: $invoice,
egsUnit: $egsUnit,
certificate: $certificate,
privateKey: $privateKey,
);
// 2. Submit to ZATCA (auto-detects sandbox vs production)
$result = Zatca::phase2()->submitInvoice(
signedInvoiceXml: $signed['signed_xml'],
invoiceHash: $signed['invoice_hash'],
certificate: $certificate,
secret: $secret,
);
if ($result->success) {
echo 'Invoice submitted successfully! Request ID: ' . $result->requestID;
}
use Aghfatehi\Zatca\Jobs\SyncInvoiceToZatcaJob;
SyncInvoiceToZatcaJob::dispatch(
invoiceData: $invoice->toArray(),
egsUnit: $egsUnit,
certificate: $certificate,
privateKey: $privateKey,
secret: $secret,
);
namespace App\Http\Controllers;
use Aghfatehi\Zatca\Facades\Zatca;
class InvoiceController extends Controller
{
public function show(Invoice $invoice)
{
$qrTlv = Zatca::phase1()->generateQrCodeFromInvoice(
invoice: $invoice->toInvoiceDto(),
egsUnit: [
'vat_name' => config('zatca.egs.vat_name'),
'vat_number' => config('zatca.egs.vat_number'),
],
);
return view('invoice.show', compact('invoice', 'qrTlv'));
}
}
use Zatca;
class InvoiceController extends Controller
{
public function show(Invoice $invoice)
{
$qrTlv = Zatca::phase1()->generateQrCodeText(
sellerName: config('zatca.egs.vat_name'),
vatNumber: config('zatca.egs.vat_number'),
invoiceDate: $invoice->created_at->format('Y-m-d\TH:i:s\Z'),
totalAmount: (string)$invoice->total,
taxAmount: (string)$invoice->tax,
);
return view('invoice.show', compact('invoice', 'qrTlv'));
}
}
$qrData = Zatca::generatePhase2Qr(
sellerName: config('zatca.egs.vat_name'),
vatNumber: config('zatca.egs.vat_number'),
invoiceDate: $invoice->created_at->format('Y-m-d\TH:i:s\Z'),
totalAmount: '115.00',
taxAmount: '15.00',
invoiceHash: $signedInvoice['invoice_hash'], // from InvoiceSignerService
digitalSignature: $signedInvoice['digital_signature'], // ECDSA signature
publicKey: $signedInvoice['public_key'], // from certificate
certificateSignature: $signedInvoice['certificate_signature'], // from ZATCA
);
use Aghfatehi\Zatca\Traits\HasZatcaQrCode;
class Invoice extends Model
{
use HasZatcaQrCode;
// Customize field names (optional)
protected $zatcaSellerField = 'company_name';
protected $zatcaVatField = 'vat_number';
protected $zatcaDateField = 'invoice_date';
protected $zatcaTotalField = 'total_amount';
protected $zatcaTaxField = 'tax_amount';
}
use Barryvdh\DomPDF\Facade\Pdf;
$qrText = Zatca::phase1()->generateQrCodeText(
sellerName: $invoice->company_name,
vatNumber: $invoice->vat_number,
invoiceDate: $invoice->invoice_date->format('Y-m-d\TH:i:s\Z'),
totalAmount: (string)$invoice->total_amount,
taxAmount: (string)$invoice->tax_amount,
);
// Generate QR as data URI (auto-detects format)
$qrDataUri = Zatca::qr()->renderAsDataUri($qrText, 150);
$pdf = Pdf::loadView('invoice.pdf', compact('invoice', 'qrDataUri'));
return $pdf->download('invoice.pdf');
use Mpdf\Mpdf;
$mpdf = new Mpdf(['mode' => 'utf-8', 'format' => 'A4']);
$qrText = Zatca::phase1()->generateQrCodeText(...);
$qrDataUri = Zatca::qr()->renderAsDataUri($qrText, 150);
$html = '<div style="position: absolute; bottom: 10mm; right: 10mm;">
<img src="' . $qrDataUri . '" width="150" height="150"/>
</div>';
$mpdf->WriteHTML($html);
$mpdf->Output('invoice.pdf', 'D');
// Base64-encoded image (SVG or PNG depending on installed packages)
$base64 = Zatca::qr()->renderAsBase64($qrText, 200);
// Data URI ready for <img> tag
$dataUri = Zatca::qr()->renderAsDataUri($qrText, 200);
// Save directly to file (SVG or PNG)
Zatca::qr()->renderToFile($qrText, storage_path('app/public/qr/invoice.svg'), 200);
namespace App\Listeners;
use Aghfatehi\Zatca\Events\InvoiceCleared;
class UpdateInvoiceStatus
{
public function handle(InvoiceCleared $event): void
{
$serial = $event->invoiceData['invoice_serial_number'];
// Update your invoice status in DB
Invoice::where('serial_number', $serial)
->update(['zatca_status' => 'cleared']);
}
}
protected $listen = [
\Aghfatehi\Zatca\Events\InvoiceCleared::class => [
\App\Listeners\UpdateInvoiceStatus::class,
],
\Aghfatehi\Zatca\Events\InvoiceFailed::class => [
\App\Listeners\MarkInvoiceAsFailed::class,
],
];
use Aghfatehi\Zatca\Services\Phase2Service;
class YourController
{
public function sync(Request $request, Phase2Service $phase2)
{
$invoice = InvoiceDTO::fromArray($request->all());
$result = $phase2->signInvoice($invoice, ...);
// ...
}
}
bash
php artisan vendor:publish --tag=zatca-config
bash
php artisan vendor:publish --tag=zatca-migrations
php artisan migrate --path=/database/migrations/2024_01_01_000001_create_zatca_certificates_table.php
php artisan migrate --path=/database/migrations/2024_01_01_000002_create_zatca_invoice_logs_table.php
bash
php artisan vendor:publish --tag=zatca-views
bash
php artisan zatca:check
bash
php artisan zatca:onboard --otp=123456 --solution-name=ERP --save
blade
{{-- resources/views/invoice/show.blade.php --}}
@extends('layouts.app')
@section('content')
<div class="invoice">
<h1>Invoice #{{ $invoice->number }}</h1>
{{-- ... invoice details ... --}}
<div class="qr-section" style="text-align: center; margin-top: 20px;">
@bash
php artisan queue:work --queue=zatca --tries=3 --delay=3600