SaudiElectronIcinvoice Documentation

Saudi Electronic Invoice Controller Documentation

File: /controllers/saudiElectronIcinvoiceController.php

Purpose: Manages ZATCA (Saudi Arabia Tax Authority) electronic invoice integration and compliance

Last Updated: December 20, 2024

Total Functions: 7 main actions + 3 utility functions

Lines of Code: ~382

---

๐Ÿ“‹ Overview

The Saudi Electronic Invoice Controller implements the complete ZATCA (Zakat, Tax and Customs Authority) electronic invoicing system for Saudi Arabia tax compliance. This controller handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**saudielectronicinvoice**ZATCA configuration and settingsid, tokenapi, urlapi, deviceuuid, deviceid, stepnow, endsetup
**esaudiclientsetting**Client electronic invoice settingsclientid, licensetype, licensenumber, companyname
**etasellbillstatus**Electronic invoice submission trackingsellbillid, estatus, submissionid, accepteddocuments, errors
### Integration Tables (Referenced)

Table NamePurposeKey Columns
**sellbill**Sales bills for electronic submissionsellbillid, sellbillclientid, sellbilldate, sellbilltotalPayed, visaPayed
**sellbilldetail**Sales bill line itemssellbilldetailproductid, sellbilldetailquantity, sellbilldetailprice
**product**Product information for invoicesproductId, productName
### Key Relationships

-- Electronic invoice settings
saudielectronicinvoice.id = 1 (single configuration record)

-- Client settings for electronic invoicing
esaudiclientsetting.clientid -> client.clientid

-- Invoice submission tracking
etasellbillstatus.sellbillid -> sellbill.sellbillid

---

๐Ÿ”‘ Key Functions

1. Default Action (empty $do) - Configuration Display

Location: Lines 21-27

Purpose: Display ZATCA configuration interface

Process Flow:

1. Load ZATCA configuration from database

2. Assign configuration to template

3. Display setup interface via saudiElectronIcinvoiceView/saudielectronicinvoice.html

---

2. devices ($do == "devices") - Device Management

Location: Lines 28-33

Purpose: Display registered ZATCA devices

Process Flow:

1. Make API call to /api/v1/zatca/devices

2. Parse JSON response for device list

3. Display devices via template

API Call:

$devices = json_decode(HTTPRequester::HTTPGet($urlapi.'/api/v1/zatca/devices', [], $headers), true);

---

3. devicestatus ($do == "devicestatus") - Device Status Check

Location: Lines 34-39

Purpose: Check status of specific ZATCA device

Parameters:

API Call:

$device = json_decode(HTTPRequester::HTTPGet($urlapi.'/api/v1/zatca/device-status/'.$_GET['deviceuuid'], [], $headers), true);

---

4. getallinvoices ($do == "getallinvoices") - Invoice Listing

Location: Lines 40-51

Purpose: Retrieve submitted invoices from ZATCA

Parameters:

API Call:

$data = [
    'device_uuid' => $saudielectronicinvoice->deviceuuid,
    'status' => isset($_POST['status']) ? trim($_POST['status']) : 'accepted',
    'limit' => isset($_POST['limit']) ? trim($_POST['limit']) : 50,
    'offset' => isset($_POST['offset']) ? trim($_POST['offset']) : 0,
];
$getallinvoices = json_decode(HTTPRequester::HTTPGet($urlapi.'/api/v1/zatca/invoices', $data, $headers), true);

---

5. detail ($do == "detail") - Invoice Detail View

Location: Lines 52-57

Purpose: Display detailed invoice information including XML

Parameters:

API Call:

$invoice = json_decode(HTTPRequester::HTTPGet($urlapi.'/api/v1/zatca/invoice/'.$_GET['uuid'].'?include_xml=true', [], $headers), true);

---

6. update ($do == "update") - Multi-Step ZATCA Setup

Location: Lines 58-203

Purpose: Handle 4-step ZATCA device setup and compliance process

Step 1: Device Registration

Step 2: OTP Validation

Step 3: Compliance Testing

Step 4: Production Initialization

Process Flow for Each Step:

switch($step){
    case 1: // Device Registration
        // Authenticate and register device
        $result = json_decode(HTTPRequester::HTTPPost($urlapi.'/api/auth/login', $data, $headers), true);
        // Generate CSR
        $result = json_decode(HTTPRequester::HTTPPost($urlapi.'/api/v1/zatca/generate-csr', $data, $headers), true);
        break;
        
    case 2: // OTP Validation
        $result = json_decode(HTTPRequester::HTTPPost($urlapi.'/api/v1/zatca/validate-otp', $data, $headers), true);
        break;
        
    case 3: // Compliance Testing
        $result = json_decode(HTTPRequester::HTTPPost($urlapi.'/api/v1/zatca/send-compliance-invoice', $data, $headers), true);
        break;
        
    case 4: // Production Initialization
        $result = json_decode(HTTPRequester::HTTPPost($urlapi.'/api/v1/zatca/initialize-production', $data, $headers), true);
        break;
}

