Sample code for 30+ languages & platforms
Java

Send ZATCA Invoice for Clearance

See more ZATCA Examples

Demonstrates how to send a ZATCA invoice for clearance, which is to send the HTTP POST with invoice hash and the signed invoice in base64 format.

Chilkat Java Downloads

Chilkat2 Java
import com.chilkatsoft.chilkat2.BinData;
import com.chilkatsoft.chilkat2.ChilkatException;
import com.chilkatsoft.chilkat2.Http;
import com.chilkatsoft.chilkat2.HttpResponse;
import com.chilkatsoft.chilkat2.JsonObject;
import com.chilkatsoft.chilkat2.Xml;

public class ChilkatExample {

    public static void main(String[] args) {
        // This example requires the Chilkat API to have been previously unlocked.
        // See Global Unlock Sample for sample code.

        // This example will send a POST with HTTP Basic Authentication to
        // https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single

        // NOTE: At the time of this writing, I don't know for sure if the above URL is correct.
        //
        // The body of the POST will contain JSON formatted as such:

        // {
        //   "summary": "Standard Invoice",
        //   "value": {
        //     "invoiceHash": "PEx8bNFcEMEpHzUVvQntQI6ot8eFqTT/l59b+H1HqX4=",
        //     "uuid": "16e78469-64af-406d-9cfd-895e724198f0",
        //     "invoice": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPEl....."
        //   }
        // }

        // The above JSON is created from the signed XML invoice, such as the following:

        // *** Look at the above base64 data for the invoiceHash and uuid.  These values are found in the invoice as shown below.
        // *** We'll write code to load the signed invoice into a Chilkat XML object, grab the invoice hash and the uuid,
        // *** and then construct the above JSON, which will then be sent in a POST.  (See below...)

        // <?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>
        //             <!-- Please note that the signature values are sample values only -->
        //             <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>PEx8bNFcEMEpHzUVvQntQI6ot8eFqTT/l59b+H1HqX4=</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>ZDEyMDUyODJjYzk4MGViNTJhNmYzMGIyZTgxODhkY2JlOWEzNmRiMTFlZTVhMDAxNjk5OTRkYTg3ODhlY2ZiMw==</ds:DigestValue>
        //                             </ds:Reference>
        //                         </ds:SignedInfo>
        // ...
        // ...
        // ...
        //         </ext:ExtensionContent>
        //     </ext:UBLExtension>
        // </ext:UBLExtensions>
        //
        //     <cbc:ProfileID>reporting:1.0</cbc:ProfileID>
        //     <cbc:ID>SME00062</cbc:ID>
        //     <cbc:UUID>16e78469-64af-406d-9cfd-895e724198f0</cbc:UUID>
        //     <cbc:IssueDate>2022-03-13</cbc:IssueDate>
        //     <cbc:IssueTime>14:40:40</cbc:IssueTime>
        //     <cbc:InvoiceTypeCode name="0111010">388</cbc:InvoiceTypeCode>
        // ...
        // ...
        // ...
        //     </cac:InvoiceLine>
        // </Invoice>

        // -------------------------------------------------------------------
        // First, let's load our signed XML into a Chilkat XML object so we can get the uuid and invoice hash.
        String signedXmlFilePath = "qa_data/zatca/http_post_clearance/sample_signed_invoice.xml";

        Xml signedXml = new Xml();
        try {
            signedXml.loadXmlFile(signedXmlFilePath);
        } catch (ChilkatException e) {
            System.out.println(e.getLastErrorText());
            return;
        }

        String invoiceHash = signedXml.getChildContent("ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation|ds:Signature|ds:SignedInfo|ds:Reference[0]|ds:DigestValue");
        System.out.println("invoiceHash: " + invoiceHash);

        String cbc_UUID = signedXml.getChildContent("cbc:UUID");
        System.out.println("UUID: " + cbc_UUID);

        // The Chilkat XML object was used purely for getting the above 2 values.
        // We must send the EXACT signed XML in base64 format.  Therefore, we should load the signed XML into a Chilkat BinData and get it in base64 single-line format.

        BinData bd = new BinData();
        bd.loadFile(signedXmlFilePath);
        String base64Invoice = bd.getEncoded("base64");

        // OK, let's build the JSON that will be in the HTTP POST body.
        JsonObject json = new JsonObject();
        json.updateString("summary", "Standard Invoice");
        json.updateString("value.invoiceHash", invoiceHash);
        json.updateString("value.uuid", cbc_UUID);
        json.updateString("value.invoice", base64Invoice);

        // Now create the HTTP object and send the POST.
        Http http = new Http();

        // We'll want HTTP basic authentication.
        http.setBasicAuth(true);
        http.setLogin("your login");
        http.setPassword("your password");

        HttpResponse resp = new HttpResponse();
        try {
            http.httpJson("POST", "https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single", json, "application/json", resp);
        } catch (ChilkatException e) {
            System.out.println(e.getLastErrorText());
            return;
        }

        // Check the response status code.  A 200 or 202 indicates success..
        int statusCode = resp.getStatusCode();
        System.out.println("Response status code = " + statusCode);

        // Examine the response, which is JSON.
        JsonObject jsonResp = new JsonObject();
        resp.getBodyJson(jsonResp);
        jsonResp.setEmitCompact(false);
        System.out.println("JSON Response:");
        System.out.println(jsonResp.emit());

        // Use this online tool to generate parsing code from sample JSON:
        // Generate Parsing Code from JSON
    }
}