Temporary Suspension of ZatcaEGS Service

Dear ZatcaEGS users,

The ZatcaEGS service is temporarily suspended due to a significant issue. While data transmission works fine, writing data to the manager fails — and if left unresolved, this could lead to bigger problems.

There have been many changes in the manager application, and I need to take some time to study them in order to find the right solution. I apologize for the inconvenience and really appreciate your understanding!

Best regards,

Where exactly is the integration broken? Manager API has not changed.

After several attempts on the Desktop Edition, the server’s response writing to the manager was successful, without changing anything.

The ongoing issue is the view data that is not included in the relay. ZatcaEGS takes the Total value from that view to ensure that the Payment Total matches the Total on the invoice that will be printed. This causes the reported invoice to be approved but with a warning status.

The most likely step is to re-include the data view in the relay as before.

Then there is a script issue in the footer that is not being executed. ZatcaEGS stores a script to display the QRCode on the footer.

Another issue I encountered in ZatcaEGS is that users cannot onboard new businesses due to a change in rules from Zatca that causes the process of registering new businesses to fail.

I see. I forgot about this one. Fixed in the latest version (25.6.22.2424)

But now that people can literally have anything in View, until we find better solution, what exactly are you looking for in View so that I can guarantee it’s there.

Can you please copy/paste that script here? I will check what we do about that.

QrCodePhaseII footer

<script src="resources/qrcode/qrcode.js"></script>
<script id="qrCodeFooter">
  document.onreadystatechange = function () {
    if (document.readyState == "complete") {
      var qrCodeContent = '%%Base64 QRCode%%';

      function parseQRCodeContent(qrCodeBase64) {
        let details = new Map();
        try {
          let data = atob(qrCodeBase64.replace(/\+/g, '+'));
          let index = 0;
          while (index < data.length) {
            let tag = data.charCodeAt(index++);
            let length = data.charCodeAt(index++);
            let value = data.substr(index, length);
            index += length;
            let decodedValue = (tag === 8 || tag === 9)
              ? [...value].map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' ').toUpperCase()
              : new TextDecoder('utf-8').decode(new Uint8Array([...value].map(c => c.charCodeAt(0))));
            details.set(tag, [decodedValue]);
          }
        } catch (ex) {
          console.error("Error decoding QR code: " + ex.message);
        }
        return details;
      }

      function findParentTable(element) {
        while (element) {
          if (element.tagName === 'TABLE') return element;
          element = element.parentElement;
        }
        return null;
      }

      function insertQRCode(qrCodeContent) {
        const qrCodeCell = document.getElementById('qrcodecell');
        const qrCodeFooterDiv = document.getElementById('qrCodeFooter');

        if (qrCodeCell) {
          qrCodeCell.innerHTML = '<div id="signedQrCode" style="padding: 20px"></div>';
          renderQRCode(qrCodeContent, 'signedQrCode');
        } else if (qrCodeContent && qrCodeContent.length > 10) {
          const mainTable = findParentTable(qrCodeFooterDiv);
          if (!mainTable) {
            console.error('Parent table not found for the QR code.');
            return;
          }
          const newRow = mainTable.insertRow();
          const newCell = newRow.insertCell();
          newCell.colSpan = 99;
          newCell.innerHTML = '<div id="signedQrCode" style="padding: 20px"></div>';
          renderQRCode(qrCodeContent, 'signedQrCode');
        }
        removeElementById('qrcode');
      }

      function renderQRCode(content, elementId) {
        new QRCode(document.getElementById(elementId), {
          text: content,
          width: 160,
          height: 160,
          colorDark: "#000000",
          colorLight: "#fafafa",
          correctLevel: QRCode.CorrectLevel.L
        });

        let details = parseQRCodeContent(content);
        if (details.size > 0) {
          let title = Array.from(details)
            .map(([tag, value]) => `Tag ${tag} : ${value.join(', ')}`)
            .join('\n');
          const qrCodeDiv = document.getElementById(elementId);
          if (qrCodeDiv) {
            qrCodeDiv.title = title.trim();
          }
        }
      }

      function removeElementById(id) {
        const element = document.getElementById(id);
        if (element) element.remove();
      }

      insertQRCode(qrCodeContent);
    }
  };
</script>

Actually, the only value I need from the view is the total amount.

I use the view to retrieve the total displayed on the invoice.
When converting the invoice data to the ZATCA eInvoice format, rounding differences can sometimes lead to discrepancies.

To ensure that the total value in the eInvoice exactly matches the total on the original invoice, I use the total amount from the invoice directly and show the rounding difference separately, using the designated field provided in the eInvoice format.

I’m thinking what if we add into Manager new custom field type which would be image.

And then your integration just sets custom field value on invoice.

This would be better compatible with custom themes so that people can use AI to place the custom field and style it any way they like.

Yes, that can be done, but we still need a script to remove QR Phase I.

Meanwhile, I haven’t tried changing the Text CustomField from Type Paragraph to QRCode.

Let’s focus on making it work like before first, then we can improve.

In the latest version I made it so:

  1. Relay receives View HTML content and HTML contains element with id=Total which will make it easy to find total again. I’m not sure what method you’ve been using.
  2. Also just pushed another update (version 25.6.22.2428) so that Footers will execute scripts.

v25.6.22.2428
Reporting works well, but the Footer Script is not yet functioning.

I’m working on fixing that.

I made it work in the latest version (25.6.22.2429) but the way it works is too brittle on the inside.

You’ve done very good job to find the way to make e-invoicing work.

The next step is to make it work without footers and custom javascript. Basically custom field that you have

Base64 QRCode

Should really be enough. Once this custom field is populated, it’s up to custom theme that users have to present it. This will make it more flexible for users to move QR code around using new theme enhancer.

I’m not familiar with your integration but Base64 QRCode custom field. Does this custom field have the same GUID (aka Key) on every business that is using your integration?

Yes, all Custom fields have the same Key for all businesses.

The QRCode issue should be resolved by directly writing the QR Script to the Theme.

If using a Custom Theme, the user must perform a batch Update on the invoices that have been reported previously.

OK, that will make it easier to convert custom field using global upgrade script.

I’m trying to avoid all this because there is simpler way. We can achieve the same result without scripts. This will make the whole solution a lot more durable.

I will improve support in Manager so your custom field can be directly presented in themes without custom footer.

You may need an example of business data that has been integrated with ZatcaEGS in Sandbox Environment.
ZatcaEGS TEST.manager (64 KB)

We can create a new invoice by cloning an invoice that has been reported previously.

When I open your ZatcaEGS file, I can see QR code when viewing invoices. Does it mean the issue has been resolved in the latest version or do you still see issues?

I’m focusing on making this work again.

barcode disappear from invoice

QR not working

@Mostafa_Makram & @Ahmad_Alameen,

I have moved your posts to this topic in order not distract efforts to solve this issue.

You can continue in this topic.