diff --git a/facho/cli.py b/facho/cli.py index 8d81df0..b30b1a9 100644 --- a/facho/cli.py +++ b/facho/cli.py @@ -216,7 +216,8 @@ def validate_invoice(invoice_path): @click.option('--ssl/--no-ssl', default=False) @click.option('--use-cache-policy/--no-use-cache-policy', default=False) @click.argument('xmlfile', type=click.Path(exists=True), required=True) -def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False): +@click.argument('output', required=True) +def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False, output=None): if not ssl: disable_ssl() @@ -226,7 +227,8 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False) signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) document = open(xmlfile, 'r').read().encode('utf-8') - print(signer.sign_xml_string(document)) + with open(output, 'w') as f: + f.write(signer.sign_xml_string(document)) @click.command() @click.option('--private-key', type=click.Path(exists=True)) @@ -236,7 +238,8 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False) @click.option('--sign/--no-sign', default=False) @click.option('--use-cache-policy/--no-use-cache-policy', default=False) @click.argument('scriptname', type=click.Path(exists=True), required=True) -def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=True, sign=False, use_cache_policy=False): +@click.argument('output', required=True) +def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=True, sign=False, use_cache_policy=False, output=None): """ imprime xml en pantalla. SCRIPTNAME espera @@ -270,12 +273,14 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr for extension in extensions: xml.add_extension(extension) - xmlstring = xml.tostringMACHETE(xml_declaration=True) + xmlstring = xml.tostringMACHETE(xml_declaration=True, encoding='UTF-8') if sign: signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) - print(signer.sign_xml_string(xmlstring.encode('utf-8'))) + with open(output, 'w') as f: + f.write(signer.sign_xml_string(xmlstring.encode('utf-8'))) else: - print(xmlstring) + with open(output, 'w') as f: + f.write(xmlstring) @click.group() def main(): diff --git a/facho/fe/fe.py b/facho/fe/fe.py index 30e8bc5..7de3ed2 100644 --- a/facho/fe/fe.py +++ b/facho/fe/fe.py @@ -202,7 +202,7 @@ class DianXMLExtensionSigner(FachoXMLExtension): extcontent = fachoxml.builder.xpath(fachoxml.root, '/fe:Invoice/ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent') fachoxml.append_element(extcontent, signature) - return fachoxml.tostring(xml_declaration=True) + return fachoxml.tostring(xml_declaration=True, encoding='UTF-8') def sign_xml_element(self, xml): id_uuid = str(uuid.uuid4()) @@ -226,23 +226,17 @@ class DianXMLExtensionSigner(FachoXMLExtension): ki = xmlsig.template.ensure_key_info(signature, name=id_keyinfo) data = xmlsig.template.add_x509_data(ki) xmlsig.template.x509_data_add_certificate(data) - - xmlsig.template.add_key_value(ki) - qualifying = xades.template.create_qualifying_properties(signature) + + qualifying = xades.template.create_qualifying_properties(signature, 'XadesObjects', 'xades') xades.utils.ensure_id(qualifying) - id_props = "xmldsig-%s-signedprops" % (id_uuid) - # MACHETE si no lo envio la dian no lo valida y pasa - # si lo adiciono https://tools.chilkat.io/xmlDsigVerify.cshtml - # falla en validar este reference.. - - #props_ref = xmlsig.template.add_reference( - # signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_props), - # uri_type="http://uri.etsi.org/01903#SignedProperties" - #) - #xmlsig.template.add_transform(props_ref, xmlsig.constants.TransformInclC14N) + props_ref = xmlsig.template.add_reference( + signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_props), + uri_type="http://uri.etsi.org/01903#SignedProperties" + ) + xmlsig.template.add_transform(props_ref, xmlsig.constants.TransformInclC14N) # TODO assert with http://www.sic.gov.co/hora-legal-colombiana props = xades.template.create_signed_properties(qualifying, name=id_props, datetime=datetime.now())