Request for Assistance in Resolving Invoice Hashing Issue

Dear,

I have followed the steps outlined below to generate the invoice XML and hash value for ZATCA compliance. However, I am encountering discrepancies in the output and kindly request your assistance in reviewing the process. Please let me know if any modifications or additional steps are required to resolve the issue.

The steps I followed are:

  1. Generate CSR & private key using the following code:
  2. Generate CSID (ZATCA Compliance Portal)
  3. Canonicalize the XML (C14N11)
  4. Generate SHA-256 Hash of the Canonicalized XML
  5. Sign the Hash using the Company’s Private Key
  6. Encode the Signature in Base64
  7. Embed the Signature in the Invoice XML
  8. Submit to Invoice Compliance API (ZATCA API)

Would you kindly assist us in resolving this issue.??

Can you provide the SDK Version, Programming Language & Share the XML.

Using PHP programming Language.

<ns10:Invoice xmlns:ns10=“urn:oasis:names:specification:ubl:schema:xsd:Invoice-2” xmlns:cac=“urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2” xmlns:cbc=“urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2” xmlns:ds=“XML-Signature Syntax and Processing” xmlns:ext=“urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2” xmlns:sac=“urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2” xmlns:sbc=“urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2” xmlns:sig=“urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2” xmlns:xades=“Assigned ETSI XML URIs”>

ext:UBLExtensions

ext:UBLExtension

ext:ExtensionURIurn:oasis:names:specification:ubl:dsig:enveloped:xades</ext:ExtensionURI>

ext:ExtensionContent

sig:UBLDocumentSignatures

sac:SignatureInformation

cbc:IDurn:oasis:names:specification:ubl:signature:1</cbc:ID>

sbc:ReferencedSignatureIDurn:oasis:names:specification:ubl:signature:Invoice</sbc:ReferencedSignatureID>

<ds:Signature Id=“signature”>

ds:SignedInfo

<ds:CanonicalizationMethod Algorithm=“Canonical XML 1.1”/>

<ds:SignatureMethod Algorithm=“xmldsig-more namespace”/>

<ds:Reference Id=“invoiceSignedData” URI=“”>

ds:Transforms

<ds:Transform Algorithm=“XML Path Language (XPath)”>

