Dear ZATCA Technical Support Team,
I am integrating Standard Tax Invoices (B2B) using the ZATCA .NET SDK v3.4.6 in the Simulation Environment. We are submitting invoices through the Reporting API (POST /e-invoicing/simulation/invoices/reporting/single) as documented by ZATCA. Our invoice XML is generated according to UBL 2.1, including Header, AdditionalDocumentReference (ICV and PIH only), Supplier, Customer, Delivery, PaymentMeans, TaxTotals, LegalMonetaryTotal and InvoiceLines. The QR element is intentionally not generated manually because it is inserted later by the SDK during the signing process. The certificate (PCSID) and private key were successfully issued by ZATCA, the certificate is stored in Base64 DER format exactly as received from ZATCA, and the private key is stored as Base64(PEM). We sign the invoice using EInvoiceSigner.SignDocument() from SDK 3.4.6. During debugging, we confirmed that the invoice hash generated by GenerateHashMiddleware is identical to the hash used by GenerateSignatureMiddleware; however, after SignDocument() completes, regenerating the invoice hash using EInvoiceHashGenerator produces a different value. Consequently, EInvoiceValidator.ValidateEInvoice() returns the following signature validation errors: hashedXml, invoiceSignedDataDigestValue, and signatureValue. We have thoroughly reviewed our implementation and verified XML generation, tax calculations, legal monetary totals, invoice lines, QR generation, PIH, CSR, certificate parsing, canonicalization, XSL transformation, and hash generation. We also reviewed the SDK internals and observed that after the signature is generated, the SDK executes TransformXMLResultMiddleware, which reloads the XML using LoadXml(), followed by FinalizeSignDocumentMiddleware, which modifies InnerXml before returning the signed document. We would appreciate your clarification on whether this behavior is expected in SDK 3.4.6, whether it has been corrected in SDK 3.4.8, whether the invoice hash is expected to change after SignDocument() completes, and whether there are any additional requirements for Standard Tax Invoice signing that are not documented. We would also appreciate it if you could confirm the recommended signing sequence for Standard Tax Invoices using the .NET SDK. For reference, we are using the Simulation Reporting API documented by ZATCA: https://zatcaapidocs.evinciblesolutions.com/reference/post_invoices-reporting-single
“The SDK generates hash A before signing, uses hash A inside SignedInfo, but after SignDocument() the SDK itself regenerates hash B from the returned SignedEInvoice. Could you clarify whether this behavior is expected?”
Thank you for your support.