Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(Unicode C++) Apply 2nd Signature to sii.cl Factura Electrónica (Chile Servicio de Impuestos Internos)Demonstrates how to apply the 2nd signature an XML invoice according to Chilean Internal Revenue Service regulations.
#include <CkXmlDSigGenW.h> #include <CkCertW.h> #include <CkXmlW.h> #include <CkStringBuilderW.h> void ChilkatSample(void) { // This example assumes the Chilkat API to have been previously unlocked. // See Global Unlock Sample for sample code. // In this example: Create sii.cl Factura Electr�nica (Chile Servicio de Impuestos Internos) // We signed XML structured like this: // <?xml version="1.0" encoding="iso-8859-1"?> // <DTE version="1.0" xmlns="http://www.sii.cl/SiiDte"> // <Documento ID="F11T22"> // ... // </Documento> // </DTE> // To get a signature like this: // <?xml version="1.0" encoding="iso-8859-1"?> // <DTE version="1.0" xmlns="http://www.sii.cl/SiiDte"> // <Documento ID="F11T22"> // ... // </Documento> // <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> // .. // </Signature> // </DTE> // Now we wish to wrap the result of the 1st example in the following and sign again: // <?xml version="1.0" encoding="iso-8859-1"?> // <EnvioDTE version="1.0" xmlns="http://www.sii.cl/SiiDte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sii.cl/SiiDte EnvioDTE_v10.xsd"> // <SetDTE ID="NDTECHILE"> // <Caratula version="1.0"> // <RutEmisor>...</RutEmisor> // <RutEnvia>...</RutEnvia> // <RutReceptor>...</RutReceptor> // <FchResol>2014-08-22</FchResol> // <NroResol>80</NroResol> // <TmstFirmaEnv>2020-07-17T13:19:10</TmstFirmaEnv> // <SubTotDTE> // <TpoDTE>34</TpoDTE> // <NroDTE>1</NroDTE> // </SubTotDTE> // </Caratula> // <DTE version="1.0" xmlns="http://www.sii.cl/SiiDte"> // <Documento ID="F11T22">...</Documento> // <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">..</Signature> // </DTE> // </SetDTE> // </EnvioDTE> // The result will be this: // <?xml version="1.0" encoding="iso-8859-1"?> // <EnvioDTE version="1.0" xmlns="http://www.sii.cl/SiiDte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sii.cl/SiiDte EnvioDTE_v10.xsd"> // <SetDTE ID="NDTECHILE"> // <Caratula version="1.0"> // <RutEmisor>...</RutEmisor> // <RutEnvia>...</RutEnvia> // <RutReceptor>...</RutReceptor> // <FchResol>2014-08-22</FchResol> // <NroResol>80</NroResol> // <TmstFirmaEnv>2020-07-17T13:19:10</TmstFirmaEnv> // <SubTotDTE> // <TpoDTE>34</TpoDTE> // <NroDTE>1</NroDTE> // </SubTotDTE> // </Caratula> // <DTE version="1.0" xmlns="http://www.sii.cl/SiiDte"> // <Documento ID="F11T22">...</Documento> // <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">..</Signature> // </DTE> // </SetDTE> // <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">..</Signature> // </EnvioDTE> CkXmlDSigGenW gen; gen.put_SigLocation(L"EnvioDTE"); gen.put_SigLocationMod(0); gen.put_SigNamespacePrefix(L""); gen.put_SigNamespaceUri(L"http://www.w3.org/2000/09/xmldsig#"); gen.put_SignedInfoCanonAlg(L"C14N"); gen.put_SignedInfoDigestMethod(L"sha1"); // -------- Reference 1 -------- gen.AddSameDocRef(L"NDTECHILE",L"sha1",L"",L"",L""); // Provide a certificate + private key. (PFX password is test123) CkCertW cert; bool success = cert.LoadPfxFile(L"qa_data/pfx/cert_test123.pfx",L"test123"); if (success != true) { wprintf(L"%s\n",cert.lastErrorText()); return; } gen.SetX509Cert(cert,true); gen.put_KeyInfoType(L"X509Data+KeyValue"); gen.put_X509Type(L"Certificate"); // Here's the part where we must be very careful not to disturb the existing signature. // We want to encapsulate the existing signed XML like this: // <?xml version="1.0" encoding="iso-8859-1"?> // <EnvioDTE version="1.0" xmlns="http://www.sii.cl/SiiDte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sii.cl/SiiDte EnvioDTE_v10.xsd"> // <SetDTE ID="NDTECHILE"> // <Caratula version="1.0"> // <RutEmisor>...</RutEmisor> // <RutEnvia>...</RutEnvia> // <RutReceptor>...</RutReceptor> // <FchResol>2014-08-22</FchResol> // <NroResol>80</NroResol> // <TmstFirmaEnv>2020-07-17T13:19:10</TmstFirmaEnv> // <SubTotDTE> // <TpoDTE>34</TpoDTE> // <NroDTE>1</NroDTE> // </SubTotDTE> // </Caratula> // <EXISTING_SIGNED_XML>HERE</EXISTING_SIGNED_XML> // </SetDTE> // <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">..</Signature> // </EnvioDTE> CkXmlW xml; xml.put_Tag(L"EnvioDTE"); xml.AddAttribute(L"version",L"1.0"); xml.AddAttribute(L"xmlns",L"http://www.sii.cl/SiiDte"); xml.AddAttribute(L"xmlns:xsi",L"http://www.w3.org/2001/XMLSchema-instance"); xml.AddAttribute(L"xsi:schemaLocation",L"http://www.sii.cl/SiiDte EnvioDTE_v10.xsd"); xml.UpdateAttrAt(L"SetDTE",true,L"ID",L"NDTECHILE"); xml.UpdateAttrAt(L"SetDTE|Caratula",true,L"version",L"1.0"); xml.UpdateChildContent(L"SetDTE|Caratula|RutEmisor",L"..."); xml.UpdateChildContent(L"SetDTE|Caratula|RutEnvia",L"..."); xml.UpdateChildContent(L"SetDTE|Caratula|RutReceptor",L"..."); xml.UpdateChildContent(L"SetDTE|Caratula|FchResol",L"2014-08-22"); xml.UpdateChildContent(L"SetDTE|Caratula|NroResol",L"80"); xml.UpdateChildContent(L"SetDTE|Caratula|TmstFirmaEnv",L"2020-07-17T13:19:10"); xml.UpdateChildContent(L"SetDTE|Caratula|SubTotDTE|TpoDTE",L"34"); xml.UpdateChildContent(L"SetDTE|Caratula|SubTotDTE|NroDTE",L"1"); xml.UpdateChildContent(L"SetDTE|EXISTING_SIGNED_XML",L"HERE"); CkStringBuilderW sbXml; xml.GetXmlSb(sbXml); // Load our existing signed XML. // We cannot load it into a Chilkat XML object because we cannot allow anything to change, // not even indentation or whitespace. CkStringBuilderW sbExisting; sbExisting.LoadFile(L"qa_data/xml_dsig/sii_cl/signed1.xml",L"iso-8859-1"); // However, we must remove the XML declarator, and we can trim the whitespace at the very front and back (i.e. whitespace completely outside the document). int numReplaced = sbExisting.Replace(L"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>",L""); sbExisting.Trim(); // Insert the existing signed XML into the new XML document to be signed. numReplaced = sbXml.Replace(L"<EXISTING_SIGNED_XML>HERE</EXISTING_SIGNED_XML>",sbExisting.getAsString()); // We now have the XML document ready for the 2nd signature to be applied... // Make sure we add the "SignExistingSignatures" behavior so that this signature includes the original signature in the digest. gen.put_Behaviors(L"IndentedSignature,SignExistingSignatures"); // Sign the XML... success = gen.CreateXmlDSigSb(sbXml); if (success != true) { wprintf(L"%s\n",gen.lastErrorText()); return; } // ----------------------------------------------- // Change the XML declarator to indicate iso-8859-1 (because we'll be saving using iso-8859-1) numReplaced = sbXml.Replace(L"encoding=\"utf-8\"?>",L"encoding=\"iso-8859-1\"?>"); // Save the signed XML to a file. success = sbXml.WriteFile(L"qa_data/xml_dsig/sii_cl/signed2.xml",L"iso-8859-1",false); wprintf(L"%s\n",sbXml.getAsString()); } |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.