ds:XPathnot(//ancestor-or-self::ext:UBLExtensions)</ds:XPath>

</ds:Transform>

<ds:Transform Algorithm=“XML Path Language (XPath)”>

ds:XPathnot(//ancestor-or-self::cac:Signature)</ds:XPath>

</ds:Transform>

<ds:Transform Algorithm=“XML Path Language (XPath)”>

ds:XPathnot(//ancestor-or-self::cac:AdditionalDocumentReference[cbc:ID=‘QR’])</ds:XPath>

</ds:Transform>

<ds:Transform Algorithm=“Canonical XML 1.1”/>

</ds:Transforms>

<ds:DigestMethod Algorithm=“XML Encryption Syntax and Processing”/>

ds:DigestValueZGViNTYzN2U5YWRmZmI3MWIyMzg5OGQzZmIzYWFhNjQ4MmYyODg1YTliNzVhY2JjMWE5ZmI1NDJjZGY2NzdhZg==</ds:DigestValue>

</ds:Reference>

<ds:Reference Type=“XML-Signature Syntax and Processing” URI=“#xadesSignedProperties”>

<ds:DigestMethod Algorithm=“XML Encryption Syntax and Processing”/>

ds:DigestValue3YAoquDC3a454aPyHqnDeRtkEW2N+8GrhKWm708H3X4=</ds:DigestValue>

</ds:Reference>

</ds:SignedInfo>

ds:SignatureValueMEUCIC8FvfSrutvKatmGueI+0Ni+9LZ4atrZO8VPWnkbYENxAiEAliIRFEUZy1IG0lr8o9bz8tWPqFUc+9I6U1vNGZ7BKeE=</ds:SignatureValue>

ds:KeyInfo

ds:X509Data

ds:X509CertificateMIICKjCCAdCgAwIBAgIGAZS4GXTJMAoGCCqGSM49BAMCMBUxEzARBgNVBAMMCmVJbnZvaWNpbmcwHhcNMjUwMTMwMTY0NDE4WhcNMzAwMTI5MjEwMDAwWjBoMR4wHAYDVQQDDBVlbGFiZXJwLnNldHJhZGVlei5jb20xFjAUBgNVBAsMDVJpeWFkaCBCcmFuY2gxITAfBgNVBAoMGFN5c3RlbXMgRXhwZXJ0IENvIGZvciBJVDELMAkGA1UEBhMCU0EwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAQ/pz+FnoSMN9O8rnVUmR/1tSygbBisjHdgtyM3ftvZb5b/Jb3f5w+blpGw85ss/JNFKQQ6d/t32SB5cQKsvYB+o4G7MIG4MAwGA1UdEwEB/wQCMAAwgacGA1UdEQSBnzCBnKSBmTCBljE7MDkGA1UEBAwyMS1lbGFiZXJwLnNldHJhZGVlei5jb218Mi1FR1MtWDEwMHwzLTRHREpBNTQ1NjQ1NkQxHzAdBgoJkiaJk/IsZAEBDA8zMTEwNjg2MTQ2MDAwMDMxDTALBgNVBAwMBDExMDAxDzANBgNVBBoMBlJpeWFkaDEWMBQGA1UEDwwNSVQgRGVwYXJ0bWVudDAKBggqhkjOPQQDAgNIADBFAiEAtP/Bd9k+XyQd9BWKvg9mLhnj80bOxHKugTnvPjl/zI4CICT5lBz+U8yD07exspKArVqn/zqEQXFJxTaObywDvwl2</ds:X509Certificate>

</ds:X509Data>

</ds:KeyInfo>

ds:Object

<xades:QualifyingProperties xmlns:xades=“Assigned ETSI XML URIs” Target=“signature”>

<xades:SignedProperties Id=“xadesSignedProperties”>

xades:SignedSignatureProperties

xades:SigningTime2025-02-04T10:06:40Z</xades:SigningTime>

xades:SigningCertificate

xades:Cert

xades:CertDigest

<ds:DigestMethod Algorithm=“XML Encryption Syntax and Processing”/>

ds:DigestValueYzJkYmE4ZjE0YzBmN2JhZjhmYTZlMjVjYzgxMDQ2MGIzOWM0YzJkNjU3ZTE3NDBjMjFhODRmMzhlY2Q0NTllMw==</ds:DigestValue>

</xades:CertDigest>

xades:IssuerSerial

ds:X509IssuerNameCN=eInvoicing,DC=extgazt, DC=gov, DC=local</ds:X509IssuerName>

ds:X509SerialNumber1738255463625</ds:X509SerialNumber>

</xades:IssuerSerial>

</xades:Cert>

</xades:SigningCertificate>

</xades:SignedSignatureProperties>

</xades:SignedProperties>

</xades:QualifyingProperties>

</ds:Object>

</ds:Signature>

</sac:SignatureInformation>

</sig:UBLDocumentSignatures>

</ext:ExtensionContent>

</ext:UBLExtension>

</ext:UBLExtensions>

cbc:ProfileIDreporting:1.0</cbc:ProfileID>

cbc:IDSALE26719</cbc:ID>

cbc:UUID19de0aea-5973-4b58-81f2-73b25b9580e0</cbc:UUID>

cbc:IssueDate2025-01-31</cbc:IssueDate>

cbc:IssueTime11:29:00</cbc:IssueTime>

<cbc:InvoiceTypeCode name=“0100000”>388</cbc:InvoiceTypeCode>

cbc:DocumentCurrencyCodeSAR</cbc:DocumentCurrencyCode>

cbc:TaxCurrencyCodeSAR</cbc:TaxCurrencyCode>

cac:AdditionalDocumentReference

cbc:IDICV</cbc:ID>

cbc:UUID1</cbc:UUID>

</cac:AdditionalDocumentReference>

cac:AdditionalDocumentReference

cbc:IDPIH</cbc:ID>

cac:Attachment

<cbc:EmbeddedDocumentBinaryObject mimeCode=“text/plain”>NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==</cbc:EmbeddedDocumentBinaryObject>

</cac:Attachment>

</cac:AdditionalDocumentReference>

cac:AdditionalDocumentReference

cbc:IDQR</cbc:ID>

cac:Attachment

<cbc:EmbeddedDocumentBinaryObject mimeCode=“text/plain”>ARNBTCBBU1NJIFRSQURJTkcgRVNUAg8zMTEwNjg2MTQ2MDAwMDMDFDIwMjUtMDEtMzFUMTE6Mjk6MDBaBAUyOC4wMAUEMy42NQZYWkdWaU5UWXpOMlU1WVdSbVptSTNNV0l5TXpnNU9HUXpabUl6WVdGaE5qUTRNbVl5T0RnMVlUbGlOelZoWTJKak1XRTVabUkxTkRKalpHWTJOemRoWmc9PQdgTUVVQ0lDOEZ2ZlNydXR2S2F0bUd1ZUkrME5pKzlMWjRhdHJaTzhWUFdua2JZRU54QWlFQWxpSVJGRVVaeTFJRzBscjhvOWJ6OHRXUHFGVWMrOUk2VTF2TkdaN0JLZUU9CFgwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAQ/pz+FnoSMN9O8rnVUmR/1tSygbBisjHdgtyM3ftvZb5b/Jb3f5w+blpGw85ss/JNFKQQ6d/t32SB5cQKsvYB+CUcwRQIhALT/wXfZPl8kHfQVir4PZi4Z4/NGzsRyroE57z45f8yOAiAk+ZQc/lPMg9O3sbKSgK1ap/86hEFxScU2jm8sA78Jdg==</cbc:EmbeddedDocumentBinaryObject>

</cac:Attachment>

</cac:AdditionalDocumentReference>

cac:Signature

cbc:IDurn:oasis:names:specification:ubl:signature:Invoice</cbc:ID>

cbc:SignatureMethodurn:oasis:names:specification:ubl:dsig:enveloped:xades</cbc:SignatureMethod>

</cac:Signature>

cac:AccountingSupplierParty

cac:Party

cac:PartyIdentification

<cbc:ID schemeID=“CRN”>1234653499</cbc:ID>

</cac:PartyIdentification>

cac:PostalAddress

cbc:StreetNameMuhayil</cbc:StreetName>

cbc:AdditionalStreetNameMuhayil</cbc:AdditionalStreetName>

cbc:BuildingNumber1234</cbc:BuildingNumber>

cbc:PlotIdentification١٢٣٤</cbc:PlotIdentification>

cbc:CitySubdivisionNameMuhayil</cbc:CitySubdivisionName>

cbc:CityNameMuhayil</cbc:CityName>

cbc:PostalZone12345</cbc:PostalZone>

cbc:CountrySubentitySaudi Arabia</cbc:CountrySubentity>

cac:Country

cbc:IdentificationCodeSA</cbc:IdentificationCode>

</cac:Country>

</cac:PostalAddress>

cac:PartyTaxScheme

cbc:CompanyID311068614600003</cbc:CompanyID>

cac:TaxScheme

cbc:IDVAT</cbc:ID>

</cac:TaxScheme>

</cac:PartyTaxScheme>

cac:PartyLegalEntity

cbc:RegistrationNameAL ASSI TRADING EST</cbc:RegistrationName>

</cac:PartyLegalEntity>

</cac:Party>

</cac:AccountingSupplierParty>

cac:AccountingCustomerParty

cac:Party

cac:PartyIdentification

<cbc:ID schemeID=“CRN”>1234653499</cbc:ID>

</cac:PartyIdentification>

cac:PostalAddress

cbc:StreetNameReesh</cbc:StreetName>

cbc:AdditionalStreetNameReesh</cbc:AdditionalStreetName>

cbc:BuildingNumber1234</cbc:BuildingNumber>

cbc:PlotIdentification١٢٣٤</cbc:PlotIdentification>

cbc:CitySubdivisionNameMuhayil </cbc:CitySubdivisionName>

cbc:CityNameMuhayil </cbc:CityName>

cbc:PostalZone12345</cbc:PostalZone>

cbc:CountrySubentityKSA</cbc:CountrySubentity>

cac:Country

cbc:IdentificationCodeSA</cbc:IdentificationCode>

</cac:Country>

</cac:PostalAddress>

cac:PartyTaxScheme

cbc:CompanyID310726992900003</cbc:CompanyID>

cac:TaxScheme

cbc:IDVAT</cbc:ID>

</cac:TaxScheme>

</cac:PartyTaxScheme>

cac:PartyLegalEntity

cbc:RegistrationNameAbdul Malik Al Ahmari</cbc:RegistrationName>

</cac:PartyLegalEntity>

</cac:Party>

</cac:AccountingCustomerParty>

cac:Delivery

cbc:ActualDeliveryDate2025-01-31</cbc:ActualDeliveryDate>

</cac:Delivery>

cac:PaymentMeans

cbc:PaymentMeansCode30</cbc:PaymentMeansCode>

cbc:InstructionNoteReturned items</cbc:InstructionNote>

</cac:PaymentMeans>

cac:AllowanceCharge

cbc:ChargeIndicatorfalse</cbc:ChargeIndicator>

<cbc:Amount currencyID=“SAR”>0.00</cbc:Amount>

cac:TaxCategory

cbc:IDS</cbc:ID>

cbc:Percent15.00</cbc:Percent>

cac:TaxScheme

cbc:IDVAT</cbc:ID>

</cac:TaxScheme>

</cac:TaxCategory>

</cac:AllowanceCharge>

cac:TaxTotal

<cbc:TaxAmount currencyID=“SAR”>3.65</cbc:TaxAmount>

cac:TaxSubtotal

<cbc:TaxableAmount currencyID=“SAR”>24.35</cbc:TaxableAmount>

<cbc:TaxAmount currencyID=“SAR”>3.65</cbc:TaxAmount>

cac:TaxCategory

cbc:IDS</cbc:ID>

cbc:Percent15.00</cbc:Percent>

cac:TaxScheme

cbc:IDVAT</cbc:ID>

</cac:TaxScheme>

</cac:TaxCategory>

</cac:TaxSubtotal>

</cac:TaxTotal>

cac:TaxTotal

<cbc:TaxAmount currencyID=“SAR”>3.65</cbc:TaxAmount>

</cac:TaxTotal>

cac:LegalMonetaryTotal

<cbc:LineExtensionAmount currencyID=“SAR”>24.35</cbc:LineExtensionAmount>

<cbc:TaxExclusiveAmount currencyID=“SAR”>24.35</cbc:TaxExclusiveAmount>

<cbc:TaxInclusiveAmount currencyID=“SAR”>28.00</cbc:TaxInclusiveAmount>

<cbc:AllowanceTotalAmount currencyID=“SAR”>0.00</cbc:AllowanceTotalAmount>

<cbc:PayableAmount currencyID=“SAR”>28.00</cbc:PayableAmount>

</cac:LegalMonetaryTotal>

cac:InvoiceLine

cbc:ID293143</cbc:ID>

cbc:InvoicedQuantity4.0</cbc:InvoicedQuantity>

<cbc:LineExtensionAmount currencyID=“SAR”>24.35</cbc:LineExtensionAmount>

cac:TaxTotal

<cbc:TaxAmount currencyID=“SAR”>3.65</cbc:TaxAmount>

<cbc:RoundingAmount currencyID=“SAR”>28.00</cbc:RoundingAmount>

</cac:TaxTotal>

cac:Item

cbc:NameBathook</cbc:Name>

cac:ClassifiedTaxCategory

cbc:IDS</cbc:ID>

cbc:Percent15</cbc:Percent>

cac:TaxScheme

cbc:IDVAT</cbc:ID>

</cac:TaxScheme>

</cac:ClassifiedTaxCategory>

</cac:Item>

cac:Price

<cbc:PriceAmount currencyID=“SAR”>6.087</cbc:PriceAmount>

</cac:Price>

</cac:InvoiceLine>

</ns10:Invoice>

Dear @Cignes

Thank you for reaching out & welcome to the community.

Kindly note that you might receive this error when the invoice hash is not generated correctly for standard invoices, or the simplified invoices is not signed correctly. Therefore, you need to follow the generate hash process for standards invoices and signing process for simplified invoice. Moreover, kindly note that when you make any modification in the invoice you need to generate new hash or sign the invoice again.

You can find blow the processes using JAVA SDK:

you can generate the hash using this command:
Fatoora -generateHash -invoice “invoice.xml”
You will have to take the hash value from the CLI and replace the first digest value in the invoice with the new generated Hash.

Unlike standard tax invoice, simplified tax invoice & its associated notes must be signed with the taxpayer X.509 certificate (CSID), there are 2 returned X.509 certificates in the taxpayer’s EGS onboarding process.

First X.509 certificate: CCSID, which is returned after completing the first API (Compliance CSID), It’s returned as a security binary token which will be used as a username in the authorization, it’s also used as a signing certificate (X.509) after we decode it using base64 (we decode the binarysecurityToken) using base64 decoder and the output is the X.509 certificate, we use this certificate to sign the simplified tax invoices in the compliance invoice API (Compliance checks phase).

Second X.509 Certificate: PCSID, which is returned after completing the third API on the onboarding process (Production CSID), it’s also returned as a binary security token, and will be used as the username in te authorization for both reporting & clearance API, it’s also used as a signing certificate (X.509) after we decode it using base64 (we decode the binarysecurityToken) using base64 decoder and the output is the X.509 certificate, we use this certificate to sign the simplified tax invoices in the reporting API.

Please refer to the steps of manual signing using ZATCA’s JAVA SDK below:

After sending the CSR in the Compliance request CSID API, a Binarytoken & secret will be returned

Take the Binarytoken output, and decode it using base64 decoder, the decoded value is the x.509 certificate

Go to the SDK file to the following path: SDK/Data/Certificates/Cert.pem

Replace the value with your obtained x.509 certificate

Go to the SDK and use the command: fatoora -sign -invoice “invoice.xml”

Now the invoice will be signed & can be submitted successfully in the compliance checks phase (Compliance invoice API)

Redo the same steps above with the returned PCSID from the third API in the onboarding process and sign your simplified tax invoices with before sending to Reporting API

If you are implementing the signing process in your own code, please refer to This document:
SigningProcessUpdated.pdf

If you still require any further assistance, please do not hesitate to reach out to our support team via below email:
sp_support@zatca.gov.sa

Thank you.

Dear @saalotaibi
We are generating a signed invoice and have noticed that when we use the hash value produced by the SDK, the API call to the following endpoint
https://gw-apic-gov.gazt.gov.sa/e-invoicing/developer-portal/compliance/invoices
(with the generated hash, UUID, and the Base64 encoded invoice) returns a successful response.
However, when we generate the hash using our PHP code as follows:
$sha256HashBinary = hash(‘sha256’, $canonicalXmls, true); // Use binary format
$base64Hashs = base64_encode($sha256HashBinary);
the API returns an error stating:
“The invoice hash API body does not match the (calculated) Hash of the XML.”
This indicates that the hash value calculated using our PHP code does not match the hash that the ZATCA system expects.

We suspect the discrepancy may be due to differences in the canonicalization process (C14N11) or the specific transforms applied to the signed invoice XML before the hash is calculated. The SDK likely applies certain transformations or excludes specific elements (for example, digital signature blocks or extra whitespace) which our PHP canonicalization (using DOMDocument::C14N(true, false)) might not replicate exactly.

Could you please advise on the following:

Are there any additional transforms or exclusions (e.g., removal of the digital signature block) that must be applied to the signed invoice XML before calculating the hash?
Is there a recommended method or set of parameters for the canonicalization process (C14N11) to ensure that the PHP-generated hash matches the SDK’s generated hash?
We appreciate any guidance you can provide to help us resolve this discrepancy and ensure our PHP implementation produces a hash value consistent with the ZATCA SDK.

Thank you for your support and prompt attention to this matter.

Dear @Cignes

Thank you for reaching out & welcome to the community.

Our recommendation is following the below steps in the hash & the signed properties tags.

For more details on implementing the signing process within your own code, please refer to the SigningProcessUpdated.pdf document.

Thank you.