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