Sample code for 30+ languages & platforms
Dart

Sign Bolivia Invoice XML

See more XML Digital Signatures Examples

Demonstrates how to create an XML digital signature (XmlDSig) for a Bolivia invoice (factura).

Chilkat Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // This example assumes the Chilkat API to have been previously unlocked.
  // See Global Unlock Sample for sample code.

  // Create the following XML to be signed:

  // <?xml version="1.0" encoding="UTF-8"?>
  // <facturaElectronicaCompraVenta xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="facturaElectronicaCompraVenta.xsd">
  //     <cabecera>
  //         <nitEmisor>99999999</nitEmisor>
  //         <razonSocialEmisor>Abc Xyz</razonSocialEmisor>
  //         <municipio>Cochabamba - Cochabamba</municipio>
  //         <telefono>4444444</telefono>
  //         <numeroFactura>417</numeroFactura>
  //         <cuf>ABABABABABABABABABABABABABABABABABABABABABABABABABABABABA</cuf>
  //         <cufd>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</cufd>
  //         <codigoSucursal>0</codigoSucursal>
  //         <direccion>aaa aaa aaa</direccion>
  //         <codigoPuntoVenta>1</codigoPuntoVenta>
  //         <fechaEmision>2023-04-13T22:43:22.417</fechaEmision>
  //         <nombreRazonSocial>xyz</nombreRazonSocial>
  //         <codigoTipoDocumentoIdentidad>1</codigoTipoDocumentoIdentidad>
  //         <numeroDocumento>1234567</numeroDocumento>
  //            <complemento xsi:nil="true"/>
  //         <codigoCliente>1234567</codigoCliente>
  //         <codigoMetodoPago>1</codigoMetodoPago>
  //            <numeroTarjeta xsi:nil="true"/>
  //         <montoTotal>22.00</montoTotal>
  //         <montoTotalSujetoIva>22.00</montoTotalSujetoIva>
  //         <codigoMoneda>1</codigoMoneda>
  //         <tipoCambio>1.00</tipoCambio>
  //         <montoTotalMoneda>22.00</montoTotalMoneda>
  //            <montoGiftCard xsi:nil="true"/>
  //         <descuentoAdicional>0.00</descuentoAdicional>
  //            <codigoExcepcion>1</codigoExcepcion>
  //            <cafc xsi:nil="true"/>
  //         <leyenda>Ley N� 453: El proveedor de servicios debe habilitar medios e instrumentos para efectuar consultas y reclamaciones.</leyenda>
  //         <usuario>nromero</usuario>
  //         <codigoDocumentoSector>1</codigoDocumentoSector>
  //     </cabecera>
  //     <detalle>
  //         <actividadEconomica>620100</actividadEconomica>
  //         <codigoProductoSin>123456</codigoProductoSin>
  //         <codigoProducto>1</codigoProducto>
  //         <descripcion>Economicos</descripcion>
  //         <cantidad>1.00</cantidad>
  //         <unidadMedida>58</unidadMedida>
  //         <precioUnitario>22.00</precioUnitario>
  //         <montoDescuento>0.00</montoDescuento>
  //         <subTotal>22.00</subTotal>
  //            <numeroSerie xsi:nil="true"/>
  //            <numeroImei xsi:nil="true"/>
  //     </detalle>
  // </facturaElectronicaCompraVenta>

  // Use this online tool to generate code from sample XML: 
  // Generate Code to Create XML

  final xml = CkXml();
  xml.tag = 'facturaElectronicaCompraVenta';
  xml.addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
  xml.addAttribute('xsi:noNamespaceSchemaLocation', 'facturaElectronicaCompraVenta.xsd');
  xml.updateChildContent('cabecera|nitEmisor', '99999999');
  xml.updateChildContent('cabecera|razonSocialEmisor', 'Abc Xyz');
  xml.updateChildContent('cabecera|municipio', 'Cochabamba - Cochabamba');
  xml.updateChildContent('cabecera|telefono', '4444444');
  xml.updateChildContent('cabecera|numeroFactura', '417');
  xml.updateChildContent('cabecera|cuf', 'ABABABABABABABABABABABABABABABABABABABABABABABABABABABABA');
  xml.updateChildContent('cabecera|cufd', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
  xml.updateChildContent('cabecera|codigoSucursal', '0');
  xml.updateChildContent('cabecera|direccion', 'aaa aaa aaa');
  xml.updateChildContent('cabecera|codigoPuntoVenta', '1');
  xml.updateChildContent('cabecera|fechaEmision', '2023-04-13T22:43:22.417');
  xml.updateChildContent('cabecera|nombreRazonSocial', 'xyz');
  xml.updateChildContent('cabecera|codigoTipoDocumentoIdentidad', '1');
  xml.updateChildContent('cabecera|numeroDocumento', '1234567');
  xml.updateAttrAt('cabecera|complemento', true, 'xsi:nil', 'true');
  xml.updateChildContent('cabecera|codigoCliente', '1234567');
  xml.updateChildContent('cabecera|codigoMetodoPago', '1');
  xml.updateAttrAt('cabecera|numeroTarjeta', true, 'xsi:nil', 'true');
  xml.updateChildContent('cabecera|montoTotal', '22.00');
  xml.updateChildContent('cabecera|montoTotalSujetoIva', '22.00');
  xml.updateChildContent('cabecera|codigoMoneda', '1');
  xml.updateChildContent('cabecera|tipoCambio', '1.00');
  xml.updateChildContent('cabecera|montoTotalMoneda', '22.00');
  xml.updateAttrAt('cabecera|montoGiftCard', true, 'xsi:nil', 'true');
  xml.updateChildContent('cabecera|descuentoAdicional', '0.00');
  xml.updateChildContent('cabecera|codigoExcepcion', '1');
  xml.updateAttrAt('cabecera|cafc', true, 'xsi:nil', 'true');
  xml.updateChildContent('cabecera|leyenda', 'Ley N� 453: El proveedor de servicios debe habilitar medios e instrumentos para efectuar consultas y reclamaciones.');
  xml.updateChildContent('cabecera|usuario', 'nromero');
  xml.updateChildContent('cabecera|codigoDocumentoSector', '1');
  xml.updateChildContent('detalle|actividadEconomica', '620100');
  xml.updateChildContent('detalle|codigoProductoSin', '123456');
  xml.updateChildContent('detalle|codigoProducto', '1');
  xml.updateChildContent('detalle|descripcion', 'Economicos');
  xml.updateChildContent('detalle|cantidad', '1.00');
  xml.updateChildContent('detalle|unidadMedida', '58');
  xml.updateChildContent('detalle|precioUnitario', '22.00');
  xml.updateChildContent('detalle|montoDescuento', '0.00');
  xml.updateChildContent('detalle|subTotal', '22.00');
  xml.updateAttrAt('detalle|numeroSerie', true, 'xsi:nil', 'true');
  xml.updateAttrAt('detalle|numeroImei', true, 'xsi:nil', 'true');

  final gen = CkXmlDSigGen();

  gen.sigLocation = 'facturaElectronicaCompraVenta';
  gen.sigLocationMod = 0;
  gen.sigNamespacePrefix = '';
  gen.sigNamespaceUri = 'http://www.w3.org/2000/09/xmldsig#';
  gen.signedInfoCanonAlg = 'C14N';
  gen.signedInfoDigestMethod = 'sha256';

  gen.addSameDocRef('', 'sha256', 'C14N_WithComments', '', '');

  // Provide your 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';

  gen.behaviors = 'EnvelopedTransformFirst';

  // Load XML to be signed...
  final sbXml = CkStringBuilder();
  xml.emitCompact = true;
  xml.getXmlSb(sbXml);

  // Sign the XML...
  try {
    gen.createXmlDSigSb(sbXml);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  // -----------------------------------------------

  // Save the signed XML to a file.
  sbXml.writeFile('qa_output/signedXml.xml', 'utf-8', true);

  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.');
}