=== ZATCA OFFLINE CALCULATE SIGNATURE AUDIT ===

==============================================================================================================
FILE=fatoora-zatca/src/Services/ReportInvoiceService.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Services;
use Bl\FatooraZatca\Actions\PostRequestAction;
use Bl\FatooraZatca\Classes\DocumentType;
use Bl\FatooraZatca\Helpers\ConfigHelper;
use Bl\FatooraZatca\Services\Invoice\HashInvoiceService;
use Bl\FatooraZatca\Services\Invoice\SignInvoiceService;
class ReportInvoiceService

------------------------------------------------------------------------------------------
METHOD=__construct
------------------------------------------------------------------------------------------
    public function __construct(object $seller, object $invoice, object $client = null)
    {
        $this->seller   = $seller;

        $this->invoice  = $invoice;

        $this->client   = $client;
    }

------------------------------------------------------------------------------------------
METHOD=calculate
------------------------------------------------------------------------------------------
    public function calculate(string $document_type): array
    {
        $hashInvoiceService = new HashInvoiceService($this->seller, $this->invoice, $this->client);

        $invoiceHash = $hashInvoiceService->generate($document_type);

        $signedXmlContent = (new SignInvoiceService(
            $this->seller,
            $this->invoice,
            $hashInvoiceService->getInvoiceXmlContent(),
            $invoiceHash
        ))->generate();

        return [
            'invoiceHash'       => $invoiceHash,
            'clearedInvoice'    => $signedXmlContent,
        ];
    }

------------------------------------------------------------------------------------------
METHOD=report
------------------------------------------------------------------------------------------
    public function report(string $route, string $document_type): array
    {
        $calculateInvoice = $this->calculate($document_type);

        $USERPWD = $this->seller->certificate . ':' . $this->seller->secret;

        $response = (new PostRequestAction)->handle($route,
        [
            'invoiceHash' => $calculateInvoice['invoiceHash'], # hashed invoice in base64 format
            'uuid' => $this->invoice->invoice_uuid,
            'invoice' => $calculateInvoice['clearedInvoice'], # signed invoice in base64 format
        ],
        [
            'Content-Type: application/json',
            'Accept-Language: en',
            'Accept-Version: V2',
            'Clearance-Status: 1'
        ],
            $USERPWD
        );

        return array_merge($response, $calculateInvoice);
    }

------------------------------------------------------------------------------------------
METHOD=reporting
------------------------------------------------------------------------------------------
    public function reporting(): array
    {
        $route = '/invoices/reporting/single';

        return $this->report($route, DocumentType::SIMPILIFIED);
    }

------------------------------------------------------------------------------------------
METHOD=clearance
------------------------------------------------------------------------------------------
    public function clearance(): array
    {
        $route = '/invoices/clearance/single';

        return $this->report($route, DocumentType::STANDARD);
    }

==============================================================================================================
FILE=fatoora-zatca/src/Services/Invoice/HashInvoiceService.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Services\Invoice;
use Bl\FatooraZatca\Actions\GetXmlFileAction;
use Bl\FatooraZatca\Classes\InvoiceType;
class HashInvoiceService

------------------------------------------------------------------------------------------
METHOD=__construct
------------------------------------------------------------------------------------------
    public function __construct(object $seller, object $invoice, ?object $client)
    {
        $this->seller   = $seller;

        $this->invoice  = $invoice;

        $this->client   = $client;
    }

------------------------------------------------------------------------------------------
METHOD=generate
------------------------------------------------------------------------------------------
    public function generate(string $document_type): string
    {
        $this->documentType = $document_type;

        $this->invoiceXml = GetXmlFileAction::handle('xml_to_hash');

        $this->invoiceXml = str_replace("\r", "", $this->invoiceXml);

        $this->xmlGenerator();

        // Eliminate Additional Signed Tags
        $invoice = str_replace('SET_XML_ENCODING', '', $this->invoiceXml);

        $invoice = str_replace('SET_UBL_EXTENSIONS_FOR_SIGNED', "    ", $invoice);

        $invoice = str_replace('SET_QR_AND_SIGNATURE_FOR_SIGNED', "    \n    ", $invoice);

        $invoiceHash = hash('sha256', $invoice, true);

        return base64_encode($invoiceHash);
    }

------------------------------------------------------------------------------------------
METHOD=xmlGenerator
------------------------------------------------------------------------------------------
    protected function xmlGenerator(): void
    {
        $this->setInvoiceDetails();

        $this->setInvoiceBillingReferenceIfExists();

        $this->setPreviousInvoiceHash();

        $this->setAccountingSupplierParty();

        $this->setAccountingCustomerParty();

        $this->setDeliveryDate();

        $this->setInvoicePaymentMeans();

        (new XmlInvoiceItemsService($this->invoice))->generate($this->invoiceXml);

        // BT-6 (TaxCurrencyCode) must always be SAR per BR-KSA-EN16931-02
        $this->invoiceXml = str_replace('<cbc:TaxCurrencyCode>SET_CURRENCY</cbc:TaxCurrencyCode>', '<cbc:TaxCurrencyCode>SAR</cbc:TaxCurrencyCode>', $this->invoiceXml);
        $this->invoiceXml = str_replace('SET_CURRENCY', $this->invoice->currency, $this->invoiceXml);
    }

