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();
}