I am currently testing the ZATCA Phase 2 integration in the API Integration Sandbox and have encountered the following error:
“errorMessages”: [
{
“type”: “ERROR”,
“code”: “invalid-invoice-hash”,
“category”: “INVOICE_HASHING_ERRORS”,
“message”: “The invoice hash API body does not match the (calculated) Hash of the XML”,
“status”: “ERROR”
}
]
Despite following the guidelines, this error indicates a mismatch between the invoice hash in the API body and the calculated hash of the XML. I have attached two files for your review:
XML Invoice Format: The raw XML file of the invoice.
Encoded Invoice Data: The encoded version of the invoice data I am using.
CURL response i got while testing in sandbox zatca account.
Could you kindly assist me in identifying the issue and provide guidance on how to resolve this? I would appreciate any support or troubleshooting tips to ensure the hash calculation and encoding are correct.
Thank you for your time and assistance. I look forward to your response.
Attached Three files below ( encoded invoice data , XML invoice format , CURL response )
eCloud
October 13, 2024, 1:56pm
2
@UnitedDev
You need to inform what the InvoiceXML sources look like, what tools you use to sign, and how you sign the Invoice and make the API Request.
Thanks , i already mentioned i am using sandbox account and testing in api integration sandbox directly. There is sample body request option , i was testing in that sample body and executing the process.
i followed steps to encode data from the official documents provided by zatca.
eCloud
October 13, 2024, 2:13pm
4
This come from your base64Invoice, and yes there is wrong in Invoice Hash
C:\Tmp>fatooranet validate -invoice newx.xml
********************* Welcome to ZATCA E-Invoice .Net SDK 3.3.5 *********************
This App uses .Net to call the SDK passing it an invoice XML file.
It can take a Standard or Simplified XML, Credit Note, or Debit Note.
It returns if the validation is successful or shows errors where the XML validation fails.
It checks for syntax and content as well.
You can use the command (fatooraNet -help) for more information.
You can use the command (fatooraNet {Command} -help) for instructions on how to use the command and expected arguments.
*************************************************************************************
Validate XSD [Success]
Validate EN Schematrons [Success]
Validate KSA Schematrons [Success]
Validate EInvoice PIH [Success]
Overall status [Success]
C:\Tmp>fatooranet generateHash -invoice newx.xml
********************* Welcome to ZATCA E-Invoice .Net SDK 3.3.5 *********************
This App uses .Net to call the SDK passing it an invoice XML file.
It can take a Standard or Simplified XML, Credit Note, or Debit Note.
It returns if the validation is successful or shows errors where the XML validation fails.
It checks for syntax and content as well.
You can use the command (fatooraNet -help) for more information.
You can use the command (fatooraNet {Command} -help) for instructions on how to use the command and expected arguments.
*************************************************************************************
Invoice has been signed successfully
*** Invoice Hash = oICe44+t+jUEhs6Gz/wMReeba4mXlZu++B7noLujsmU=
C:\Tmp>fatooranet sign -invoice newx.xml -signedInvoice Signed_newx.xml
********************* Welcome to ZATCA E-Invoice .Net SDK 3.3.5 *********************
This App uses .Net to call the SDK passing it an invoice XML file.
It can take a Standard or Simplified XML, Credit Note, or Debit Note.
It returns if the validation is successful or shows errors where the XML validation fails.
It checks for syntax and content as well.
You can use the command (fatooraNet -help) for more information.
You can use the command (fatooraNet {Command} -help) for instructions on how to use the command and expected arguments.
*************************************************************************************
Invoice has been signed successfully
*** Invoice Hash = oICe44+t+jUEhs6Gz/wMReeba4mXlZu++B7noLujsmU=
C:\Tmp>
That why i ask you, how you signeing Document and how you create Request Api
1 Like
thanks again , would you please describe is this invoice hash generated from my XML data ?
and i tested encoded data from here : Zatca
and i create encoded data using the tools described in documentation , like XPath or hex to base64 etc
all the request is being create from integration sandbox ,
after using this invoice hash that you created ( oICe44+t+jUEhs6Gz/wMReeba4mXlZu++B7noLujsmU= ) my invoice is passed successfully but would you please tell me what was the issue , is this my XML format issue or invoice hash creating issue ?
can you share Canonicalize invoice from which you created this invoice hash ?
thanks for sharing , you given invoice hash is working , can you check my Canonicalize invoice and tell me what was wrong?
below is XML Canonicalize
eCloud
October 13, 2024, 2:39pm
8
Step to test
Create InvoiceXML ( for example newx.xml)
Sign InvoiceXML
fatooranet sign -invoice newx.xml -signedInvoice Signed_newx.xml
Create invoiceRequest
fatooranet invoiceRequest -invoice Signed_newx.xml -apiRequest newx_request.json
Open file newx_request.json using notepad copy and paste content to Sanbox SwaggerUI.
There is nothing wrong with your invoice, it is just not quite right, you do not need the attribute on every element, declare all used attribut on Invoice element and you just need tag cac and cbc for other element.
This attribute will be removed when the invoice is signed by the SDK, you can see the sample invoice included in the SDK to see the correct format.
1 Like
thanks for information but i am using PHP and web to test it , SDK is not my process ,
would you share canonicalize version of invoice from which you generated invoice hash ?
and also if i am right then signing is not required to generate invoice hash so why this process you mentioned?
and also the XML invoice that you mentioned i was unable to access it , would you provide proper link to download it ?
eCloud
October 13, 2024, 3:02pm
10
I don’t understand PHP, but if you understand C# you can see how I sign the Invoice in this repository .
You can look the code at Zatca.Einvoice Library project.
I respect your work , but can you provide me raw XML of canonicalize or full XML , so that i can compare what is the mistakes i was doing.
i would love if you can provide me raw XML , thanks
eCloud
October 13, 2024, 3:39pm
12
let see
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7097
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5075
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\Users\Incredible One\source\repos\ZatcaEGS\ZatcaEGS
Certificate Valid from : 2024-01-11 4:19:30 PM to 2029-01-09 4:19:30 PM
Sources XML : <?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">
<cbc:ProfileID>reporting:1.0</cbc:ProfileID>
<cbc:ID>1</cbc:ID>
<cbc:UUID>801df1ad-6dbd-47e5-a88a-ee09340ea85b</cbc:UUID>
<cbc:IssueDate>2024-10-13</cbc:IssueDate>
<cbc:IssueTime>11:31:25</cbc:IssueTime>
<cbc:InvoiceTypeCode name="0100000">388</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>SAR</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>SAR</cbc:TaxCurrencyCode>
<cac:AdditionalDocumentReference>
<cbc:ID>ICV</cbc:ID>
<cbc:UUID>1</cbc:UUID>
</cac:AdditionalDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>PIH</cbc:ID>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="text/plain">NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID schemeID="CRN">1010010000</cbc:ID>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>Prince Sultan</cbc:StreetName>
<cbc:BuildingNumber>2322</cbc:BuildingNumber>
<cbc:CitySubdivisionName>Al-Murabba</cbc:CitySubdivisionName>
<cbc:CityName>Riyadh</cbc:CityName>
<cbc:PostalZone>23333</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>SA</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>399999999900003</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Maximum Speed Tech Supply LTD</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>???? ????? | Salah Al-Din</cbc:StreetName>
<cbc:BuildingNumber>1111</cbc:BuildingNumber>
<cbc:CitySubdivisionName>?????? | Al-Murooj</cbc:CitySubdivisionName>
<cbc:CityName>?????? | Riyadh</cbc:CityName>
<cbc:PostalZone>12222</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>SA</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>399999999800003</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Fatoora Samples LTD</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2024-10-13</cbc:ActualDeliveryDate>
<cbc:LatestDeliveryDate>2024-10-13</cbc:LatestDeliveryDate>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="SAR">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="SAR">1000.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="SAR">1000.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="SAR">1150.00</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="SAR">0.00</cbc:AllowanceTotalAmount>
<cbc:PrepaidAmount currencyID="SAR">0.00</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="SAR">1150.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="PCE">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="SAR">1000.00</cbc:LineExtensionAmount>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
<cbc:RoundingAmount currencyID="SAR">1150.00</cbc:RoundingAmount>
</cac:TaxTotal>
<cac:Item>
<cbc:Name>Item with Vat 15%</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="SAR">100.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
canonicalizedXml: <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">
<cbc:ProfileID>reporting:1.0</cbc:ProfileID>
<cbc:ID>1</cbc:ID>
<cbc:UUID>801df1ad-6dbd-47e5-a88a-ee09340ea85b</cbc:UUID>
<cbc:IssueDate>2024-10-13</cbc:IssueDate>
<cbc:IssueTime>11:31:25</cbc:IssueTime>
<cbc:InvoiceTypeCode name="0100000">388</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>SAR</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>SAR</cbc:TaxCurrencyCode>
<cac:AdditionalDocumentReference>
<cbc:ID>ICV</cbc:ID>
<cbc:UUID>1</cbc:UUID>
</cac:AdditionalDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>PIH</cbc:ID>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="text/plain">NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID schemeID="CRN">1010010000</cbc:ID>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>Prince Sultan</cbc:StreetName>
<cbc:BuildingNumber>2322</cbc:BuildingNumber>
<cbc:CitySubdivisionName>Al-Murabba</cbc:CitySubdivisionName>
<cbc:CityName>Riyadh</cbc:CityName>
<cbc:PostalZone>23333</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>SA</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>399999999900003</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Maximum Speed Tech Supply LTD</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>???? ????? | Salah Al-Din</cbc:StreetName>
<cbc:BuildingNumber>1111</cbc:BuildingNumber>
<cbc:CitySubdivisionName>?????? | Al-Murooj</cbc:CitySubdivisionName>
<cbc:CityName>?????? | Riyadh</cbc:CityName>
<cbc:PostalZone>12222</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>SA</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>399999999800003</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Fatoora Samples LTD</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2024-10-13</cbc:ActualDeliveryDate>
<cbc:LatestDeliveryDate>2024-10-13</cbc:LatestDeliveryDate>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="SAR">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5305">S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5153">VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="SAR">1000.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="SAR">1000.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="SAR">1150.00</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="SAR">0.00</cbc:AllowanceTotalAmount>
<cbc:PrepaidAmount currencyID="SAR">0.00</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="SAR">1150.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="PCE">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="SAR">1000.00</cbc:LineExtensionAmount>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="SAR">150.00</cbc:TaxAmount>
<cbc:RoundingAmount currencyID="SAR">1150.00</cbc:RoundingAmount>
</cac:TaxTotal>
<cac:Item>
<cbc:Name>Item with Vat 15%</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5305">S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID schemeAgencyID="6" schemeID="UN/ECE 5153">VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="SAR">100.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
{
"requestUri": "https://gw-fatoora.zatca.gov.sa/e-invoicing/developer-portal/invoices/clearance/single",
"requestType": "Invoice Clearance",
"statusCode": "200-OK",
"clearanceStatus": "CLEARED",
"validationResults": {
"status": "PASS",
"infoMessages": [
{
"status": "PASS",
"type": "INFO",
"code": "XSD_ZATCA_VALID",
"category": "XSD validation",
"Message": "Complied with UBL 2.1 standards in line with ZATCA specifications"
}
],
"warningMessages": [],
"errorMessages": []
},
"clearedInvoice": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPEludm9pY2UgeG1sbnM9InVybjpvYXNpczpuYW1lczpzcGVjaWZpY2F0aW9uOnVibDpzY2hlbWE6eHNkOkludm9pY2UtMiIgeG1sbnM6Y2FjPSJ1cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2NoZW1hOnhzZDpDb21tb25BZ2dyZWdhdGVDb21wb25lbnRzLTIiIHhtbG5zOmNiYz0idXJuOm9hc2lzOm5hbWVzOnNwZWNpZmljYXRpb246dWJsOnNjaGVtYTp4c2Q6Q29tbW9uQmFzaWNDb21wb25lbnRzLTIiIHhtbG5zOmV4dD0idXJuOm9hc2lzOm5hbWVzOnNwZWNpZmljYXRpb246dWJsOnNjaGVtYTp4c2Q6Q29tbW9uRXh0ZW5zaW9uQ29tcG9uZW50cy0yIj48ZXh0OlVCTEV4dGVuc2lvbnM+CiAgICA8ZXh0OlVCTEV4dGVuc2lvbj4KICAgICAgICA8ZXh0OkV4dGVuc2lvblVSST51cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6ZHNpZzplbnZlbG9wZWQ6eGFkZXM8L2V4dDpFeHRlbnNpb25VUkk+CiAgICAgICAgPGV4dDpFeHRlbnNpb25Db250ZW50PgogICAgICAgICAgICA8c2lnOlVCTERvY3VtZW50U2lnbmF0dXJlcyB4bWxuczpzaWc9InVybjpvYXNpczpuYW1lczpzcGVjaWZpY2F0aW9uOnVibDpzY2hlbWE6eHNkOkNvbW1vblNpZ25hdHVyZUNvbXBvbmVudHMtMiIgeG1sbnM6c2FjPSJ1cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2NoZW1hOnhzZDpTaWduYXR1cmVBZ2dyZWdhdGVDb21wb25lbnRzLTIiIHhtbG5zOnNiYz0idXJuOm9hc2lzOm5hbWVzOnNwZWNpZmljYXRpb246dWJsOnNjaGVtYTp4c2Q6U2lnbmF0dXJlQmFzaWNDb21wb25lbnRzLTIiPgogICAgICAgICAgICAgICAgPHNhYzpTaWduYXR1cmVJbmZvcm1hdGlvbj4gCiAgICAgICAgICAgICAgICAgICAgPGNiYzpJRD51cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2lnbmF0dXJlOjE8L2NiYzpJRD4KICAgICAgICAgICAgICAgICAgICA8c2JjOlJlZmVyZW5jZWRTaWduYXR1cmVJRD51cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2lnbmF0dXJlOkludm9pY2U8L3NiYzpSZWZlcmVuY2VkU2lnbmF0dXJlSUQ+CiAgICAgICAgICAgICAgICAgICAgPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyIgSWQ9InNpZ25hdHVyZSI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkczpTaWduZWRJbmZvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDA2LzEyL3htbC1jMTRuMTEiLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNlY2RzYS1zaGEyNTYiLz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpSZWZlcmVuY2UgSWQ9Imludm9pY2VTaWduZWREYXRhIiBVUkk9IiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlRyYW5zZm9ybXM+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy9UUi8xOTk5L1JFQy14cGF0aC0xOTk5MTExNiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZHM6WFBhdGg+bm90KC8vYW5jZXN0b3Itb3Itc2VsZjo6ZXh0OlVCTEV4dGVuc2lvbnMpPC9kczpYUGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kczpUcmFuc2Zvcm0+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy9UUi8xOTk5L1JFQy14cGF0aC0xOTk5MTExNiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZHM6WFBhdGg+bm90KC8vYW5jZXN0b3Itb3Itc2VsZjo6Y2FjOlNpZ25hdHVyZSk8L2RzOlhQYXRoPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2RzOlRyYW5zZm9ybT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnL1RSLzE5OTkvUkVDLXhwYXRoLTE5OTkxMTE2Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpYUGF0aD5ub3QoLy9hbmNlc3Rvci1vci1zZWxmOjpjYWM6QWRkaXRpb25hbERvY3VtZW50UmVmZXJlbmNlW2NiYzpJRD0nUVInXSk8L2RzOlhQYXRoPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2RzOlRyYW5zZm9ybT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDYvMTIveG1sLWMxNG4xMSIvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZHM6VHJhbnNmb3Jtcz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOkRpZ2VzdFZhbHVlPndzTXlpYTQ5cDlzQjVJT09JTndFMjlrdWtuMS9jbGpENXEwUkFDNzcxVTg9PC9kczpEaWdlc3RWYWx1ZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZHM6UmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlJlZmVyZW5jZSBUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjU2lnbmF0dXJlUHJvcGVydGllcyIgVVJJPSIjeGFkZXNTaWduZWRQcm9wZXJ0aWVzIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOkRpZ2VzdFZhbHVlPlptRTNOamMzT1RreE1HTXpZalk0T1Rrd1pqWTNNRGd3WWpjd01HSTBPREF4TkRka09UUTFNVFl4WVRCa09EVXhOelE1WXpRek5XWm1OV00yWm1Jd01BPT08L2RzOkRpZ2VzdFZhbHVlPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kczpSZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZHM6U2lnbmVkSW5mbz4KICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlNpZ25hdHVyZVZhbHVlPk1FWUNJUURscWJFdTljU1cwVG9LT08rZFBtS1M0Nlo1d2NoYkFlY2FoSnFiekxUNU53SWhBTE9Pc0dRVTBLOUpmL3ZUaVRzajcvcUtPZkxoR2tWOUJkWitvZHNrT3RnZTwvZHM6U2lnbmF0dXJlVmFsdWU+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkczpLZXlJbmZvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlg1MDlEYXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpYNTA5Q2VydGlmaWNhdGU+TUlJRDNqQ0NBNFNnQXdJQkFnSVRFUUFBT0FQRjkwQWpzL3hjWHdBQkFBQTRBekFLQmdncWhrak9QUVFEQWpCaU1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRmJHOWpZV3d4RXpBUkJnb0praWFKay9Jc1pBRVpGZ05uYjNZeEZ6QVZCZ29Ka2lhSmsvSXNaQUVaRmdkbGVIUm5ZWHAwTVJzd0dRWURWUVFERXhKUVVscEZTVTVXVDBsRFJWTkRRVFF0UTBFd0hoY05NalF3TVRFeE1Ea3hPVE13V2hjTk1qa3dNVEE1TURreE9UTXdXakIxTVFzd0NRWURWUVFHRXdKVFFURW1NQ1FHQTFVRUNoTWRUV0Y0YVcxMWJTQlRjR1ZsWkNCVVpXTm9JRk4xY0hCc2VTQk1WRVF4RmpBVUJnTlZCQXNURFZKcGVXRmthQ0JDY21GdVkyZ3hKakFrQmdOVkJBTVRIVlJUVkMwNE9EWTBNekV4TkRVdE16azVPVGs1T1RrNU9UQXdNREF6TUZZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUFvRFFnQUVvV0NLYTBTYTlGSUVyVE92MHVBa0MxVklLWHhVOW5QcHgydmxmNHloTWVqeThjMDJYSmJsRHE3dFB5ZG84bXEwYWhPTW1Obzhnd25pN1h0MUtUOVVlS09DQWdjd2dnSURNSUd0QmdOVkhSRUVnYVV3Z2FLa2daOHdnWnd4T3pBNUJnTlZCQVFNTWpFdFZGTlVmREl0VkZOVWZETXRaV1F5TW1ZeFpEZ3RaVFpoTWkweE1URTRMVGxpTlRndFpEbGhPR1l4TVdVME5EVm1NUjh3SFFZS0NaSW1pWlB5TEdRQkFRd1BNems1T1RrNU9UazVPVEF3TURBek1RMHdDd1lEVlFRTURBUXhNVEF3TVJFd0R3WURWUVFhREFoU1VsSkVNamt5T1RFYU1CZ0dBMVVFRHd3UlUzVndjR3g1SUdGamRHbDJhWFJwWlhNd0hRWURWUjBPQkJZRUZFWCtZdm1tdG5Zb0RmOUJHYktvN29jVEtZSzFNQjhHQTFVZEl3UVlNQmFBRkp2S3FxTHRtcXdza0lGelZ2cFAyUHhUKzlObk1Ic0dDQ3NHQVFVRkJ3RUJCRzh3YlRCckJnZ3JCZ0VGQlFjd0FvWmZhSFIwY0RvdkwyRnBZVFF1ZW1GMFkyRXVaMjkyTG5OaEwwTmxjblJGYm5KdmJHd3ZVRkphUlVsdWRtOXBZMlZUUTBFMExtVjRkR2RoZW5RdVoyOTJMbXh2WTJGc1gxQlNXa1ZKVGxaUFNVTkZVME5CTkMxRFFTZ3hLUzVqY25Rd0RnWURWUjBQQVFIL0JBUURBZ2VBTUR3R0NTc0dBUVFCZ2pjVkJ3UXZNQzBHSlNzR0FRUUJnamNWQ0lHR3FCMkUwUHNTaHUyZEpJZk8reG5Ud0ZWbWgvcWxaWVhaaEQ0Q0FXUUNBUkl3SFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdNR0NDc0dBUVVGQndNQ01DY0dDU3NHQVFRQmdqY1ZDZ1FhTUJnd0NnWUlLd1lCQlFVSEF3TXdDZ1lJS3dZQkJRVUhBd0l3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUxFL2ljaG1uV1hDVUtVYmNhM3ljaThvcXdhTHZGZEhWalFydmVJOXVxQWJBaUE5aEM0TThqZ01CQURQU3ptZDJ1aVBKQTZnS1IzTEUwM1U3NWVxYkMvclhBPT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZHM6WDUwOURhdGE+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZHM6S2V5SW5mbz4KICAgICAgICAgICAgICAgICAgICAgICAgPGRzOk9iamVjdD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx4YWRlczpRdWFsaWZ5aW5nUHJvcGVydGllcyB4bWxuczp4YWRlcz0iaHR0cDovL3VyaS5ldHNpLm9yZy8wMTkwMy92MS4zLjIjIiBUYXJnZXQ9InNpZ25hdHVyZSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHhhZGVzOlNpZ25lZFByb3BlcnRpZXMgSWQ9InhhZGVzU2lnbmVkUHJvcGVydGllcyI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx4YWRlczpTaWduZWRTaWduYXR1cmVQcm9wZXJ0aWVzPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHhhZGVzOlNpZ25pbmdUaW1lPjIwMjQtMTAtMTNUMTg6Mzk6MjI8L3hhZGVzOlNpZ25pbmdUaW1lPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHhhZGVzOlNpZ25pbmdDZXJ0aWZpY2F0ZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8eGFkZXM6Q2VydD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHhhZGVzOkNlcnREaWdlc3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZHM6RGlnZXN0VmFsdWU+WkRNd01tSTBNVEUxTnpWak9UVTJOVGs0WXpWbE9EaGhZbUkwT0RVMk5EVXlOVFUyWVRWaFlqaGhNREZtTjJGallqazFZVEEyT1dRME5qWTJNalE0TlE9PTwvZHM6RGlnZXN0VmFsdWU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwveGFkZXM6Q2VydERpZ2VzdD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHhhZGVzOklzc3VlclNlcmlhbD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkczpYNTA5SXNzdWVyTmFtZT5DTj1QUlpFSU5WT0lDRVNDQTQtQ0EsIERDPWV4dGdhenQsIERDPWdvdiwgREM9bG9jYWw8L2RzOlg1MDlJc3N1ZXJOYW1lPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRzOlg1MDlTZXJpYWxOdW1iZXI+Mzc5MTEyNzQyODMxMzgwNDcxODM1MjYzOTY5NTg3Mjg3NjYzNTIwNTI4Mzg3PC9kczpYNTA5U2VyaWFsTnVtYmVyPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3hhZGVzOklzc3VlclNlcmlhbD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3hhZGVzOkNlcnQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3hhZGVzOlNpZ25pbmdDZXJ0aWZpY2F0ZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC94YWRlczpTaWduZWRTaWduYXR1cmVQcm9wZXJ0aWVzPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwveGFkZXM6U2lnbmVkUHJvcGVydGllcz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwveGFkZXM6UXVhbGlmeWluZ1Byb3BlcnRpZXM+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZHM6T2JqZWN0PgogICAgICAgICAgICAgICAgICAgIDwvZHM6U2lnbmF0dXJlPgogICAgICAgICAgICAgICAgPC9zYWM6U2lnbmF0dXJlSW5mb3JtYXRpb24+CiAgICAgICAgICAgIDwvc2lnOlVCTERvY3VtZW50U2lnbmF0dXJlcz4KICAgICAgICA8L2V4dDpFeHRlbnNpb25Db250ZW50PgogICAgPC9leHQ6VUJMRXh0ZW5zaW9uPgo8L2V4dDpVQkxFeHRlbnNpb25zPgogICAgPGNiYzpQcm9maWxlSUQ+cmVwb3J0aW5nOjEuMDwvY2JjOlByb2ZpbGVJRD4KICAgIDxjYmM6SUQ+MTwvY2JjOklEPgogICAgPGNiYzpVVUlEPjgwMWRmMWFkLTZkYmQtNDdlNS1hODhhLWVlMDkzNDBlYTg1YjwvY2JjOlVVSUQ+CiAgICA8Y2JjOklzc3VlRGF0ZT4yMDI0LTEwLTEzPC9jYmM6SXNzdWVEYXRlPgogICAgPGNiYzpJc3N1ZVRpbWU+MTE6MzE6MjU8L2NiYzpJc3N1ZVRpbWU+CiAgICA8Y2JjOkludm9pY2VUeXBlQ29kZSBuYW1lPSIwMTAwMDAwIj4zODg8L2NiYzpJbnZvaWNlVHlwZUNvZGU+CiAgICA8Y2JjOkRvY3VtZW50Q3VycmVuY3lDb2RlPlNBUjwvY2JjOkRvY3VtZW50Q3VycmVuY3lDb2RlPgogICAgPGNiYzpUYXhDdXJyZW5jeUNvZGU+U0FSPC9jYmM6VGF4Q3VycmVuY3lDb2RlPgogICAgPGNhYzpBZGRpdGlvbmFsRG9jdW1lbnRSZWZlcmVuY2U+CiAgICAgICAgPGNiYzpJRD5JQ1Y8L2NiYzpJRD4KICAgICAgICA8Y2JjOlVVSUQ+MTwvY2JjOlVVSUQ+CiAgICA8L2NhYzpBZGRpdGlvbmFsRG9jdW1lbnRSZWZlcmVuY2U+CiAgICA8Y2FjOkFkZGl0aW9uYWxEb2N1bWVudFJlZmVyZW5jZT4KICAgICAgICA8Y2JjOklEPlBJSDwvY2JjOklEPgogICAgICAgIDxjYWM6QXR0YWNobWVudD4KICAgICAgICAgICAgPGNiYzpFbWJlZGRlZERvY3VtZW50QmluYXJ5T2JqZWN0IG1pbWVDb2RlPSJ0ZXh0L3BsYWluIj5OV1psWTJWaU5qWm1abU00Tm1Zek9HUTVOVEkzT0Raak5tUTJPVFpqTnpsak1tUmlZekl6T1dSa05HVTVNV0kwTmpjeU9XUTNNMkV5TjJaaU5UZGxPUT09PC9jYmM6RW1iZWRkZWREb2N1bWVudEJpbmFyeU9iamVjdD4KICAgICAgICA8L2NhYzpBdHRhY2htZW50PgogICAgPC9jYWM6QWRkaXRpb25hbERvY3VtZW50UmVmZXJlbmNlPgogICAgPGNhYzpBZGRpdGlvbmFsRG9jdW1lbnRSZWZlcmVuY2U+CiAgICAgICAgPGNiYzpJRD5RUjwvY2JjOklEPgogICAgICAgIDxjYWM6QXR0YWNobWVudD4KICAgICAgICAgICAgPGNiYzpFbWJlZGRlZERvY3VtZW50QmluYXJ5T2JqZWN0IG1pbWVDb2RlPSJ0ZXh0L3BsYWluIj5BUjFOWVhocGJYVnRJRk53WldWa0lGUmxZMmdnVTNWd2NHeDVJRXhVUkFJUE16azVPVGs1T1RrNU9UQXdNREF6QXhNeU1ESTBMVEV3TFRFelZERXhPak14T2pJMUJBY3hNVFV3TGpBd0JRWXhOVEF1TURBR0xIZHpUWGxwWVRRNWNEbHpRalZKVDA5SlRuZEZNamxyZFd0dU1TOWpiR3BFTlhFd1VrRkROemN4VlRnOUIyQk5SVmxEU1ZGRWJIRmlSWFU1WTFOWE1GUnZTMDlQSzJSUWJVdFRORFphTlhkamFHSkJaV05oYUVweFlucE1WRFZPZDBsb1FVeFBUM05IVVZVd1N6bEtaaTkyVkdsVWMybzNMM0ZMVDJaTWFFZHJWamxDWkZvcmIyUnphMDkwWjJVSVdEQldNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQUtBMElBQktGZ2ltdEVtdlJTQkswenI5TGdKQXRWU0NsOFZQWno2Y2RyNVgrTW9USG84dkhOTmx5VzVRNnU3VDhuYVBKcXRHb1RqSmphUElNSjR1MTdkU2svVkhnPTwvY2JjOkVtYmVkZGVkRG9jdW1lbnRCaW5hcnlPYmplY3Q+CiAgICAgICAgPC9jYWM6QXR0YWNobWVudD4KPC9jYWM6QWRkaXRpb25hbERvY3VtZW50UmVmZXJlbmNlPjxjYWM6U2lnbmF0dXJlPgogICAgICA8Y2JjOklEPnVybjpvYXNpczpuYW1lczpzcGVjaWZpY2F0aW9uOnVibDpzaWduYXR1cmU6SW52b2ljZTwvY2JjOklEPgogICAgICA8Y2JjOlNpZ25hdHVyZU1ldGhvZD51cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6ZHNpZzplbnZlbG9wZWQ6eGFkZXM8L2NiYzpTaWduYXR1cmVNZXRob2Q+CjwvY2FjOlNpZ25hdHVyZT48Y2FjOkFjY291bnRpbmdTdXBwbGllclBhcnR5PgogICAgICAgIDxjYWM6UGFydHk+CiAgICAgICAgICAgIDxjYWM6UGFydHlJZGVudGlmaWNhdGlvbj4KICAgICAgICAgICAgICAgIDxjYmM6SUQgc2NoZW1lSUQ9IkNSTiI+MTAxMDAxMDAwMDwvY2JjOklEPgogICAgICAgICAgICA8L2NhYzpQYXJ0eUlkZW50aWZpY2F0aW9uPgogICAgICAgICAgICA8Y2FjOlBvc3RhbEFkZHJlc3M+CiAgICAgICAgICAgICAgICA8Y2JjOlN0cmVldE5hbWU+UHJpbmNlIFN1bHRhbjwvY2JjOlN0cmVldE5hbWU+CiAgICAgICAgICAgICAgICA8Y2JjOkJ1aWxkaW5nTnVtYmVyPjIzMjI8L2NiYzpCdWlsZGluZ051bWJlcj4KICAgICAgICAgICAgICAgIDxjYmM6Q2l0eVN1YmRpdmlzaW9uTmFtZT5BbC1NdXJhYmJhPC9jYmM6Q2l0eVN1YmRpdmlzaW9uTmFtZT4KICAgICAgICAgICAgICAgIDxjYmM6Q2l0eU5hbWU+Uml5YWRoPC9jYmM6Q2l0eU5hbWU+CiAgICAgICAgICAgICAgICA8Y2JjOlBvc3RhbFpvbmU+MjMzMzM8L2NiYzpQb3N0YWxab25lPgogICAgICAgICAgICAgICAgPGNhYzpDb3VudHJ5PgogICAgICAgICAgICAgICAgICAgIDxjYmM6SWRlbnRpZmljYXRpb25Db2RlPlNBPC9jYmM6SWRlbnRpZmljYXRpb25Db2RlPgogICAgICAgICAgICAgICAgPC9jYWM6Q291bnRyeT4KICAgICAgICAgICAgPC9jYWM6UG9zdGFsQWRkcmVzcz4KICAgICAgICAgICAgPGNhYzpQYXJ0eVRheFNjaGVtZT4KICAgICAgICAgICAgICAgIDxjYmM6Q29tcGFueUlEPjM5OTk5OTk5OTkwMDAwMzwvY2JjOkNvbXBhbnlJRD4KICAgICAgICAgICAgICAgIDxjYWM6VGF4U2NoZW1lPgogICAgICAgICAgICAgICAgICAgIDxjYmM6SUQ+VkFUPC9jYmM6SUQ+CiAgICAgICAgICAgICAgICA8L2NhYzpUYXhTY2hlbWU+CiAgICAgICAgICAgIDwvY2FjOlBhcnR5VGF4U2NoZW1lPgogICAgICAgICAgICA8Y2FjOlBhcnR5TGVnYWxFbnRpdHk+CiAgICAgICAgICAgICAgICA8Y2JjOlJlZ2lzdHJhdGlvbk5hbWU+TWF4aW11bSBTcGVlZCBUZWNoIFN1cHBseSBMVEQ8L2NiYzpSZWdpc3RyYXRpb25OYW1lPgogICAgICAgICAgICA8L2NhYzpQYXJ0eUxlZ2FsRW50aXR5PgogICAgICAgIDwvY2FjOlBhcnR5PgogICAgPC9jYWM6QWNjb3VudGluZ1N1cHBsaWVyUGFydHk+CiAgICA8Y2FjOkFjY291bnRpbmdDdXN0b21lclBhcnR5PgogICAgICAgIDxjYWM6UGFydHk+CiAgICAgICAgICAgIDxjYWM6UG9zdGFsQWRkcmVzcz4KICAgICAgICAgICAgICAgIDxjYmM6U3RyZWV0TmFtZT7YtdmE2KfYrSDYp9mE2K/ZitmGIHwgU2FsYWggQWwtRGluPC9jYmM6U3RyZWV0TmFtZT4KICAgICAgICAgICAgICAgIDxjYmM6QnVpbGRpbmdOdW1iZXI+MTExMTwvY2JjOkJ1aWxkaW5nTnVtYmVyPgogICAgICAgICAgICAgICAgPGNiYzpDaXR5U3ViZGl2aXNpb25OYW1lPtin2YTZhdix2YjYrCB8IEFsLU11cm9vajwvY2JjOkNpdHlTdWJkaXZpc2lvbk5hbWU+CiAgICAgICAgICAgICAgICA8Y2JjOkNpdHlOYW1lPtin2YTYsdmK2KfYtiB8IFJpeWFkaDwvY2JjOkNpdHlOYW1lPgogICAgICAgICAgICAgICAgPGNiYzpQb3N0YWxab25lPjEyMjIyPC9jYmM6UG9zdGFsWm9uZT4KICAgICAgICAgICAgICAgIDxjYWM6Q291bnRyeT4KICAgICAgICAgICAgICAgICAgICA8Y2JjOklkZW50aWZpY2F0aW9uQ29kZT5TQTwvY2JjOklkZW50aWZpY2F0aW9uQ29kZT4KICAgICAgICAgICAgICAgIDwvY2FjOkNvdW50cnk+CiAgICAgICAgICAgIDwvY2FjOlBvc3RhbEFkZHJlc3M+CiAgICAgICAgICAgIDxjYWM6UGFydHlUYXhTY2hlbWU+CiAgICAgICAgICAgICAgICA8Y2JjOkNvbXBhbnlJRD4zOTk5OTk5OTk4MDAwMDM8L2NiYzpDb21wYW55SUQ+CiAgICAgICAgICAgICAgICA8Y2FjOlRheFNjaGVtZT4KICAgICAgICAgICAgICAgICAgICA8Y2JjOklEPlZBVDwvY2JjOklEPgogICAgICAgICAgICAgICAgPC9jYWM6VGF4U2NoZW1lPgogICAgICAgICAgICA8L2NhYzpQYXJ0eVRheFNjaGVtZT4KICAgICAgICAgICAgPGNhYzpQYXJ0eUxlZ2FsRW50aXR5PgogICAgICAgICAgICAgICAgPGNiYzpSZWdpc3RyYXRpb25OYW1lPkZhdG9vcmEgU2FtcGxlcyBMVEQ8L2NiYzpSZWdpc3RyYXRpb25OYW1lPgogICAgICAgICAgICA8L2NhYzpQYXJ0eUxlZ2FsRW50aXR5PgogICAgICAgIDwvY2FjOlBhcnR5PgogICAgPC9jYWM6QWNjb3VudGluZ0N1c3RvbWVyUGFydHk+CiAgICA8Y2FjOkRlbGl2ZXJ5PgogICAgICAgIDxjYmM6QWN0dWFsRGVsaXZlcnlEYXRlPjIwMjQtMTAtMTM8L2NiYzpBY3R1YWxEZWxpdmVyeURhdGU+CiAgICAgICAgPGNiYzpMYXRlc3REZWxpdmVyeURhdGU+MjAyNC0xMC0xMzwvY2JjOkxhdGVzdERlbGl2ZXJ5RGF0ZT4KICAgIDwvY2FjOkRlbGl2ZXJ5PgogICAgPGNhYzpQYXltZW50TWVhbnM+CiAgICAgICAgPGNiYzpQYXltZW50TWVhbnNDb2RlPjMwPC9jYmM6UGF5bWVudE1lYW5zQ29kZT4KICAgIDwvY2FjOlBheW1lbnRNZWFucz4KICAgIDxjYWM6VGF4VG90YWw+CiAgICAgICAgPGNiYzpUYXhBbW91bnQgY3VycmVuY3lJRD0iU0FSIj4xNTAuMDA8L2NiYzpUYXhBbW91bnQ+CiAgICA8L2NhYzpUYXhUb3RhbD4KICAgIDxjYWM6VGF4VG90YWw+CiAgICAgICAgPGNiYzpUYXhBbW91bnQgY3VycmVuY3lJRD0iU0FSIj4xNTAuMDA8L2NiYzpUYXhBbW91bnQ+CiAgICAgICAgPGNhYzpUYXhTdWJ0b3RhbD4KICAgICAgICAgICAgPGNiYzpUYXhhYmxlQW1vdW50IGN1cnJlbmN5SUQ9IlNBUiI+MTAwMC4wMDwvY2JjOlRheGFibGVBbW91bnQ+CiAgICAgICAgICAgIDxjYmM6VGF4QW1vdW50IGN1cnJlbmN5SUQ9IlNBUiI+MTUwLjAwPC9jYmM6VGF4QW1vdW50PgogICAgICAgICAgICA8Y2FjOlRheENhdGVnb3J5PgogICAgICAgICAgICAgICAgPGNiYzpJRCBzY2hlbWVJRD0iVU4vRUNFIDUzMDUiIHNjaGVtZUFnZW5jeUlEPSI2Ij5TPC9jYmM6SUQ+CiAgICAgICAgICAgICAgICA8Y2JjOlBlcmNlbnQ+MTU8L2NiYzpQZXJjZW50PgogICAgICAgICAgICAgICAgPGNhYzpUYXhTY2hlbWU+CiAgICAgICAgICAgICAgICAgICAgPGNiYzpJRCBzY2hlbWVJRD0iVU4vRUNFIDUxNTMiIHNjaGVtZUFnZW5jeUlEPSI2Ij5WQVQ8L2NiYzpJRD4KICAgICAgICAgICAgICAgIDwvY2FjOlRheFNjaGVtZT4KICAgICAgICAgICAgPC9jYWM6VGF4Q2F0ZWdvcnk+CiAgICAgICAgPC9jYWM6VGF4U3VidG90YWw+CiAgICA8L2NhYzpUYXhUb3RhbD4KICAgIDxjYWM6TGVnYWxNb25ldGFyeVRvdGFsPgogICAgICAgIDxjYmM6TGluZUV4dGVuc2lvbkFtb3VudCBjdXJyZW5jeUlEPSJTQVIiPjEwMDAuMDA8L2NiYzpMaW5lRXh0ZW5zaW9uQW1vdW50PgogICAgICAgIDxjYmM6VGF4RXhjbHVzaXZlQW1vdW50IGN1cnJlbmN5SUQ9IlNBUiI+MTAwMC4wMDwvY2JjOlRheEV4Y2x1c2l2ZUFtb3VudD4KICAgICAgICA8Y2JjOlRheEluY2x1c2l2ZUFtb3VudCBjdXJyZW5jeUlEPSJTQVIiPjExNTAuMDA8L2NiYzpUYXhJbmNsdXNpdmVBbW91bnQ+CiAgICAgICAgPGNiYzpBbGxvd2FuY2VUb3RhbEFtb3VudCBjdXJyZW5jeUlEPSJTQVIiPjAuMDA8L2NiYzpBbGxvd2FuY2VUb3RhbEFtb3VudD4KICAgICAgICA8Y2JjOlByZXBhaWRBbW91bnQgY3VycmVuY3lJRD0iU0FSIj4wLjAwPC9jYmM6UHJlcGFpZEFtb3VudD4KICAgICAgICA8Y2JjOlBheWFibGVBbW91bnQgY3VycmVuY3lJRD0iU0FSIj4xMTUwLjAwPC9jYmM6UGF5YWJsZUFtb3VudD4KICAgIDwvY2FjOkxlZ2FsTW9uZXRhcnlUb3RhbD4KICAgIDxjYWM6SW52b2ljZUxpbmU+CiAgICAgICAgPGNiYzpJRD4xPC9jYmM6SUQ+CiAgICAgICAgPGNiYzpJbnZvaWNlZFF1YW50aXR5IHVuaXRDb2RlPSJQQ0UiPjEwPC9jYmM6SW52b2ljZWRRdWFudGl0eT4KICAgICAgICA8Y2JjOkxpbmVFeHRlbnNpb25BbW91bnQgY3VycmVuY3lJRD0iU0FSIj4xMDAwLjAwPC9jYmM6TGluZUV4dGVuc2lvbkFtb3VudD4KICAgICAgICA8Y2FjOlRheFRvdGFsPgogICAgICAgICAgICA8Y2JjOlRheEFtb3VudCBjdXJyZW5jeUlEPSJTQVIiPjE1MC4wMDwvY2JjOlRheEFtb3VudD4KICAgICAgICAgICAgPGNiYzpSb3VuZGluZ0Ftb3VudCBjdXJyZW5jeUlEPSJTQVIiPjExNTAuMDA8L2NiYzpSb3VuZGluZ0Ftb3VudD4KICAgICAgICA8L2NhYzpUYXhUb3RhbD4KICAgICAgICA8Y2FjOkl0ZW0+CiAgICAgICAgICAgIDxjYmM6TmFtZT5JdGVtIHdpdGggVmF0IDE1JTwvY2JjOk5hbWU+CiAgICAgICAgICAgIDxjYWM6Q2xhc3NpZmllZFRheENhdGVnb3J5PgogICAgICAgICAgICAgICAgPGNiYzpJRCBzY2hlbWVJRD0iVU4vRUNFIDUzMDUiIHNjaGVtZUFnZW5jeUlEPSI2Ij5TPC9jYmM6SUQ+CiAgICAgICAgICAgICAgICA8Y2JjOlBlcmNlbnQ+MTU8L2NiYzpQZXJjZW50PgogICAgICAgICAgICAgICAgPGNhYzpUYXhTY2hlbWU+CiAgICAgICAgICAgICAgICAgICAgPGNiYzpJRCBzY2hlbWVJRD0iVU4vRUNFIDUxNTMiIHNjaGVtZUFnZW5jeUlEPSI2Ij5WQVQ8L2NiYzpJRD4KICAgICAgICAgICAgICAgIDwvY2FjOlRheFNjaGVtZT4KICAgICAgICAgICAgPC9jYWM6Q2xhc3NpZmllZFRheENhdGVnb3J5PgogICAgICAgIDwvY2FjOkl0ZW0+CiAgICAgICAgPGNhYzpQcmljZT4KICAgICAgICAgICAgPGNiYzpQcmljZUFtb3VudCBjdXJyZW5jeUlEPSJTQVIiPjEwMC4wMDwvY2JjOlByaWNlQW1vdW50PgogICAgICAgIDwvY2FjOlByaWNlPgogICAgPC9jYWM6SW52b2ljZUxpbmU+CjwvSW52b2ljZT4="
}
as this Standard Invoice, i dont need to sign the document
your information is great, please check below more information for more clarification , i am using you XML version that you provided in drive file , i extracted text from base64
first please check if i created correct canonicalized version of you XML : Unique Download Link | WeTransfer
second , if i hashed correct sha256 using the same canonicalized version i given above. I used tool as per zatca document ( SHA256 - Online Tools ) : f7885494e2596958aeaec02bbc680c5cd9073c4c8ea4dc023996c87ddc9882e3
third check if i encoded above hashed into base64. I used tool as per zatca document ( https:// emn178. github. io/ online-tools/sha256.html ) :
hh7wXNKt/CjnEr1AEd7Lhgr205Lf5rNDWgrzgvVoiCI=
why cannot i the above generated invoice hash in api request body in sandbox account?
eCloud
October 13, 2024, 4:20pm
14
The invoice format does not need to be the same, the most important thing is to follow the rules set by Zatca.
We need to make sure the InvoiceHash generated by our code is the same as the InvoiceHash that will be generated by the Server.
This is how I generate Hash from InvoiceXML.
Aplay XLST
private string GetCleanInvoiceXML(bool applayXsl = true)
{
try
{
XmlSerializerNamespaces namespaces = new();
namespaces.Add("cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2");
namespaces.Add("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2");
namespaces.Add("ext", "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2");
var invoiceData = InvoiceObject.ObjectToXml(namespaces);
if (applayXsl) { invoiceData = invoiceData.ApplyXSLT(SharedUtilities.ReadResource("ZatcaDataInvoice.xsl"), true); }
return invoiceData.ToFormattedXml();
}
catch (Exception)
{
//Console.WriteLine($"Error Get CleanInvoice XML: {ex.Message}");
return null;
}
}
internal static string ApplyXSLT(this string xml, string xsltFileContent, bool indent)
{
StringBuilder output = new();
XmlWriterSettings settings = new()
{
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8,
ConformanceLevel = ConformanceLevel.Auto,
Indent = indent
};
using (XmlWriter writer = XmlWriter.Create(output, settings))
{
XmlReader stylesheet = XmlReader.Create(new StringReader(xsltFileContent));
XmlReader input = XmlReader.Create(new StringReader(xml));
input.Read();
XslCompiledTransform transform1 = new();
transform1.Load(stylesheet);
transform1.Transform(input, writer);
}
return output.ToString();
}
Canonicalize and get Hash
internal static string GetBase64InvoiceHash(string eInvoiceXml)
{
Console.WriteLine($"Sources XML : " + eInvoiceXml);
using MemoryStream stream = new(Encoding.UTF8.GetBytes(eInvoiceXml));
XmlDsigC14NTransform transform1 = new(false);
transform1.LoadInput(stream);
MemoryStream output = transform1.GetOutput() as MemoryStream;
Console.WriteLine("canonicalizedXml: " + Encoding.UTF8.GetString(output.ToArray()));
byte[] hashBytes = HashSha256(Encoding.UTF8.GetString(output.ToArray()));
return Convert.ToBase64String(hashBytes);
}
You can use AI to convert it into PHP code and try it on your project
1 Like
Thank you for detailed explanation , i have one minor question , suppose if any person is using manual process to generate invoice hash as step followed by zatca documentation then why the invoice hash generated is not accepted by request api and getting error , steps below :
Open the invoice XML file.
Remove the tags mentioned in the table below using the XPath.
Remove the XML version.
Canonicalize the Invoice using the C14N11 standard
Hash the new invoice body using SHA-256 (output). e.g.:a11b6fe587a50f7daffe3a7fb42dcccf-
32b43ee9b37d9f252d04243e54c11a3f
Encode the hashed invoice using base64 (output)
Using HEX-to Base64 Encoder
e.g.:oRtv5YelD32v/jp/tC3MzzK0PumzfZ8lLQQkPlTBGj8=
Note: All these values will be used in later steps
below tool links to generate invoice hash as per zatca documentation :
Xpath
For canonicalization XML Canonicalizer
For hashing and then enocoding base64 both : SHA256 - Online Tools
eCloud
October 14, 2024, 6:37am
17
I don’t understand PHP, but the code works as it should, and its approved by the server.
<?php
function generateApiRequest($xmlFilePath, $xslFilePath) {
// 1. Buka dokumen XML dengan preserveWhiteSpace = true
$xml = new DOMDocument();
$xml->preserveWhiteSpace = true;
$xml->formatOutput = false;
// Load XML dari path yang diberikan
if (!$xml->load($xmlFilePath)) {
throw new Exception("Failed to load XML file: $xmlFilePath");
}
// 1a. Ambil UUID dari elemen <cbc:UUID>
$xpath = new DOMXPath($xml);
$xpath->registerNamespace('cbc', 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2');
$uuidNode = $xpath->query('//cbc:UUID')->item(0);
if (!$uuidNode) {
throw new Exception("UUID not found in the XML document.");
}
$uuid = $uuidNode->nodeValue;
// 2. Terapkan XSL untuk transformasi
$xsl = new DOMDocument();
if (!$xsl->load($xslFilePath)) {
throw new Exception("Failed to load XSL file: $xslFilePath");
}
$proc = new XSLTProcessor();
$proc->importStylesheet($xsl);
// Lakukan transformasi
$transformedXml = $proc->transformToDoc($xml);
if (!$transformedXml) {
throw new Exception("XSL Transformation failed.");
}
// 3. Canonicalize (C14N) hasil transformasi
$canonicalXml = $transformedXml->C14N(); // hasil transformasi dalam format C14N
// 4. Dapatkan byte hash256 dari hasil transformasi
$hash = hash('sha256', $canonicalXml, true); // menghasilkan hash SHA-256 sebagai binary data
// 5. Encode hasil hash ke Base64
$base64Hash = base64_encode($hash);
// 6. Encode canonicalized XML ke Base64
$base64Invoice = base64_encode($canonicalXml);
// 7. Buat array dengan hasil yang diinginkan
$result = array(
"invoiceHash" => $base64Hash,
"uuid" => $uuid,
"invoice" => $base64Invoice
);
// 8. Konversi array menjadi JSON string
return json_encode($result);
}
// Contoh penggunaan fungsi:
$xmlFilePath = 'xmlfile.xml';
$xslFilePath = 'xslfile.xsl';
try {
$jsonResult = generateApiRequest($xmlFilePath, $xslFilePath);
echo $jsonResult; // Menampilkan JSON string
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
?>
1 Like
amazing your code is working perfectly , i am pretty shocked why it is not working when i was keep trying. i converted it into python and tested
eCloud
October 14, 2024, 9:01am
19
Do gou got an error with that code?
I download php this day, its should be the latest version, I am on windows 11 OS.
Just enable xsl in php.ini. and this work fine
1 Like
hey , thank you for for providing these information , your information worked for me ,
Last issue solve and worked , can i ask different question here regarding Simplified QR data ?