I really need help in this I am stuck please someone help me in resolving this issue.
I am implementing the Invoice Compliance API, including the QR code for simplified invoices, in Node.js and testing it with the ZATCA sandbox. However, I keep encountering an “INVALID QR CODE FORMAT” error.
API Endpoint: https://gw-fatoora.zatca.gov.sa/e-invoicing/developer-portal/compliance/invoices
Below is the screenshot of the error I am getting:
Interestingly, when I scan the QR code using the E-Invoice QR scanner app from the Play Store, it indicates that the QR code is compatible with Phase 2. I’ve included a screenshot of this response.
I’m not using an SDK for this implementation. Below I am attaching my code for generating the QR code, which follows the exact approach provided in ZATCA’s documentation. I’ve also attached the link to the documentation for reference.
const encodeTLV = function(tag, value) {
// Directly use the tag without converting it to hexadecimal
const tagBuffer = Buffer.from([Number(tag)],"utf8"); // Directly converting to number, not hex
// Convert the value to a buffer (binary/hex representation)
const valueBuffer = Buffer.from(value, "utf8");
// The length of the value in bytes
const lengthBuffer = Buffer.from([valueBuffer.length],"utf8");
// Concatenate the tag, length, and value buffers to form the TLV structure
return Buffer.concat([tagBuffer, lengthBuffer, valueBuffer]);
};
const generateQR = ({
invoice_xml, // Canonicalized XML string
digital_signature,
public_key,
certificate_signature,
invoice_hash
}) => {
try {
// Parse the canonicalized XML string into a DOM object
const xml_dom = new xmldom.DOMParser().parseFromString(invoice_xml);
// Define namespaces used in the XML for XPath queries
const namespaces = {
cac: 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
cbc: 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2'
};
const select = xpath.useNamespaces(namespaces);
// Extract the necessary elements from the XML using XPath
let seller_name = select(
"//cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cbc:RegistrationName/text()",
xml_dom
)[0]?.nodeValue;
let VAT_number = select(
"//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID/text()",
xml_dom
)[0]?.nodeValue;
const invoice_total = select(
"//cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount/text()",
xml_dom
)[0]?.nodeValue;
const VAT_total = select(
"//cac:TaxTotal/cbc:TaxAmount/text()",
xml_dom
)[0]?.nodeValue;
const issue_date = select("//cbc:IssueDate/text()", xml_dom)[0]?.nodeValue;
const issue_time = select("//cbc:IssueTime/text()", xml_dom)[0]?.nodeValue;
// Combine date and time and format to ISO 8601
const datetime = `${issue_date}T${issue_time}`;
const formatted_datetime =
moment(datetime).format("YYYY-MM-DDTHH:mm:ss") + "Z"
const digi_buff = Buffer.from(digital_signature);
// Prepare the QR code TLV (Tag-Length-Value)
const tlvSegments = [
encodeTLV("01", seller_name),
encodeTLV("02", VAT_number),
encodeTLV("03", formatted_datetime),
encodeTLV("04", invoice_total),
encodeTLV("05", VAT_total),
encodeTLV("06", invoice_hash),
encodeTLV("07", digi_buff),
encodeTLV("08", public_key),
encodeTLV("09", certificate_signature),
];
// Use Buffer.concat with the array of TLV segments
const qr_tlv = Buffer.concat(tlvSegments);
return qr_tlv.toString("base64"); // Convert TLV to base64 and return it
} catch (error) {
console.error("Error generating QR:", error.message);
throw error;
}
};
This is one of the sample QR generated from this code
AQt4eXkgcHZ0IGx0ZAIPMzAwMDU2MTg2NzAwMDAzAxQyMDI0LTA5LTIwVDEwOjI4OjQ2WgQGMTAzLjE5BQU1NS4xOQYsc1JSdFVOYTU0azJhNUJYUkVKejN5ajdkK1dOZ0NCMVkvRDNGRTVBWWVPaz0H7E1UazBMREUzTnl3eU1Dd3hNRGtzT0RBc01UazFMREUxTUN3eE9UUXNNVGcxTERFNU5Td3hOaklzTnpjc01UazBMREUxTkN3eE9UVXNNVFkwTERJeExERTVOU3d4TkRVc01UWXNNVGswTERFMU5pd3hPVFVzTVRnekxERTVOU3d4TXpnc05qSXNNVGsxTERFMU55d3hPVFVzTVRnMUxEazVMRGsyTERnc01qa3NPRGdzTVRrMUxERTRPQ3cyTVN3eE9UVXNNVE16TERFNUxERTVOQ3d4TkRRc01qUXNNVEl3TERFNU5Td3hOams9CFgwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAQl7q+hlHxWm2j/n9dLHTPrO0PbWpKGL0l3pUIhFnlpa4m0czR7YbSc65he72V8uqc9vu2FKX3ahOX/pCjaBYKGCUgwRgIhAOmAfixZwoOWBtYmxtWUSMxKqu2v7F40yk34R0D9PlYPAiEA9qk2YEDI7R6EoMOLq5oww7wLRoDZ9MTsoiZoT9l+c1s=
Below is the UBL generated
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="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:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionURI>urn:oasis:names:specification:ubl:dsig:enveloped:xades</ext:ExtensionURI>
<ext:ExtensionContent>
<sig:UBLDocumentSignatures xmlns:sig="urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2" xmlns:sac="urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2" xmlns:sbc="urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2">
<sac:SignatureInformation>
<cbc:ID>urn:oasis:names:specification:ubl:signature:1</cbc:ID>
<sbc:ReferencedSignatureID>urn:oasis:names:specification:ubl:signature:Invoice</sbc:ReferencedSignatureID>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="signature">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
<ds:Reference Id="invoiceSignedData" URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<ds:XPath>not(//ancestor-or-self::ext:UBLExtensions)</ds:XPath>
</ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<ds:XPath>not(//ancestor-or-self::cac:Signature)</ds:XPath>
</ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<ds:XPath>not(//ancestor-or-self::cac:AdditionalDocumentReference[cbc:ID='QR'])</ds:XPath>
</ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>sRRtUNa54k2a5BXREJz3yj7d+WNgCB1Y/D3FE5AYeOk=</ds:DigestValue>
</ds:Reference>
<ds:Reference Type="http://www.w3.org/2000/09/xmldsig#SignatureProperties" URI="#xadesSignedProperties">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>TbeLb+FN0V3f8M50tMtMYonJBqCfRtqpwV4EoxqyCig=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>MTk0LDE3NywyMCwxMDksODAsMTk1LDE1MCwxOTQsMTg1LDE5NSwxNjIsNzcsMTk0LDE1NCwxOTUsMTY0LDIxLDE5NSwxNDUsMTYsMTk0LDE1NiwxOTUsMTgzLDE5NSwxMzgsNjIsMTk1LDE1NywxOTUsMTg1LDk5LDk2LDgsMjksODgsMTk1LDE4OCw2MSwxOTUsMTMzLDE5LDE5NCwxNDQsMjQsMTIwLDE5NSwxNjk=</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICGDCCAb2gAwIBAgIGAZIialv6MAoGCCqGSM49BAMCMBUxEzARBgNVBAMMCmVJbnZvaWNpbmcwHhcNMjQwOTI0MDUwNDAzWhcNMjkwOTIzMjEwMDAwWjBEMQ4wDAYDVQQDDAVQT1MtMTEPMA0GA1UECwwGUml5YWRoMRQwEgYDVQQKDAt4eXkgcHZ0IGx0ZDELMAkGA1UEBhMCU0EwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAQl7q+hlHxWm2j/n9dLHTPrO0PbWpKGL0l3pUIhFnlpa4m0czR7YbSc65he72V8uqc9vu2FKX3ahOX/pCjaBYKGo4HMMIHJMAwGA1UdEwEB/wQCMAAwgbgGA1UdEQSBsDCBraSBqjCBpzE/MD0GA1UEBAw2MS14eXl8Mi14eXl8My1lZDIyZjFkOS1lNmEyLTExMjgtOWI1OC1kOWE4ZjExZTQ0ZXdyNTNyMR8wHQYKCZImiZPyLGQBAQwPMzAwMDU2MTg2NzAwMDAzMQ0wCwYDVQQMDAQxMTAwMSQwIgYDVQQaDBswMDAwIEtpbmcgRmFoYWhkIHN0LCBSaXlhZGgxDjAMBgNVBA8MBUNpdmlsMAoGCCqGSM49BAMCA0kAMEYCIQDpgH4sWcKDlgbWJsbVlEjMSqrtr+xeNMpN+EdA/T5WDwIhAPapNmBAyO0ehKDDi6uaMMO8C0aA2fTE7KImaE/ZfnNb</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object>
<xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="signature">
<xades:SignedProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="xadesSignedProperties">
<xades:SignedSignatureProperties>
<xades:SigningTime>2024-09-24T05:04:09.748Z</xades:SigningTime>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>NzVlM2E3ZDJiZmMzOTNlOGZhYmIzOTkzOGZjYzdjNDM3MzBjNWJiMjAwZmUwODk1M2UxOTYzYTZmMDg5ZjljMg==</ds:DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<ds:X509IssuerName>CN=eInvoicing</ds:X509IssuerName>
<ds:X509SerialNumber>1727154248698</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:ProfileID>reporting:1.0</cbc:ProfileID>
<cbc:ID>EGS1-886431145-1</cbc:ID>
<cbc:UUID>6f4d20e0-6bfe-4a80-9389-7dabe6620f12</cbc:UUID>
<cbc:IssueDate>2024-09-20</cbc:IssueDate>
<cbc:IssueTime>10:28:46</cbc:IssueTime>
<cbc:InvoiceTypeCode name="0200000">388</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>SAR</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>SAR</cbc:TaxCurrencyCode>
<cac:AdditionalDocumentReference>
<cbc:ID>ICV</cbc:ID>
<cbc:UUID>1</cbc:UUID>
</cac:AdditionalDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>PIH</cbc:ID>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="text/plain">NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>QR</cbc:ID>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="text/plain">AQt4eXkgcHZ0IGx0ZAIPMzAwMDU2MTg2NzAwMDAzAxQyMDI0LTA5LTIwVDEwOjI4OjQ2WgQGMTAzLjE5BQU1NS4xOQYsc1JSdFVOYTU0azJhNUJYUkVKejN5ajdkK1dOZ0NCMVkvRDNGRTVBWWVPaz0H7E1UazBMREUzTnl3eU1Dd3hNRGtzT0RBc01UazFMREUxTUN3eE9UUXNNVGcxTERFNU5Td3hOaklzTnpjc01UazBMREUxTkN3eE9UVXNNVFkwTERJeExERTVOU3d4TkRVc01UWXNNVGswTERFMU5pd3hPVFVzTVRnekxERTVOU3d4TXpnc05qSXNNVGsxTERFMU55d3hPVFVzTVRnMUxEazVMRGsyTERnc01qa3NPRGdzTVRrMUxERTRPQ3cyTVN3eE9UVXNNVE16TERFNUxERTVOQ3d4TkRRc01qUXNNVEl3TERFNU5Td3hOams9CFgwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAQl7q+hlHxWm2j/n9dLHTPrO0PbWpKGL0l3pUIhFnlpa4m0czR7YbSc65he72V8uqc9vu2FKX3ahOX/pCjaBYKGCUgwRgIhAOmAfixZwoOWBtYmxtWUSMxKqu2v7F40yk34R0D9PlYPAiEA9qk2YEDI7R6EoMOLq5oww7wLRoDZ9MTsoiZoT9l+c1s=</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:Signature>
<cbc:ID>urn:oasis:names:specification:ubl:signature:Invoice</cbc:ID>
<cbc:SignatureMethod>urn:oasis:names:specification:ubl:dsig:enveloped:xades</cbc:SignatureMethod>
</cac:Signature>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID schemeID="CRN">3000551844</cbc:ID>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>King Fahahd st</cbc:StreetName>
<cbc:BuildingNumber>0000</cbc:BuildingNumber>
<cbc:PlotIdentification>0000</cbc:PlotIdentification>
<cbc:CitySubdivisionName>West</cbc:CitySubdivisionName>
<cbc:CityName>Riyadh</cbc:CityName>
<cbc:PostalZone>31952</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>SA</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>300056186700003</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>xyy pvt ltd</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PostalAddress>
<cbc:BuildingNumber>1234</cbc:BuildingNumber>
<cbc:CitySubdivisionName>West</cbc:CitySubdivisionName>
<cbc:CityName>Dammam</cbc:CityName>
<cbc:PostalZone>12313</cbc:PostalZone>
<cbc:District>Riyadh</cbc:District>
<cac:Country>
<cbc:IdentificationCode>SA</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Zahid Gani</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">55.19</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="SAR">48.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="SAR">7.19</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5305">S</cbc:ID>
<cbc:Percent>15.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5153">VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="SAR">48.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="SAR">48.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5305">S</cbc:ID>
<cbc:Percent>15.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5153">VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">55.19</cbc:TaxAmount>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="SAR">48.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="SAR">48.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="SAR">103.19</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="SAR">0</cbc:AllowanceTotalAmount>
<cbc:PrepaidAmount currencyID="SAR">0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="SAR">103.19</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="PCE">5</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="SAR">48.00</cbc:LineExtensionAmount>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">55.19</cbc:TaxAmount>
<cbc:RoundingAmount currencyID="SAR">103.19</cbc:RoundingAmount>
</cac:TaxTotal>
<cac:Item>
<cbc:Name>TEST NAME</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>15.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>15.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="SAR">10</cbc:PriceAmount>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReason>A discount</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="SAR">2.00</cbc:Amount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
</Invoice>