Sample code for 30+ languages & platforms
Tcl

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 Tcl Downloads

Tcl

load ./chilkat.dll

set success 0

# This example assumes the Chilkat API to have been previously unlocked.
# See Global Unlock Sample for sample code.

set success 1

# 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

set xml [new_CkXml]

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

set gen [new_CkXmlDSigGen]

CkXmlDSigGen_put_SigLocation $gen "facturaElectronicaCompraVenta"
CkXmlDSigGen_put_SigLocationMod $gen 0
CkXmlDSigGen_put_SigNamespacePrefix $gen ""
CkXmlDSigGen_put_SigNamespaceUri $gen "http://www.w3.org/2000/09/xmldsig#"
CkXmlDSigGen_put_SignedInfoCanonAlg $gen "C14N"
CkXmlDSigGen_put_SignedInfoDigestMethod $gen "sha256"

CkXmlDSigGen_AddSameDocRef $gen "" "sha256" "C14N_WithComments" "" ""

# Provide your certificate + private key. (PFX password is test123)
set cert [new_CkCert]

set success [CkCert_LoadPfxFile $cert "qa_data/pfx/cert_test123.pfx" "test123"]
if {$success != 1} then {
    puts [CkCert_lastErrorText $cert]
    delete_CkXml $xml
    delete_CkXmlDSigGen $gen
    delete_CkCert $cert
    exit
}

CkXmlDSigGen_SetX509Cert $gen $cert 1

CkXmlDSigGen_put_KeyInfoType $gen "X509Data"
CkXmlDSigGen_put_X509Type $gen "Certificate"

CkXmlDSigGen_put_Behaviors $gen "EnvelopedTransformFirst"

# Load XML to be signed...
set sbXml [new_CkStringBuilder]

CkXml_put_EmitCompact $xml 1
CkXml_GetXmlSb $xml $sbXml

# Sign the XML...
set success [CkXmlDSigGen_CreateXmlDSigSb $gen $sbXml]
if {$success != 1} then {
    puts [CkXmlDSigGen_lastErrorText $gen]
    delete_CkXml $xml
    delete_CkXmlDSigGen $gen
    delete_CkCert $cert
    delete_CkStringBuilder $sbXml
    exit
}

# -----------------------------------------------

# Save the signed XML to a file.
set success [CkStringBuilder_WriteFile $sbXml "qa_output/signedXml.xml" "utf-8" 1]

puts [CkStringBuilder_getAsString $sbXml]

# ----------------------------------------
# Verify the signatures we just produced...
set verifier [new_CkXmlDSig]

set success [CkXmlDSig_LoadSignatureSb $verifier $sbXml]
if {$success != 1} then {
    puts [CkXmlDSig_lastErrorText $verifier]
    delete_CkXml $xml
    delete_CkXmlDSigGen $gen
    delete_CkCert $cert
    delete_CkStringBuilder $sbXml
    delete_CkXmlDSig $verifier
    exit
}

set numSigs [CkXmlDSig_get_NumSignatures $verifier]
set verifyIdx 0
while {$verifyIdx < $numSigs} {
    CkXmlDSig_put_Selector $verifier $verifyIdx
    set verified [CkXmlDSig_VerifySignature $verifier 1]
    if {$verified != 1} then {
        puts [CkXmlDSig_lastErrorText $verifier]
        delete_CkXml $xml
        delete_CkXmlDSigGen $gen
        delete_CkCert $cert
        delete_CkStringBuilder $sbXml
        delete_CkXmlDSig $verifier
        exit
    }

    set verifyIdx [expr $verifyIdx + 1]
}
puts "All signatures were successfully verified."

delete_CkXml $xml
delete_CkXmlDSigGen $gen
delete_CkCert $cert
delete_CkStringBuilder $sbXml
delete_CkXmlDSig $verifier