PHP code example of corecave / laravel-zatca

1. Go to this page and download the library: Download corecave/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/ */

    

corecave / laravel-zatca example snippets


use Corecave\Zatca\Facades\Zatca;

// The package automatically uses your production certificate
$result = Zatca::process($invoice);



namespace App\Services;

use Corecave\Zatca\Facades\Zatca;
use Corecave\Zatca\Invoice\InvoiceBuilder;
use Corecave\Zatca\Enums\VatCategory;
use Corecave\Zatca\Enums\PaymentMethod;
use Corecave\Zatca\Models\ZatcaInvoice;

class InvoiceService
{
    /**
     * Create and submit a B2C invoice to ZATCA.
     */
    public function createSimplifiedInvoice(array $orderData): ZatcaInvoice
    {
        // Step 1: Build the invoice
        $invoice = InvoiceBuilder::simplified()
            ->setInvoiceNumber('INV-' . date('Y') . '-' . str_pad($orderData['id'], 6, '0', STR_PAD_LEFT))
            ->setIssueDate(now())
            ->setSupplyDate(now())
            ->setPaymentMethod(PaymentMethod::CASH);

        // Step 2: Add line items
        foreach ($orderData['items'] as $item) {
            $invoice->addLineItem([
                'name' => $item['name'],
                'quantity' => $item['quantity'],
                'unit_price' => $item['price'],  // Price EXCLUDING VAT
                'vat_category' => VatCategory::STANDARD,  // 15% VAT
            ]);
        }

        // Step 3: Build and submit to ZATCA
        $builtInvoice = $invoice->build();
        $result = Zatca::report($builtInvoice);  // B2C uses report()

        // Step 4: Handle the result
        if ($result->isSuccess()) {
            // Get the stored invoice record
            $zatcaInvoice = ZatcaInvoice::where('uuid', $builtInvoice->getUuid())->first();

            // QR code for printing on receipt
            $qrCodeTlv = $result->getQrCode();

            // QR code as PNG for embedding in emails/PDFs
            $qrCodePng = $zatcaInvoice->qr_code_image;

            return $zatcaInvoice;
        }

        // Handle errors
        throw new \Exception('ZATCA submission failed: ' . json_encode($result->getErrors()));
    }

    /**
     * Create and submit a B2B invoice to ZATCA.
     */
    public function createStandardInvoice(array $orderData, array $buyerData): ZatcaInvoice
    {
        // Step 1: Build the invoice with buyer information
        $invoice = InvoiceBuilder::standard()
            ->setInvoiceNumber('INV-' . date('Y') . '-' . str_pad($orderData['id'], 6, '0', STR_PAD_LEFT))
            ->setIssueDate(now())
            ->setSupplyDate(now())
            ->setPaymentMethod(PaymentMethod::CREDIT)
            ->setBuyer([
                'name' => $buyerData['company_name'],
                'vat_number' => $buyerData['vat_number'],
                'registration_number' => $buyerData['cr_number'],
                'registration_scheme' => 'CRN',
                'address' => [
                    'street' => $buyerData['street'],
                    'building' => $buyerData['building'],
                    'city' => $buyerData['city'],
                    'district' => $buyerData['district'],
                    'postal_code' => $buyerData['postal_code'],
                    'country' => 'SA',
                ],
            ]);

        // Step 2: Add line items
        foreach ($orderData['items'] as $item) {
            $invoice->addLineItem([
                'name' => $item['name'],
                'quantity' => $item['quantity'],
                'unit_price' => $item['price'],
                'vat_category' => VatCategory::STANDARD,
            ]);
        }

        // Step 3: Build and submit to ZATCA
        $builtInvoice = $invoice->build();
        $result = Zatca::clear($builtInvoice);  // B2B uses clear()

        // Step 4: Handle the result
        if ($result->isSuccess()) {
            return ZatcaInvoice::where('uuid', $builtInvoice->getUuid())->first();
        }

        throw new \Exception('ZATCA clearance failed: ' . json_encode($result->getErrors()));
    }

    /**
     * Auto-detect invoice type and submit.
     */
    public function submitInvoice($invoice): ZatcaInvoice
    {
        // process() automatically uses report() for B2C and clear() for B2B
        $result = Zatca::process($invoice);

        if ($result->wasReported()) {
            // B2C invoice was reported
        }

        if ($result->wasCleared()) {
            // B2B invoice was cleared
        }

        return ZatcaInvoice::where('uuid', $invoice->getUuid())->first();
    }
}

use Corecave\Zatca\Invoice\InvoiceBuilder;

// Credit note for a B2C refund
$creditNote = InvoiceBuilder::creditNote(simplified: true)
    ->setInvoiceNumber('CN-2024-001')
    ->setOriginalInvoice('INV-2024-001')  // Reference the original invoice
    ->setReason('Customer returned goods')
    ->addLineItem([
        'name' => 'Returned Product',
        'quantity' => 1,
        'unit_price' => 100.00,
        'vat_category' => VatCategory::STANDARD,
    ])
    ->build();

$result = Zatca::process($creditNote);

use Corecave\Zatca\Models\ZatcaInvoice;

$invoice = ZatcaInvoice::find($id);

// Get QR code as base64-encoded PNG (for emails/PDFs)
$pngBase64 = $invoice->qr_code_image;
echo '<img src="data:image/png;base64,' . $pngBase64 . '" alt="QR Code">';

// Get QR code as SVG (for web display)
$svg = $invoice->qr_code_svg;
echo $svg;

// Get raw TLV data (for custom QR generation)
$tlvData = $invoice->qr_code;

use Corecave\Zatca\Exceptions\ApiException;
use Corecave\Zatca\Exceptions\ValidationException;
use Corecave\Zatca\Exceptions\CertificateException;

try {
    $result = Zatca::report($invoice);

    if (!$result->isSuccess()) {
        // ZATCA accepted but with warnings
        $warnings = $result->getWarnings();
    }
} catch (ValidationException $e) {
    // Invoice validation failed locally
    $errors = $e->getErrors();
} catch (ApiException $e) {
    // ZATCA API returned an error
    $zatcaErrors = $e->getZatcaErrors();
    $zatcaWarnings = $e->getZatcaWarnings();
} catch (CertificateException $e) {
    // Certificate issue (missing, expired, invalid)
    $message = $e->getMessage();
}

// In EventServiceProvider
protected $listen = [
    \Corecave\Zatca\Events\InvoiceReported::class => [
        \App\Listeners\HandleInvoiceReported::class,
    ],
    \Corecave\Zatca\Events\InvoiceCleared::class => [
        \App\Listeners\HandleInvoiceCleared::class,
    ],
    \Corecave\Zatca\Events\InvoiceRejected::class => [
        \App\Listeners\HandleInvoiceRejected::class,
    ],
];
bash
php artisan vendor:publish --tag=zatca-config
bash
php artisan migrate
bash
php artisan zatca:generate-csr --save
bash
php artisan zatca:production-csid
bash
php artisan zatca:generate-csr --save
bash
# After compliance passes (no OTP needed):
php artisan zatca:production-csid

# Or specify request ID manually:
php artisan zatca:production-csid --request-id=1234567890