Sample code for 30+ languages & platforms
Objective-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 Objective-C Downloads

Objective-C
#import <NSString.h>
#import <CkoXml.h>
#import <CkoBinData.h>
#import <CkoJsonObject.h>
#import <CkoHttp.h>
#import <CkoHttpResponse.h>

BOOL success = NO;

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

CkoXml *signedXml = [[CkoXml alloc] init];
success = [signedXml LoadXmlFile: signedXmlFilePath];
if (success == NO) {
    NSLog(@"%@",signedXml.LastErrorText);
    return;
}

NSString *invoiceHash = [signedXml GetChildContent: @"ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation|ds:Signature|ds:SignedInfo|ds:Reference[0]|ds:DigestValue"];
NSLog(@"%@%@",@"invoiceHash: ",invoiceHash);

NSString *cbc_UUID = [signedXml GetChildContent: @"cbc:UUID"];
NSLog(@"%@%@",@"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.

CkoBinData *bd = [[CkoBinData alloc] init];
success = [bd LoadFile: signedXmlFilePath];
NSString *base64Invoice = [bd GetEncoded: @"base64"];

// OK, let's build the JSON that will be in the HTTP POST body.
CkoJsonObject *json = [[CkoJsonObject alloc] init];
[json UpdateString: @"summary" value: @"Standard Invoice"];
[json UpdateString: @"value.invoiceHash" value: invoiceHash];
[json UpdateString: @"value.uuid" value: cbc_UUID];
[json UpdateString: @"value.invoice" value: base64Invoice];

// Now create the HTTP object and send the POST.
CkoHttp *http = [[CkoHttp alloc] init];

// We'll want HTTP basic authentication.
http.BasicAuth = YES;
http.Login = @"your login";
http.Password = @"your password";

CkoHttpResponse *resp = [[CkoHttpResponse alloc] init];
success = [http HttpJson: @"POST" url: @"https://gw-fatoora.zatca.sa/e-invoicing/simulation/invoices/clearance/single" json: json contentType: @"application/json" response: resp];
if (success == NO) {
    NSLog(@"%@",http.LastErrorText);
    return;
}

// Check the response status code.  A 200 or 202 indicates success..
int statusCode = [resp.StatusCode intValue];
NSLog(@"%@%d",@"Response status code = ",statusCode);

// Examine the response, which is JSON.
CkoJsonObject *jsonResp = [[CkoJsonObject alloc] init];
[resp GetBodyJson: jsonResp];
jsonResp.EmitCompact = NO;
NSLog(@"%@",@"JSON Response:");
NSLog(@"%@",[jsonResp Emit]);

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