DataFlex
DataFlex
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 DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
String sSignedXmlFilePath
Handle hoSignedXml
String sInvoiceHash
String sCbc_UUID
Handle hoBd
String sBase64Invoice
Variant vJson
Handle hoJson
Handle hoHttp
Variant vResp
Handle hoResp
Integer iStatusCode
Variant vJsonResp
Handle hoJsonResp
String sTemp1
Move False To iSuccess
// 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.
Move "qa_data/zatca/http_post_clearance/sample_signed_invoice.xml" To sSignedXmlFilePath
Get Create (RefClass(cComChilkatXml)) To hoSignedXml
If (Not(IsComObjectCreated(hoSignedXml))) Begin
Send CreateComObject of hoSignedXml
End
Get ComLoadXmlFile Of hoSignedXml sSignedXmlFilePath To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoSignedXml To sTemp1
Showln sTemp1
Procedure_Return
End
Get ComGetChildContent Of hoSignedXml "ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation|ds:Signature|ds:SignedInfo|ds:Reference[0]|ds:DigestValue" To sInvoiceHash
Showln "invoiceHash: " sInvoiceHash
Get ComGetChildContent Of hoSignedXml "cbc:UUID" To sCbc_UUID
Showln "UUID: " sCbc_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.
Get Create (RefClass(cComChilkatBinData)) To hoBd
If (Not(IsComObjectCreated(hoBd))) Begin
Send CreateComObject of hoBd
End
Get ComLoadFile Of hoBd sSignedXmlFilePath To iSuccess
Get ComGetEncoded Of hoBd "base64" To sBase64Invoice
// OK, let's build the JSON that will be in the HTTP POST body.
Get Create (RefClass(cComChilkatJsonObject)) To hoJson
If (Not(IsComObjectCreated(hoJson))) Begin
Send CreateComObject of hoJson
End
Get ComUpdateString Of hoJson "summary" "Standard Invoice" To iSuccess
Get ComUpdateString Of hoJson "value.invoiceHash" sInvoiceHash To iSuccess
Get ComUpdateString Of hoJson "value.uuid" sCbc_UUID To iSuccess
Get ComUpdateString Of hoJson "value.invoice" sBase64Invoice To iSuccess
// Now create the HTTP object and send the POST.
Get Create (RefClass(cComChilkatHttp)) To hoHttp
If (Not(IsComObjectCreated(hoHttp))) Begin
Send CreateComObject of hoHttp
End
// We'll want HTTP basic authentication.
Set ComBasicAuth Of hoHttp To True
Set ComLogin Of hoHttp To "your login"
Set ComPassword Of hoHttp To "your password"
Get Create (RefClass(cComChilkatHttpResponse)) To hoResp
If (Not(IsComObjectCreated(hoResp))) Begin
Send CreateComObject of hoResp
End
Get pvComObject of hoJson to vJson
Get pvComObject of hoResp to vResp
Get ComHttpJson Of hoHttp "POST" "https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single" vJson "application/json" vResp To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoHttp To sTemp1
Showln sTemp1
Procedure_Return
End
// Check the response status code. A 200 or 202 indicates success..
Get ComStatusCode Of hoResp To iStatusCode
Showln "Response status code = " iStatusCode
// Examine the response, which is JSON.
Get Create (RefClass(cComChilkatJsonObject)) To hoJsonResp
If (Not(IsComObjectCreated(hoJsonResp))) Begin
Send CreateComObject of hoJsonResp
End
Get pvComObject of hoJsonResp to vJsonResp
Get ComGetBodyJson Of hoResp vJsonResp To iSuccess
Set ComEmitCompact Of hoJsonResp To False
Showln "JSON Response:"
Get ComEmit Of hoJsonResp To sTemp1
Showln sTemp1
// Use this online tool to generate parsing code from sample JSON:
// Generate Parsing Code from JSON
End_Procedure