![]() |
Chilkat HOME Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi DLL Go Java Node.js Objective-C PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(Delphi ActiveX) Send ZATCA Invoice for ClearanceSee more ZATCA ExamplesDemonstrates 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.Note: This example requires Chilkat v11.0.0 or greater.
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Chilkat_TLB; ... procedure TForm1.Button1Click(Sender: TObject); var success: Integer; signedXmlFilePath: WideString; signedXml: TChilkatXml; invoiceHash: WideString; cbc_UUID: WideString; bd: TChilkatBinData; base64Invoice: WideString; json: TChilkatJsonObject; http: TChilkatHttp; resp: TChilkatHttpResponse; statusCode: Integer; jsonResp: TChilkatJsonObject; begin success := 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. signedXmlFilePath := 'qa_data/zatca/http_post_clearance/sample_signed_invoice.xml'; signedXml := TChilkatXml.Create(Self); success := signedXml.LoadXmlFile(signedXmlFilePath); if (success = 0) then begin Memo1.Lines.Add(signedXml.LastErrorText); Exit; end; invoiceHash := signedXml.GetChildContent('ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation|ds:Signature|ds:SignedInfo|ds:Reference[0]|ds:DigestValue'); Memo1.Lines.Add('invoiceHash: ' + invoiceHash); cbc_UUID := signedXml.GetChildContent('cbc:UUID'); Memo1.Lines.Add('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. bd := TChilkatBinData.Create(Self); success := bd.LoadFile(signedXmlFilePath); base64Invoice := bd.GetEncoded('base64'); // OK, let's build the JSON that will be in the HTTP POST body. json := TChilkatJsonObject.Create(Self); 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 := TChilkatHttp.Create(Self); // We'll want HTTP basic authentication. http.BasicAuth := 1; http.Login := 'your login'; http.Password := 'your password'; resp := TChilkatHttpResponse.Create(Self); success := http.HttpJson('POST','https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single',json.ControlInterface,'application/json',resp.ControlInterface); if (success = 0) then begin Memo1.Lines.Add(http.LastErrorText); Exit; end; // Check the response status code. A 200 or 202 indicates success.. statusCode := resp.StatusCode; Memo1.Lines.Add('Response status code = ' + IntToStr(statusCode)); // Examine the response, which is JSON. jsonResp := TChilkatJsonObject.Create(Self); resp.GetBodyJson(jsonResp.ControlInterface); jsonResp.EmitCompact := 0; Memo1.Lines.Add('JSON Response:'); Memo1.Lines.Add(jsonResp.Emit()); // Use this online tool to generate parsing code from sample JSON: // Generate Parsing Code from JSON end; |
© 2000-2025 Chilkat Software, Inc. All Rights Reserved.