---

7. etsellbill ($do == "etsellbill") - Electronic Bill Submission

Location: Lines 204-340

Purpose: Submit sales bill to ZATCA for electronic invoicing

Parameters:

Process Flow:

1. Load sales bill and detail data

2. Load client electronic settings

3. Determine payment method based on bill payments

4. Build invoice line items from bill details

5. Generate invoice data structure

6. Submit to ZATCA API

7. Update bill with submission status and QR code

8. Log submission status

Payment Method Mapping:

if($sellbill['isBankAccountTransfer'] > 0){
    $payment_method = 42; // Bank transfer
}else if($sellbill['sellbilltotalPayed'] == 0 && $sellbill['visaPayed'] == 0){
    $payment_method = 30; // Credit
}else if($sellbill['visaPayed'] > 0 && $sellbill['sellbilltotalPayed'] > 0){
    $payment_method = 1; // Mixed payment
}else if($sellbill['visaPayed'] > 0){
    $payment_method = 48; // Card payment
}else{
    $payment_method = 10; // Cash payment
}

Invoice Data Structure:

$data = [
    "device_uuid" => $saudielectronicinvoice->deviceuuid,
    "invoice_type_code" => "0200000",
    "invoice_subtype_code" => "388",
    "invoice_number" => "INV-" . $sellbill['sellbillid'],
    "invoice_uuid" => makeUuidFromHex($sellbill['sellbillserial']),
    "invoice_counter" => $saudielectronicinvoice->invoicecounter,
    "previous_invoice_hash" => $saudielectronicinvoice->previousinvoicehash,
    "issue_date" => date("Y-m-d", strtotime($sellbill['sellbilldate'])),
    "issue_time" => date("H:i:s", strtotime($sellbill['sellbilldate'])),
    "seller_data" => [...], // Company information
    "customer_data" => [...], // Customer information (if applicable)
    "payment_method" => $payment_method,
    "products" => $invoiceLines // Product line items
];

---

๐Ÿ”„ Workflows

Workflow 1: ZATCA Device Setup (4-Step Process)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: ZATCA Setup Process
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
Step 1: Device Registration
โ†’ Authenticate with ZATCA API
โ†’ Submit company information
โ†’ Generate CSR (Certificate Signing Request)
โ”‚ โ””โ”€โ†’ Store device UUID and ID โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
Step 2: OTP Validation
โ†’ Receive OTP from ZATCA
โ†’ Submit OTP for device validation
โ”‚ โ””โ”€โ†’ Confirm device activation โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
Step 3: Compliance Testing
โ†’ Submit 6 test compliance invoices
โ†’ Monitor submission progress
โ†’ Wait for all 6 invoices to be accepted
โ”‚ โ””โ”€โ†’ Verify compliance approval โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
Step 4: Production Initialization
โ†’ Initialize production environment
โ†’ Mark setup as complete (endsetup = 1)
โ”‚ โ””โ”€โ†’ Ready for live invoice submission โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Electronic Invoice Submission

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Submit Sales Bill to ZATCA
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Sales Bill Data
โ†’ Get bill header information
โ†’ Load bill detail line items
โ”‚ โ””โ”€โ†’ Load customer electronic settings โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Determine Payment Method
โ†’ Check for bank transfers
โ†’ Check for credit terms
โ†’ Check for card payments
โ”‚ โ””โ”€โ†’ Default to cash payment โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Invoice Structure
โ†’ Generate invoice UUID
โ†’ Build seller data (company info)
โ†’ Build customer data (if not cash customer)
โ†’ Build product line items with tax
โ”‚ โ””โ”€โ†’ Set invoice counters and hashes โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Submit to ZATCA API
โ†’ POST invoice data to /api/v1/zatca/submit-invoice
โ†’ Check response status
โ”‚ โ””โ”€โ†’ Handle success/failure scenarios โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Update Bill Status
โ†’ Success: Update with UUID and QR code
โ†’ Failure: Mark as rejected with error details
โ†’ Update invoice counter and previous hash
โ”‚ โ””โ”€โ†’ Log submission status in etasellbillstatus โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionDisplay ZATCA configuration interface
`do=devices`Device listingShow registered ZATCA devices
`do=devicestatus`Device statusCheck specific device status
`do=getallinvoices`Invoice listingList submitted invoices
`do=detail`Invoice detailShow detailed invoice information
`do=update`Setup processHandle 4-step ZATCA setup
`do=etsellbill`Invoice submissionSubmit sales bill to ZATCA
### Required Parameters by Action

