I have some errors while submitting a sample invoice to get my production CSID

Hello Team,
I have some errors while submitting a sample invoice to get my production CSID.
I’m using php code to manually generate the QR. I mean I don’t use the SDK.
I will attach the errors along with the function that generate the QR.

“errorMessages”:[
{
“type”:“ERROR”,
“code”:“invalid-invoice-hash”,
“category”:“INVOICE_HASHING_ERRORS”,
“message”:“The invoice hash API body does not match the (calculated) Hash of the XML”,
“status”:“ERROR”
},
{
“type”:“ERROR”,
“code”:“CERTIFICATE_SIGNATURE_QRCODE_INVALID”,
“category”:“QRCODE_VALIDATION”,
“message”:“certificate signature does not match with qr certificate signature value”,
“status”:“ERROR”
},
{
“type”:“ERROR”,
“code”:“signed-properties-hashing”,
“category”:“CERTIFICATE_ERRORS”,
“message”:“Invalid signed properties hashing, SignedProperties with id=‘xadesSignedProperties’”,
“status”:“ERROR”
}
],

public function generateQR(DOMDocument $invoice_xml, string $digital_signature, string $public_key, string $signature, string $invoice_timestamp, string $invoice_hash): string
{
$doc = $invoice_xml;

    // Get seller data
    $seller_name = $doc->getElementsByTagName('RegistrationName')[0]->textContent;
    $VAT_number = $doc->getElementsByTagName('CompanyID')[0]->textContent;
    
    // Get amounts
    $invoice_total = $doc->getElementsByTagName('TaxInclusiveAmount')[0]->textContent;
    $VAT_total = '0.00';
    if ($tax_total = $doc->getElementsByTagName('TaxTotal')[0]) {
        $VAT_total = $tax_total->getElementsByTagName('TaxAmount')[0]->textContent;
    }

    // Ensure consistent number formatting
    $invoice_total = number_format((float)$invoice_total, 2, '.', '');
    $VAT_total = number_format((float)$VAT_total, 2, '.', '');

    // Build TLV data in exact order
    $qr_data = [
        $seller_name,                    // Tag 1
        $VAT_number,                     // Tag 2
        $invoice_timestamp,              // Tag 3
        $invoice_total,                  // Tag 4
        $VAT_total,                      // Tag 5
        $invoice_hash,                   // Tag 6
        $digital_signature,              // Tag 7
        $public_key,                     // Tag 8
        $signature                       // Tag 9
    ];

    // Generate TLV
    $qr_tlv = $this->TLV($qr_data);
    
    // Ensure max length
    $qr_tlv = substr($qr_tlv, 0, 1000);
    
    return base64_encode($qr_tlv);
}

private function TLV(array $tags): string
{
    $tlv = '';
    foreach ($tags as $index => $value) {
        $tag = $index + 1;
        $length = strlen($value);
        $tlv .= pack('C', $tag) . pack('C', $length) . $value;
    }
    return $tlv;
}

Dear @abdullah

Thanks for reaching out, Welcome to our community.

Please find the
SigningProcessUpdated.pdf (927.7 KB)

Following the provided steps will help you to understanding the main functionalities of the Signing process, which will lead you to successfully implementing your own code.

Thanks,
Ibrahem Daoud.

Hello Dear,
Thank you for getting back to me.

Regarding the first error "The invoice hash API body does not match the (calculated) Hash of the XML” I believe I have followed the steps of the signing process at least generating the invoice hash which causing this error.

Let me send you the function that I use to do the invoice hash generation step and I will appreciate if you can help me finding what’s going wrong with it.

 public function getInvoiceHash(DOMDocument $invoice_xml): string
    {
        $pure_invoice_string = $this->getPureInvoiceString($invoice_xml);

        $pure_invoice_string = str_replace('<?xml version="1.0" encoding="UTF-8"?>' . "\n", '', $pure_invoice_string);

        // Canonicalize the Invoice using the C14N11 standard
        $document = new DOMDocument();
        $document->loadXML($pure_invoice_string);
        $canonicalized_invoice = $document->C14N(true, false);

        $hash = hash('sha256', $canonicalized_invoice);

        return base64_encode($hash);
    }

    private function getPureInvoiceString(DOMDocument $invoice_xml)
    {
        $document = new DOMDocument();
        $document->loadXML($invoice_xml->saveXML());

        $xpath = new DOMXPath($document);

        // Remove UBLExtensions
        foreach ($xpath->query("//*[local-name()='Invoice']//*[local-name()='UBLExtensions']") as $element) {
            $element->parentNode->removeChild($element);
        }

        // Remove Signature
        foreach ($xpath->query("//*[local-name()='Invoice']//*[local-name()='Signature']") as $element) {
            $element->parentNode->removeChild($element);
        }

        // Remove AdditionalDocumentReference with QR code
        foreach ($xpath->query("//*[local-name()='AdditionalDocumentReference'][cbc:ID[normalize-space(text()) = 'QR']]") as $element) {
            $element->parentNode->removeChild($element);
        }

        return $document->saveXML();
    }

I have checked the invoice string and the version was removed and all the mentioned tags was removed also.

I have printed the variables of the invoice hash after generation and right before sending it to the API body and they were identical same as the invoice hash that has been added to the invoice xml.

Thank you for your support