Dart
Dart
Paraguay E-Invoicing Signed XML (SIFEN)
See more XML Digital Signatures Examples
Demonstrates how to sign XML for e-invoicing -- SISTEMA INTEGRADO DE FACTURACIÓN ELECTRÓNICA NACIONAL (SIFEN). This is for signing XML files that need to be submitted to a government agency (Country Paraguay, SIFEN / EKUATIA, Sistema Nacional de Facturacion Electrónica).Chilkat Dart Downloads
import 'package:chilkat/chilkat.dart';
void main() {
// Create the XML to be signed...
// Use this online tool to generate code from sample XML:
// Generate Code to Create XML
final xmlToSign = CkXml();
xmlToSign.tag = 'rDE';
xmlToSign.addAttribute('xmlns', 'http://ekuatia.set.gov.py/sifen/xsd');
xmlToSign.addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
xmlToSign.addAttribute('xsi:schemaLocation', 'http://ekuatia.set.gov.py/sifen/xsd siRecepDE_v150.xsd');
xmlToSign.updateChildContent('dVerFor', '150');
xmlToSign.updateAttrAt('DE', true, 'Id', '01800228774059001001501012022091519999999990');
xmlToSign.updateChildContent('DE|dDVId', '0');
xmlToSign.updateChildContent('DE|dFecFirma', '2022-09-15T10:23:05');
xmlToSign.updateChildContent('DE|dSisFact', '1');
xmlToSign.updateChildContent('DE|gOpeDE|iTipEmi', '1');
xmlToSign.updateChildContent('DE|gOpeDE|dDesTipEmi', 'Normal');
xmlToSign.updateChildContent('DE|gOpeDE|dCodSeg', '999999999');
xmlToSign.updateChildContent('DE|gOpeDE|dInfoEmi', 'GENERADA DE PEDIDO 131043202');
xmlToSign.updateChildContent('DE|gTimb|iTiDE', '1');
xmlToSign.updateChildContent('DE|gTimb|dDesTiDE', 'Factura electr�nica');
xmlToSign.updateChildContent('DE|gTimb|dNumTim', '18889014');
xmlToSign.updateChildContent('DE|gTimb|dEst', '059');
xmlToSign.updateChildContent('DE|gTimb|dPunExp', '001');
xmlToSign.updateChildContent('DE|gTimb|dNumDoc', '0015010');
xmlToSign.updateChildContent('DE|gTimb|dFeIniT', '2022-05-25');
xmlToSign.updateChildContent('DE|gDatGralOpe|dFeEmiDE', '2022-09-15T10:22:57');
xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|iTipTra', '1');
xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|dDesTipTra', 'Venta de mercader�a');
xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|iTImp', '1');
xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|dDesTImp', 'IVA');
xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|cMoneOpe', 'PYG');
xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|dDesMoneOpe', 'Guarani');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dRucEm', '80022877');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDVEmi', '4');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|iTipCont', '1');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cTipReg', '1');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dNomEmi', 'ABCDEF SA');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dNomFanEmi', 'ABCDEF SA');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDirEmi', 'Jos� Abcde Xyz N� 666 e/Abxyz123');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dNumCas', '0');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dCompDir1', 'N/A');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dCompDir2', 'N/A');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cDepEmi', '12');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDesDepEmi', 'CENTRAL');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cDisEmi', '153');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDesDisEmi', 'CAPIATA');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cCiuEmi', '1234');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDesCiuEmi', 'CAPIATA');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dTelEmi', '(022) 1111 000');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dEmailE', 'somebody@example.com.py');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDenSuc', 'PUNTO 99');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|gActEco|cActEco', '47721');
xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|gActEco|dDesActEco', 'COMERCIO AL POR MENOR DE PRODUCTOS');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|iNatRec', '1');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|iTiOpe', '2');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|cPaisRec', 'PRY');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dDesPaisRe', 'Paraguay');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|iTiContRec', '2');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dRucRec', '80082971');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dDVRec', '9');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dNomRec', 'XXXXXXX');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dNomFanRec', 'XXXXXXX');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dNumCasRec', '0');
xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dCodCliente', '9999999');
xmlToSign.updateChildContent('DE|gDtipDE|gCamFE|iIndPres', '1');
xmlToSign.updateChildContent('DE|gDtipDE|gCamFE|dDesIndPres', 'Operaci�n presencial');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|iCondOpe', '1');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|dDCondOpe', 'Contado');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|iTiPago', '1');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|dDesTiPag', 'Efectivo');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|dMonTiPag', '100000.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|cMoneTiPag', 'PYG');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|dDMoneTiPag', 'Guarani');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|iTiPago', '1');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|dDesTiPag', 'Efectivo');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|dMonTiPag', '73600.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|cMoneTiPag', 'PYG');
xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|dDMoneTiPag', 'Guarani');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dCodInt', '818181');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dDesProSer', 'Widget Abc Xyz');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|cUniMed', '77');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dDesUniMed', 'UNI');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dCantProSer', '2.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|dPUniProSer', '16500.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|dTotBruOpeItem', '33000.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|gValorRestaItem|dDescItem', '3300.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|gValorRestaItem|dPorcDesIt', '20.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|gValorRestaItem|dTotOpeItem', '26400.0000');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|iAfecIVA', '1');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dDesAfecIVA', 'Gravado IVA');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dPropIVA', '100');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dTasaIVA', '5');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dBasGravIVA', '25142.8571');
xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dLiqIVAItem', '1257.1429');
xmlToSign.updateChildContent('DE|gTotSub|dSubExe', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dSub5', '26400.0000');
xmlToSign.updateChildContent('DE|gTotSub|dSub10', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotOpe', '26400.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotDesc', '6600.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotDescGlotem', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotAntItem', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotAnt', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dPorcDescTotal', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dDescTotal', '6600.0000');
xmlToSign.updateChildContent('DE|gTotSub|dAnticipo', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dRedon', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotGralOpe', '26400.0000');
xmlToSign.updateChildContent('DE|gTotSub|dIVA5', '1257.1429');
xmlToSign.updateChildContent('DE|gTotSub|dIVA10', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTotIVA', '1257.1429');
xmlToSign.updateChildContent('DE|gTotSub|dBaseGrav5', '25142.8571');
xmlToSign.updateChildContent('DE|gTotSub|dBaseGrav10', '0.0000');
xmlToSign.updateChildContent('DE|gTotSub|dTBasGraIVA', '25142.8571');
final gen = CkXmlDSigGen();
gen.sigLocation = 'rDE';
gen.sigLocationMod = 0;
gen.sigNamespacePrefix = '';
gen.sigNamespaceUri = 'http://www.w3.org/2000/09/xmldsig#';
gen.signedInfoCanonAlg = 'C14N';
gen.signedInfoDigestMethod = 'sha256';
// -------- Reference 1 --------
final xml1 = CkXml();
xml1.tag = 'Transforms';
xml1.updateAttrAt('Transform', true, 'Algorithm', 'http://www.w3.org/2000/09/xmldsig#enveloped-signature');
xml1.updateAttrAt('Transform[1]', true, 'Algorithm', 'http://www.w3.org/2001/10/xml-exc-c14n#');
gen.addSameDocRef2('01800228774059001001501012022091516941989060', 'sha256', xml1, '');
// Provide a certificate + private key. (PFX password is test123)
final cert = CkCert();
try {
cert.loadPfxFile('qa_data/pfx/cert_test123.pfx', 'test123');
} on ChilkatException catch (e) {
print(e.lastErrorText);
return;
}
gen.setX509Cert(cert, true);
gen.keyInfoType = 'X509Data';
gen.x509Type = 'Certificate';
// Load XML to be signed...
final sbXml = CkStringBuilder();
xmlToSign.getXmlSb(sbXml);
gen.behaviors = 'IndentedSignature';
// Sign the XML...
try {
gen.createXmlDSigSb(sbXml);
} on ChilkatException catch (e) {
print(e.lastErrorText);
return;
}
// -----------------------------------------------
// Save the signed XML to a file.
sbXml.writeFile('c:/temp/qa_output/signedXml.xml', 'utf-8', false);
print(sbXml.getAsString());
// ----------------------------------------
// Verify the signatures we just produced...
final verifier = CkXmlDSig();
try {
verifier.loadSignatureSb(sbXml);
} on ChilkatException catch (e) {
print(e.lastErrorText);
return;
}
final numSigs = verifier.numSignatures;
var verifyIdx = 0;
while (verifyIdx < numSigs) {
verifier.selector = verifyIdx;
try {
verifier.verifySignature(true);
} on ChilkatException catch (e) {
print(e.lastErrorText);
return;
}
verifyIdx++;
}
print('All signatures were successfully verified.');
}