Sample code for 30+ languages & platforms
C

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 C Downloads

C
#include <C_CkXml.h>
#include <C_CkBinData.h>
#include <C_CkJsonObject.h>
#include <C_CkHttp.h>
#include <C_CkHttpResponse.h>

void ChilkatSample(void)
    {
    BOOL success;
    const char *signedXmlFilePath;
    HCkXml signedXml;
    const char *invoiceHash;
    const char *cbc_UUID;
    HCkBinData bd;
    const char *base64Invoice;
    HCkJsonObject json;
    HCkHttp http;
    HCkHttpResponse resp;
    int statusCode;
    HCkJsonObject jsonResp;

    success = FALSE;

    //  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.
    signedXmlFilePath = "qa_data/zatca/http_post_clearance/sample_signed_invoice.xml";

    signedXml = CkXml_Create();
    success = CkXml_LoadXmlFile(signedXml,signedXmlFilePath);
    if (success == FALSE) {
        printf("%s\n",CkXml_lastErrorText(signedXml));
        CkXml_Dispose(signedXml);
        return;
    }

    invoiceHash = CkXml_getChildContent(signedXml,"ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation|ds:Signature|ds:SignedInfo|ds:Reference[0]|ds:DigestValue");
    printf("invoiceHash: %s\n",invoiceHash);

    cbc_UUID = CkXml_getChildContent(signedXml,"cbc:UUID");
    printf("UUID: %s\n",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.

    bd = CkBinData_Create();
    success = CkBinData_LoadFile(bd,signedXmlFilePath);
    base64Invoice = CkBinData_getEncoded(bd,"base64");

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

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

    //  We'll want HTTP basic authentication.
    CkHttp_putBasicAuth(http,TRUE);
    CkHttp_putLogin(http,"your login");
    CkHttp_putPassword(http,"your password");

    resp = CkHttpResponse_Create();
    success = CkHttp_HttpJson(http,"POST","https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single",json,"application/json",resp);
    if (success == FALSE) {
        printf("%s\n",CkHttp_lastErrorText(http));
        CkXml_Dispose(signedXml);
        CkBinData_Dispose(bd);
        CkJsonObject_Dispose(json);
        CkHttp_Dispose(http);
        CkHttpResponse_Dispose(resp);
        return;
    }

    //  Check the response status code.  A 200 or 202 indicates success..
    statusCode = CkHttpResponse_getStatusCode(resp);
    printf("Response status code = %d\n",statusCode);

    //  Examine the response, which is JSON.
    jsonResp = CkJsonObject_Create();
    CkHttpResponse_GetBodyJson(resp,jsonResp);
    CkJsonObject_putEmitCompact(jsonResp,FALSE);
    printf("JSON Response:\n");
    printf("%s\n",CkJsonObject_emit(jsonResp));

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


    CkXml_Dispose(signedXml);
    CkBinData_Dispose(bd);
    CkJsonObject_Dispose(json);
    CkHttp_Dispose(http);
    CkHttpResponse_Dispose(resp);
    CkJsonObject_Dispose(jsonResp);

    }