Sample code for 30+ languages & platforms
Xbase++

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 Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL cSignedXmlFilePath
LOCAL oSignedXml
LOCAL cInvoiceHash
LOCAL cCbc_UUID
LOCAL oBd
LOCAL cBase64Invoice
LOCAL oJson
LOCAL oHttp
LOCAL oResp
LOCAL nStatusCode
LOCAL oJsonResp

nSuccess := 0

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

oSignedXml := CreateObject("Chilkat.Xml")
nSuccess := oSignedXml:LoadXmlFile(cSignedXmlFilePath)
IF (nSuccess == 0)
    ? oSignedXml:LastErrorText
    oSignedXml:destroy()
    RETURN
ENDIF

cInvoiceHash := oSignedXml:GetChildContent("ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation|ds:Signature|ds:SignedInfo|ds:Reference[0]|ds:DigestValue")
? "invoiceHash: " + cInvoiceHash

cCbc_UUID := oSignedXml:GetChildContent("cbc:UUID")
? "UUID: " + cCbc_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.

oBd := CreateObject("Chilkat.BinData")
nSuccess := oBd:LoadFile(cSignedXmlFilePath)
cBase64Invoice := oBd:GetEncoded("base64")

//  OK, let's build the JSON that will be in the HTTP POST body.
oJson := CreateObject("Chilkat.JsonObject")
oJson:UpdateString("summary", "Standard Invoice")
oJson:UpdateString("value.invoiceHash", cInvoiceHash)
oJson:UpdateString("value.uuid", cCbc_UUID)
oJson:UpdateString("value.invoice", cBase64Invoice)

//  Now create the HTTP object and send the POST.
oHttp := CreateObject("Chilkat.Http")

//  We'll want HTTP basic authentication.
oHttp:BasicAuth := 1
oHttp:Login := "your login"
oHttp:Password := "your password"

oResp := CreateObject("Chilkat.HttpResponse")
nSuccess := oHttp:HttpJson("POST", "https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single", oJson, "application/json", oResp)
IF (nSuccess == 0)
    ? oHttp:LastErrorText
    oSignedXml:destroy()
    oBd:destroy()
    oJson:destroy()
    oHttp:destroy()
    oResp:destroy()
    RETURN
ENDIF

//  Check the response status code.  A 200 or 202 indicates success..
nStatusCode := oResp:StatusCode
? "Response status code = " + Str(nStatusCode)

//  Examine the response, which is JSON.
oJsonResp := CreateObject("Chilkat.JsonObject")
oResp:GetBodyJson(oJsonResp)
oJsonResp:EmitCompact := 0
? "JSON Response:"
? oJsonResp:Emit()

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

oSignedXml:destroy()
oBd:destroy()
oJson:destroy()
oHttp:destroy()
oResp:destroy()
oJsonResp:destroy()