==============================================================================================================
FILE=fatoora-zatca/src/Services/Invoice/SignInvoiceService.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Services\Invoice;
use Bl\FatooraZatca\Actions\GetXmlFileAction;
use Bl\FatooraZatca\Helpers\ConfigHelper;
use Bl\FatooraZatca\Helpers\InvoiceHelper;
use Bl\FatooraZatca\Transformers\PriceFormat;
use Bl\FatooraZatca\Transformers\PublicKey;
use phpseclib3\File\X509;
use DOMDocument;
class SignInvoiceService

------------------------------------------------------------------------------------------
METHOD=__construct
------------------------------------------------------------------------------------------
    public function __construct(object $seller, object $invoice, string $invoice_xml, string $invoice_hash)
    {
        $this->seller       = $seller;

        $this->invoice      = $invoice;

        $this->invoiceXml   = $invoice_xml;

        $this->invoiceHash  = $invoice_hash;
    }

------------------------------------------------------------------------------------------
METHOD=setUp
------------------------------------------------------------------------------------------
    protected function setUp(): void
    {
        $csrX509 = "-----BEGIN CERTIFICATE-----\r\n". base64_decode($this->seller->certificate) ."\r\n-----END CERTIFICATE-----";

        $x509 = new X509();

        $this->certificateOutput = $x509->loadX509($csrX509);

        $issuerNameArray = $x509->getIssuerDN(X509::DN_ARRAY)['rdnSequence'];

        if(count($issuerNameArray) === 4) {
            $CN = $issuerNameArray[3][0]['value']['printableString'];
            $DC1 = $issuerNameArray[2][0]['value']['ia5String'];
            $DC2 = $issuerNameArray[1][0]['value']['ia5String'];
            $DC3 = $issuerNameArray[0][0]['value']['ia5String'];
            $this->issuerName = "CN={$CN}, DC={$DC1}, DC={$DC2}, DC={$DC3}";
        }
        else {
            $this->issuerName = $x509->getIssuerDN(X509::DN_STRING);
        }

        $this->publicKey         = (new PublicKey)->transform($x509->getPublicKey());

        $this->digitalSignature = $this->getDigitalSignature();
    }

------------------------------------------------------------------------------------------
METHOD=generate
------------------------------------------------------------------------------------------
    public function generate(): string
    {
        $this->setUp();

        $this->invoiceXml = str_replace('SET_XML_ENCODING', '<?xml version="1.0" encoding="UTF-8"?>', $this->invoiceXml);

        $this->invoiceXml = str_replace(
            'SET_UBL_EXTENSIONS_FOR_SIGNED',
            $this->getUBLExtensions(),
            $this->invoiceXml
        );

        $this->invoiceXml = str_replace(
            'SET_QR_AND_SIGNATURE_FOR_SIGNED',
            $this->getQRCodeData(),
            $this->invoiceXml
        );

        return base64_encode($this->invoiceXml);
    }

------------------------------------------------------------------------------------------
METHOD=getQRCodeData
------------------------------------------------------------------------------------------
    protected function getQRCodeData(): string
    {
        $xml = GetXmlFileAction::handle('xml_qr_and_signature');

        $data = [
            $this->seller->registration_name,
            $this->seller->tax_number,
            (new InvoiceHelper)->getTimestamp($this->invoice),
            // TESTMOBILE_ZATCA_QR_TAG4_BT115_FIX_20260720
            PriceFormat::transform(
                $this->invoice->payable_amount
                    ?? $this->invoice->total
            ),
            PriceFormat::transform($this->invoice->tax),
            $this->invoiceHash,
            $this->digitalSignature,
            $this->publicKey,
            (new InvoiceHelper)->getCertificateSignature($this->certificateOutput),
        ];

        $tlvEncoded = (new TLVProtocolService($data))->toBase64Format();

        $xml = str_replace('SET_QR_CODE_DATA', $tlvEncoded, $xml);

        $xml = rtrim($xml, "\n");

        return $xml;
    }

==============================================================================================================
FILE=fatoora-zatca/src/Objects/Invoice.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Objects;
class Invoice