Device Status (do=devicestatus):

Invoice Detail (do=detail):

Setup Process (do=update):

Invoice Submission (do=etsellbill):

---

๐Ÿงฎ Calculation Methods

Tax Calculation (15% VAT)

// Applied to all product lines
$array = array(
    "tax_percentage" => 15.0,
    "tax_code" => "S" // Standard rate
);

UUID Generation

function makeUuidFromHex($hex) {
    // Convert to hex if not already
    if (!ctype_xdigit($hex)) {
        $hex = bin2hex($hex);
    }
    
    // Pad to 32 characters (128 bits)
    $hex = str_pad($hex, 32, "0");
    
    // Format as UUID
    return substr($hex, 0, 8) . "-" .
           substr($hex, 8, 4) . "-" .
           substr($hex, 12, 4) . "-" .
           substr($hex, 16, 4) . "-" .
           substr($hex, 20, 12);
}

Token Expiration Check

function istokenexpired() {
    if (empty($_SESSION['auth_token']) || empty($_SESSION['auth_token_exp'])) 
        return true;
    return (time() >= $_SESSION['auth_token_exp']);
}

---

๐Ÿ”’ Security & Permissions

Authentication & Authorization

// Authentication headers for ZATCA API
$headers = array(
    'Accept: application/json', 
    'Content-Type: application/json', 
    "Authorization: Bearer $saudielectronicinvoice->tokenapi", 
    "token: $saudielectronicinvoice->logintoken"
);

// Auto-refresh expired tokens
if (istokenexpired() && $_SESSION['auth_token']) {
    $result = refreshtoken();
    $authtoken = $_SESSION['auth_token'] = $result['data']['auth_token'];
    $_SESSION['auth_token_exp'] = time() + (int)$result['data']['expires_in'];
}

Input Validation

---

๐Ÿ“Š Performance Considerations

API Rate Limiting

1. Token Management: Reuse tokens until expiration to avoid excessive authentication

2. Batch Operations: Consider batching multiple invoice submissions

3. Error Handling: Implement proper retry logic for API failures

Database Optimization

-- Recommended indexes
CREATE INDEX idx_sellbill_client_date ON sellbill(sellbillclientid, sellbilldate);
CREATE INDEX idx_sellbilldetail_bill ON sellbilldetail(sellbillid);
CREATE INDEX idx_etasellbillstatus_bill ON etasellbillstatus(sellbillid);

---

๐Ÿ› Common Issues & Troubleshooting

1. Setup Step Failures

Issue: Setup process fails at any step

Cause: API connectivity, invalid data, or ZATCA service issues

Debug:

// Check stored responses
SELECT responsestepone, responsesteptwo, responsestepthree, responsestepfour 
FROM saudielectronicinvoice WHERE id = 1;

// Check current step status
SELECT stepnow, endsetup FROM saudielectronicinvoice WHERE id = 1;

2. Token Expiration Issues

Issue: API calls fail with authentication errors

Cause: Expired authentication tokens

Fix:

// Manual token refresh
if (istokenexpired()) {
    $result = refreshtoken();
    // Update stored token
}

3. Invoice Submission Failures

Issue: Sales bills not accepted by ZATCA

Cause: Invalid customer data, missing fields, or format errors

Debug:

-- Check submission status
SELECT * FROM etasellbillstatus WHERE sellbillid = [BILL_ID];

-- Check bill electronic status
SELECT estatus, ereason, qrerpids FROM sellbill WHERE sellbillid = [BILL_ID];

4. Missing Client Electronic Settings

Issue: Customer invoices fail due to missing settings

Cause: No electronic settings configured for B2B customers

Fix:

-- Check client settings
SELECT * FROM esaudiclientsetting WHERE clientid = [CLIENT_ID];

-- Add required settings for B2B customers
INSERT INTO esaudiclientsetting (clientid, licensetype, licensenumber, companyname, ...) VALUES (...);

---

๐Ÿงช Testing Scenarios

Test Case 1: Complete Setup Process

1. Start fresh ZATCA setup (stepnow = 0)
2. Complete Step 1 with valid company data
3. Validate OTP in Step 2
4. Monitor compliance testing in Step 3
5. Initialize production in Step 4
6. Verify endsetup = 1

Test Case 2: Invoice Submission

1. Create test sales bill
2. Configure customer electronic settings (if B2B)
3. Submit bill via etsellbill action
4. Verify ZATCA acceptance
5. Check QR code generation
6. Confirm bill status update

Test Case 3: Error Handling

1. Submit invoice with invalid data
2. Check error logging in etasellbillstatus
3. Verify bill marked with error status
4. Test retry functionality

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When ZATCA requirements change