------------------------------------------------------------------------------------------
METHOD=__construct
------------------------------------------------------------------------------------------
    public function __construct(
        int         $id,
        string      $invoice_number,
        string      $invoice_uuid,
        string      $invoice_date,
        string      $invoice_time,
        int         $invoice_type,
        int         $payment_type,
        float       $price,
        float       $discount,
        float       $tax,
        float       $total,
        array       $invoice_items,
        string      $previous_hash = null,
        $invoice_billing_id = null,
        string      $invoice_note = null,
        string      $payment_note = null,
        string      $currency = 'SAR',
        float       $tax_percent = 15,
        string      $delivery_date = NULL
    )
    {
        $this->id                       = $id;
        $this->invoice_number           = $invoice_number;
        $this->invoice_billing_id       = $invoice_billing_id;
        $this->invoice_uuid             = $invoice_uuid;
        $this->invoice_date             = $invoice_date;
        $this->invoice_time             = $invoice_time;
        $this->invoice_type             = $invoice_type;
        $this->payment_type             = $payment_type;
        $this->invoice_note             = $invoice_note;
        $this->payment_note             = $payment_note;
        $this->currency                 = $currency;
        $this->previous_hash            = $previous_hash;
        $this->price                    = $price;
        $this->discount                 = $discount;
        $this->tax                      = $tax;
        $this->total                    = $total;
        $this->invoice_items            = $invoice_items;
        $this->tax_percent              = $tax_percent;
        $this->delivery_date            = $delivery_date ?? $invoice_date;
    }

==============================================================================================================
FILE=fatoora-zatca/src/Objects/Seller.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Objects;
class Seller

------------------------------------------------------------------------------------------
METHOD=__construct
------------------------------------------------------------------------------------------
    public function __construct(
        string $registration_number,
        string $street_name,
        string $building_number,
        string $plot_identification,
        string $city_sub_division,
        string $city,
        string $postal_number,
        string $tax_number,
        string $registration_name,
        string $private_key,
        string $certificate,
        string $secret,
        string $country = 'SA'
    )
    {
        $this->registration_number          = $registration_number;
        $this->street_name                  = $street_name;
        $this->building_number              = $building_number;
        $this->plot_identification          = $plot_identification;
        $this->city_sub_division            = $city_sub_division;
        $this->city                         = $city;
        $this->country                      = $country;
        $this->postal_number                = $postal_number;
        $this->tax_number                   = $tax_number;
        $this->registration_name            = $registration_name;
        $this->private_key                  = $private_key;
        $this->certificate                  = $certificate;
        $this->secret                       = $secret;
    }

==============================================================================================================
FILE=fatoora-zatca/src/Objects/Client.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Objects;
class Client

------------------------------------------------------------------------------------------
METHOD=__construct
------------------------------------------------------------------------------------------
    public function __construct(
        string $registration_name,
        string $tax_number,
        string $postal_number,
        string $street_name,
        string $building_number,
        string $plot_identification,
        string $city_subdivision_name,
        string $city,
        string $country = 'SA',
        string $registration_number = ''
    )
    {
        $this->street_name              = $street_name;
        $this->building_number          = $building_number;
        $this->plot_identification      = $plot_identification;
        $this->city_subdivision_name    = $city_subdivision_name;
        $this->city                     = $city;
        $this->country                  = $country;
        $this->postal_number            = $postal_number;
        $this->tax_number               = $tax_number;
        $this->registration_name        = $registration_name;
        $this->registration_number      = $registration_number;
    }

==============================================================================================================
FILE=fatoora-zatca/src/Classes/DocumentType.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca\Classes;
class DocumentType

TARGET_METHODS_FOUND=NO

==============================================================================================================
FILE=fatoora-zatca/src/Zatca.php
==============================================================================================================
FILE_FOUND=YES
namespace Bl\FatooraZatca;
use Bl\FatooraZatca\Classes\DocumentType;
use Bl\FatooraZatca\Helpers\ConfigHelper;
use Bl\FatooraZatca\Objects\Client;
use Bl\FatooraZatca\Objects\Invoice;
use Bl\FatooraZatca\Objects\Seller;
use Bl\FatooraZatca\Objects\Setting;
use Bl\FatooraZatca\Services\ReportInvoiceService;
use Bl\FatooraZatca\Services\SettingService;
class Zatca

TARGET_METHODS_FOUND=NO

=== CALCULATE CALL SITES ===

FILE=fatoora-zatca/src/Services/ReportInvoiceService.php
97: $calculateInvoice = $this->calculate($document_type);

FILE=fatoora-zatca/src/Zatca.php
37: return (new ReportInvoiceService($seller, $invoice, $client))->test(DocumentType::STANDARD);
50: return (new ReportInvoiceService($seller, $invoice, $client))->clearance();
63: return (new ReportInvoiceService($seller, $invoice, $client))->test(DocumentType::SIMPILIFIED);
76: return (new ReportInvoiceService($seller, $invoice, $client))->reporting();
89: return (new ReportInvoiceService($seller, $invoice, $client))->calculate(DocumentType::SIMPILIFIED);

FILE=app/Http/Controllers/Api/V1/InvoiceController.php
105: $totals = $calculator->calculate(

FILE=app/Services/Mobile/CreateSalesInvoiceService.php
196: $totals = $this->calculator->calculate(

FILE=app/Services/Mobile/CreateSalesReturnService.php
249: $totals = $this->calculator->calculate(

FILES_CHANGED=NO
DATABASE_CHANGED=NO
ZATCA_REQUEST_SENT=NO