From 01ccbcabd57906e41964c9115aa617c19e3cd916 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 11:32:01 -0600 Subject: [PATCH 01/16] =?UTF-8?q?Cambio=20de=20NameSpace=20en=20XML=20de?= =?UTF-8?q?=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ VERSION | 2 +- source/app/settings.py | 9 ++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9910ab1..21f3ca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +v 1.45.4 [24-Ene-2022] +---------------------- + - Error: Cambio de NameSpace del XML de cancelación + + v 1.45.3 [23-Ene-2022] ---------------------- - Error: El enviar por correo CFDI de pago. Ticket #40 diff --git a/VERSION b/VERSION index 1a5c268..bdcb000 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -1.45.3 +1.45.4 diff --git a/source/app/settings.py b/source/app/settings.py index eecb97a..786143f 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -42,7 +42,7 @@ except ImportError: DEBUG = DEBUG -VERSION = '1.45.3' +VERSION = '1.45.4' EMAIL_SUPPORT = ('soporte@empresalibre.mx',) TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION) @@ -256,7 +256,8 @@ DEFAULT_GLOBAL = { 'clave_sat': '01010101', } -TEMPLATE_CANCEL = """ +TEMPLATE_CANCEL = """ + @@ -289,5 +290,7 @@ TEMPLATE_CANCEL = """ -""" + +""" + # ~ TEMPLATE_CANCEL = """""" From c09a5749daa8fbc1f427eb507355cfb3968a3cec Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:04:26 -0600 Subject: [PATCH 02/16] =?UTF-8?q?Quitar=20declaraci=C3=B3n=20de=20encondin?= =?UTF-8?q?g=20en=20XML=20de=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/pacs/cfdi_cert.py | 5 +++-- source/app/controllers/utils.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index eb5ef5f..e90ab57 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -184,8 +184,9 @@ class SATCertificate(object): # ~ node = xmlsec.tree.find_node(tree, 'Modulus') # ~ node.text = node.text.replace('\n', '') - xml_signed = ET.tostring(tree, - xml_declaration=True, encoding='UTF-8').decode() + # ~ xml_signed = ET.tostring(tree, + # ~ xml_declaration=True, encoding='UTF-8').decode() + xml_signed = ET.tostring(tree, encoding='UTF-8').decode() return xml_signed diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 72312ef..f0eec46 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -799,7 +799,7 @@ def cancel_xml_sign(invoice, args, auth, certificado): template = TEMPLATE_CANCEL.format(**data) tree = ET.fromstring(template.encode()) sign_xml = cert.sign_xml(tree) - # ~ print(sign_xml) + print(sign_xml) result = pac.cancel_xml(sign_xml, auth, invoice.xml) From 121831a13959df7af70ef6616c825721f5cee2cf Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:08:17 -0600 Subject: [PATCH 03/16] =?UTF-8?q?Quitar=20saltos=20de=20l=C3=ADnea=20en=20?= =?UTF-8?q?XML=20de=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/utils.py | 2 +- source/app/settings.py | 74 ++++++++++++++++----------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index f0eec46..72312ef 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -799,7 +799,7 @@ def cancel_xml_sign(invoice, args, auth, certificado): template = TEMPLATE_CANCEL.format(**data) tree = ET.fromstring(template.encode()) sign_xml = cert.sign_xml(tree) - print(sign_xml) + # ~ print(sign_xml) result = pac.cancel_xml(sign_xml, auth, invoice.xml) diff --git a/source/app/settings.py b/source/app/settings.py index 786143f..bc1d03c 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -256,41 +256,41 @@ DEFAULT_GLOBAL = { 'clave_sat': '01010101', } -TEMPLATE_CANCEL = """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -""" +# ~ TEMPLATE_CANCEL = """ +# ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ + # ~ +# ~ +# ~ """ -# ~ TEMPLATE_CANCEL = """""" +TEMPLATE_CANCEL = """""" From 825e23e369a8d587a003eb16387fe67d6d5a24ef Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:15:27 -0600 Subject: [PATCH 04/16] Mostrar el request enviado --- .../pacs/comerciodigital/comercio.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/source/app/controllers/pacs/comerciodigital/comercio.py b/source/app/controllers/pacs/comerciodigital/comercio.py index b053c2e..d2bdf42 100644 --- a/source/app/controllers/pacs/comerciodigital/comercio.py +++ b/source/app/controllers/pacs/comerciodigital/comercio.py @@ -42,6 +42,23 @@ logging.getLogger('requests').setLevel(logging.ERROR) TIMEOUT = 10 +def pretty_print_POST(req): + """ + At this point it is completely built and ready + to be fired; it is "prepared". + + However pay attention at the formatting used in + this function because it is programmed to be pretty + printed and may differ from the actual request. + """ + print('{}\n{}\r\n{}\r\n\r\n{}'.format( + '-----------START-----------', + req.method + ' ' + req.url, + '\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()), + req.body, + )) + + class PACComercioDigital(object): ws = 'https://{}.comercio-digital.mx/{}' api = 'https://app2.comercio-digital.mx/{}' @@ -91,6 +108,7 @@ class PACComercioDigital(object): headers['host'] = url.split('/')[2] headers['Content-type'] = 'text/plain' headers['Connection'] = 'Keep-Alive' + headers['Expect'] = '100-continue' try: result = requests.post(url, data=data, headers=headers, timeout=TIMEOUT) @@ -251,6 +269,11 @@ class PACComercioDigital(object): url = self.URL['cancelxml'] headers = self._get_headers_cancel_xml(cfdi, info, auth) + + req = requests.Request('POST', url, headers=headers, data=xml) + prepared = req.prepare() + pretty_print_POST(prepared) + result = self._post(url, xml, headers) if result is None: From a0a8e0ce62453aefa85eee212fbc28301f6d2f35 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:21:21 -0600 Subject: [PATCH 05/16] =?UTF-8?q?Quitar=20KeyInfo=20del=20XML=20de=20cance?= =?UTF-8?q?laci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/pacs/cfdi_cert.py | 8 ++++---- source/app/controllers/pacs/comerciodigital/comercio.py | 9 ++++----- source/app/settings.py | 3 ++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index e90ab57..90cdf36 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -175,12 +175,12 @@ class SATCertificate(object): node = xmlsec.tree.find_node(tree, 'X509Certificate') node.text = self.cer_txt - # ~ node = xmlsec.tree.find_node(tree, 'X509IssuerName') - # ~ node.text = self.issuer + node = xmlsec.tree.find_node(tree, 'X509IssuerName') + node.text = self.issuer node = xmlsec.tree.find_node(tree, 'X509SerialNumber') node.text = self.serial_number - # ~ node = xmlsec.tree.find_node(tree, 'SignatureValue') - # ~ node.text = node.text.replace('\n', '') + node = xmlsec.tree.find_node(tree, 'SignatureValue') + node.text = node.text.replace('\n', '') # ~ node = xmlsec.tree.find_node(tree, 'Modulus') # ~ node.text = node.text.replace('\n', '') diff --git a/source/app/controllers/pacs/comerciodigital/comercio.py b/source/app/controllers/pacs/comerciodigital/comercio.py index d2bdf42..88be17d 100644 --- a/source/app/controllers/pacs/comerciodigital/comercio.py +++ b/source/app/controllers/pacs/comerciodigital/comercio.py @@ -110,6 +110,10 @@ class PACComercioDigital(object): headers['Connection'] = 'Keep-Alive' headers['Expect'] = '100-continue' + req = requests.Request('POST', url, headers=headers, data=data) + prepared = req.prepare() + pretty_print_POST(prepared) + try: result = requests.post(url, data=data, headers=headers, timeout=TIMEOUT) except ConnectionError as e: @@ -269,11 +273,6 @@ class PACComercioDigital(object): url = self.URL['cancelxml'] headers = self._get_headers_cancel_xml(cfdi, info, auth) - - req = requests.Request('POST', url, headers=headers, data=xml) - prepared = req.prepare() - pretty_print_POST(prepared) - result = self._post(url, xml, headers) if result is None: diff --git a/source/app/settings.py b/source/app/settings.py index bc1d03c..28e0ce5 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -293,4 +293,5 @@ DEFAULT_GLOBAL = { # ~ # ~ """ -TEMPLATE_CANCEL = """""" +# ~ TEMPLATE_CANCEL = """""" +TEMPLATE_CANCEL = """""" From 15a05e38f70d975fa3bba929d361c219be7b8c21 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:31:10 -0600 Subject: [PATCH 06/16] =?UTF-8?q?Agregar,=20de=20nuevo=20KeyInfo=20del=20X?= =?UTF-8?q?ML=20de=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/pacs/cfdi_cert.py | 4 ++-- source/app/settings.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index 90cdf36..3d101ec 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -181,8 +181,8 @@ class SATCertificate(object): node.text = self.serial_number node = xmlsec.tree.find_node(tree, 'SignatureValue') node.text = node.text.replace('\n', '') - # ~ node = xmlsec.tree.find_node(tree, 'Modulus') - # ~ node.text = node.text.replace('\n', '') + node = xmlsec.tree.find_node(tree, 'Modulus') + node.text = node.text.replace('\n', '') # ~ xml_signed = ET.tostring(tree, # ~ xml_declaration=True, encoding='UTF-8').decode() diff --git a/source/app/settings.py b/source/app/settings.py index 28e0ce5..7fa568d 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -293,5 +293,5 @@ DEFAULT_GLOBAL = { # ~ # ~ """ -# ~ TEMPLATE_CANCEL = """""" -TEMPLATE_CANCEL = """""" +TEMPLATE_CANCEL = """""" +# ~ TEMPLATE_CANCEL = """""" From 1bab1cb23c4bededc3ef98a262146f343f087f27 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:37:42 -0600 Subject: [PATCH 07/16] =?UTF-8?q?Quitar=20todos=20los=20saltos=20de=20l?= =?UTF-8?q?=C3=ADnea=20del=20XML=20de=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/pacs/cfdi_cert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index 3d101ec..ce9bb1e 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -186,7 +186,7 @@ class SATCertificate(object): # ~ xml_signed = ET.tostring(tree, # ~ xml_declaration=True, encoding='UTF-8').decode() - xml_signed = ET.tostring(tree, encoding='UTF-8').decode() + xml_signed = ET.tostring(tree, encoding='UTF-8').decode().replace('\n', '') return xml_signed From b16eabd77359a56db4360f03dd045b776b48ec06 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:43:28 -0600 Subject: [PATCH 08/16] =?UTF-8?q?Quitar=20nodo=20KeyInfo=20del=20XML=20de?= =?UTF-8?q?=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/pacs/cfdi_cert.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index ce9bb1e..2c6afc2 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -181,8 +181,8 @@ class SATCertificate(object): node.text = self.serial_number node = xmlsec.tree.find_node(tree, 'SignatureValue') node.text = node.text.replace('\n', '') - node = xmlsec.tree.find_node(tree, 'Modulus') - node.text = node.text.replace('\n', '') + # ~ node = xmlsec.tree.find_node(tree, 'Modulus') + # ~ node.text = node.text.replace('\n', '') # ~ xml_signed = ET.tostring(tree, # ~ xml_declaration=True, encoding='UTF-8').decode() From 12774af7acfd3144fabcc7af476731e544a08b3b Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 12:47:57 -0600 Subject: [PATCH 09/16] =?UTF-8?q?Quitar=20nodo=20KeyInfo=20del=20XML=20de?= =?UTF-8?q?=20cancelaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/app/settings.py b/source/app/settings.py index 7fa568d..28e0ce5 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -293,5 +293,5 @@ DEFAULT_GLOBAL = { # ~ # ~ """ -TEMPLATE_CANCEL = """""" -# ~ TEMPLATE_CANCEL = """""" +# ~ TEMPLATE_CANCEL = """""" +TEMPLATE_CANCEL = """""" From 0422eece407e86212b7d9ddf7923dae38635803d Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 15:45:40 -0600 Subject: [PATCH 10/16] =?UTF-8?q?Prueba=20de=20cancelaci=C3=B3n=20con=20UU?= =?UTF-8?q?ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/pacs/cfdi_cert.py | 4 ++-- source/app/controllers/utils.py | 10 +++++----- source/app/settings.py | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index 2c6afc2..ce9bb1e 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -181,8 +181,8 @@ class SATCertificate(object): node.text = self.serial_number node = xmlsec.tree.find_node(tree, 'SignatureValue') node.text = node.text.replace('\n', '') - # ~ node = xmlsec.tree.find_node(tree, 'Modulus') - # ~ node.text = node.text.replace('\n', '') + node = xmlsec.tree.find_node(tree, 'Modulus') + node.text = node.text.replace('\n', '') # ~ xml_signed = ET.tostring(tree, # ~ xml_declaration=True, encoding='UTF-8').decode() diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 72312ef..2993a00 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -765,9 +765,9 @@ def get_pac_by_rfc(cfdi): def _cancel_with_cert(invoice, args, auth, certificado): cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) pac = PACS[auth['pac']]() - info = {'cer': cert.cer_pem, 'key': cert.key_pem, 'pass': '', 'args': args} - # ~ info = {'cer': cert.cer_pem, 'key': cert.key_pem, - # ~ 'key_enc': cert._key_der, 'pass': cert._p, 'args': args} + # ~ info = {'cer': cert.cer_pem, 'key': cert.key_pem, 'pass': '', 'args': args} + info = {'cer': cert.cer_pem, 'key': cert.key_pem, + 'key_enc': cert._key_der, 'pass': cert._p, 'args': args} result = pac.cancel(invoice.xml, info, auth) if pac.error: @@ -781,8 +781,8 @@ def _cancel_with_cert(invoice, args, auth, certificado): def cancel_xml_sign(invoice, args, auth, certificado): - if auth['pac'] == 'finkok': - return _cancel_with_cert(invoice, args, auth, certificado) + # ~ if auth['pac'] == 'finkok': + return _cancel_with_cert(invoice, args, auth, certificado) cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) pac = PACS[auth['pac']]() diff --git a/source/app/settings.py b/source/app/settings.py index 28e0ce5..bc1d03c 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -293,5 +293,4 @@ DEFAULT_GLOBAL = { # ~ # ~ """ -# ~ TEMPLATE_CANCEL = """""" -TEMPLATE_CANCEL = """""" +TEMPLATE_CANCEL = """""" From 702aa264d85858bd94de2e80f6e27d94ba186492 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Jan 2022 17:05:41 -0600 Subject: [PATCH 11/16] Agregar certificado original --- source/app/controllers/pacs/comerciodigital/comercio.py | 2 +- source/app/controllers/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/app/controllers/pacs/comerciodigital/comercio.py b/source/app/controllers/pacs/comerciodigital/comercio.py index 88be17d..e484c37 100644 --- a/source/app/controllers/pacs/comerciodigital/comercio.py +++ b/source/app/controllers/pacs/comerciodigital/comercio.py @@ -172,7 +172,7 @@ class PACComercioDigital(object): def _get_data_cancel(self, cfdi, info, auth): info['tipo'] = 'cfdi' info['key'] = base64.b64encode(info['key_enc']).decode() - info['cer'] = base64.b64encode(info['cer']).decode() + info['cer'] = base64.b64encode(info['cer_ori']).decode() NS_CFDI = { 'cfdi': 'http://www.sat.gob.mx/cfd/3', diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 2993a00..491c7e2 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -766,7 +766,7 @@ def _cancel_with_cert(invoice, args, auth, certificado): cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) pac = PACS[auth['pac']]() # ~ info = {'cer': cert.cer_pem, 'key': cert.key_pem, 'pass': '', 'args': args} - info = {'cer': cert.cer_pem, 'key': cert.key_pem, + info = {'cer': cert.cer_pem, 'key': cert.key_pem, 'cer_ori': cert.cer, 'key_enc': cert._key_der, 'pass': cert._p, 'args': args} result = pac.cancel(invoice.xml, info, auth) From a38247727ca96b1d6ac5b9733ba0a1006925d838 Mon Sep 17 00:00:00 2001 From: El Mau Date: Tue, 25 Jan 2022 19:12:41 -0600 Subject: [PATCH 12/16] Error al timbrar Carta Porte --- CHANGELOG.md | 7 ++++-- source/app/controllers/pacs/cfdi_cert.py | 25 +++++++++++-------- .../pacs/comerciodigital/comercio.py | 7 +++--- source/app/controllers/utils.py | 4 +-- source/app/models/main.py | 5 +++- source/app/settings.py | 2 +- source/static/js/ui/invoices.js | 2 +- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21f3ca5..bbaaabc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ -v 1.45.4 [24-Ene-2022] +v 1.45.4 [25-Ene-2022] ---------------------- - - Error: Cambio de NameSpace del XML de cancelación + - Error: Al timbrar carta porte. + - Error: Al cancelar con Comercio Digital. + +* IMPORTANTE: Es necesario subir de nuevo tus certificados de sello, **solo** si timbras con Comercio Digital. v 1.45.3 [23-Ene-2022] diff --git a/source/app/controllers/pacs/cfdi_cert.py b/source/app/controllers/pacs/cfdi_cert.py index ce9bb1e..2af68e0 100644 --- a/source/app/controllers/pacs/cfdi_cert.py +++ b/source/app/controllers/pacs/cfdi_cert.py @@ -28,18 +28,18 @@ class SATCertificate(object): self._init_values() self._get_data_cer(cer) self._get_data_key(key, password) - if not password: - self._test() + # ~ if not password: + # ~ self._test() - def _test(self): - key = self._get_key('') - self._p = TOKEN - self._key_der = key.private_bytes( - encoding=serialization.Encoding.DER, - format=serialization.PrivateFormat.PKCS8, - encryption_algorithm=serialization.BestAvailableEncryption(self._p.encode()) - ) - return + # ~ def _test(self): + # ~ key = self._get_key('') + # ~ self._p = '' + # ~ self._key_der = key.private_bytes( + # ~ encoding=serialization.Encoding.DER, + # ~ format=serialization.PrivateFormat.PKCS8, + # ~ encryption_algorithm=serialization.BestAvailableEncryption(self._p.encode()) + # ~ ) + # ~ return def _init_values(self): self._rfc = '' @@ -52,6 +52,7 @@ class SATCertificate(object): self._is_fiel = False self._are_couple = False self._is_valid_time = False + self._key = b'' self._cer = b'' self._cer_pem = '' self._cer_txt = '' @@ -110,6 +111,8 @@ class SATCertificate(object): return def _get_data_key(self, key, password): + self._key = key + self._keyp = password self._key_enc = key if not key or not password: return diff --git a/source/app/controllers/pacs/comerciodigital/comercio.py b/source/app/controllers/pacs/comerciodigital/comercio.py index e484c37..e930278 100644 --- a/source/app/controllers/pacs/comerciodigital/comercio.py +++ b/source/app/controllers/pacs/comerciodigital/comercio.py @@ -110,9 +110,10 @@ class PACComercioDigital(object): headers['Connection'] = 'Keep-Alive' headers['Expect'] = '100-continue' - req = requests.Request('POST', url, headers=headers, data=data) - prepared = req.prepare() - pretty_print_POST(prepared) + if DEBUG: + req = requests.Request('POST', url, headers=headers, data=data) + prepared = req.prepare() + pretty_print_POST(prepared) try: result = requests.post(url, data=data, headers=headers, timeout=TIMEOUT) diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 491c7e2..8e02fe3 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -767,7 +767,7 @@ def _cancel_with_cert(invoice, args, auth, certificado): pac = PACS[auth['pac']]() # ~ info = {'cer': cert.cer_pem, 'key': cert.key_pem, 'pass': '', 'args': args} info = {'cer': cert.cer_pem, 'key': cert.key_pem, 'cer_ori': cert.cer, - 'key_enc': cert._key_der, 'pass': cert._p, 'args': args} + 'key_enc': certificado.key, 'pass': decrypt(bytes(certificado.p12).decode(), certificado.serie), 'args': args} result = pac.cancel(invoice.xml, info, auth) if pac.error: @@ -796,11 +796,11 @@ def cancel_xml_sign(invoice, args, auth, certificado): 'motivo': args['reason'], 'folio': folio_new, } + template = TEMPLATE_CANCEL.format(**data) tree = ET.fromstring(template.encode()) sign_xml = cert.sign_xml(tree) # ~ print(sign_xml) - result = pac.cancel_xml(sign_xml, auth, invoice.xml) if pac.error: diff --git a/source/app/models/main.py b/source/app/models/main.py index 1a4c8f4..254af18 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -1167,9 +1167,12 @@ class Certificado(BaseModel): result['msg'] = 'El RFC del certificado no corresponde.' return result + obj.key = cert._key obj.key_enc = cert.key_enc obj.cer = cert.cer obj.serie = cert.serial_number + obj.cer_txt = cert.cer_txt + obj.p12 = utils.encrypt(cert._keyp, cert.serial_number) obj.desde = cert.not_before obj.hasta = cert.not_after obj.save() @@ -5357,7 +5360,7 @@ class Facturas(BaseModel): ubicaciones = values['ubicaciones'] for ubicacion in ubicaciones: - if 'DistanciaRecorrida' in ubicacion: + if 'DistanciaRecorrida' in ubicacion and ubicacion['DistanciaRecorrida'].strip(): total_distance += float(ubicacion['DistanciaRecorrida']) if isinstance(ubicacion['DistanciaRecorrida'], (int, float)): ubicacion['DistanciaRecorrida'] = f"{ubicacion['DistanciaRecorrida']:.2f}" diff --git a/source/app/settings.py b/source/app/settings.py index bc1d03c..8765bc4 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -293,4 +293,4 @@ DEFAULT_GLOBAL = { # ~ # ~ """ -TEMPLATE_CANCEL = """""" +TEMPLATE_CANCEL = """""" diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 6a05e3c..92dc3a1 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -746,7 +746,7 @@ var opt_clave_entidad = [ {id: 'GRO', value: 'Guerrero'}, {id: 'HID', value: 'Hidalgo'}, {id: 'JAL', value: 'Jalisco'}, - {id: 'MEX', value: 'México'}, + {id: 'MEX', value: 'Estado de México'}, {id: 'MIC', value: 'Michoacán'}, {id: 'MOR', value: 'Morelos'}, {id: 'NAC', value: 'Nacional'}, From 480ec57d1e93344970e5ba1c84668b2a457e6d1f Mon Sep 17 00:00:00 2001 From: El Mau Date: Tue, 25 Jan 2022 19:33:05 -0600 Subject: [PATCH 13/16] Error al timbrar Carta Porte --- source/app/models/main.py | 2 +- source/static/js/ui/invoices.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/app/models/main.py b/source/app/models/main.py index 254af18..8ff48f9 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -5360,7 +5360,7 @@ class Facturas(BaseModel): ubicaciones = values['ubicaciones'] for ubicacion in ubicaciones: - if 'DistanciaRecorrida' in ubicacion and ubicacion['DistanciaRecorrida'].strip(): + if 'DistanciaRecorrida' in ubicacion and ubicacion['DistanciaRecorrida']: total_distance += float(ubicacion['DistanciaRecorrida']) if isinstance(ubicacion['DistanciaRecorrida'], (int, float)): ubicacion['DistanciaRecorrida'] = f"{ubicacion['DistanciaRecorrida']:.2f}" diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 92dc3a1..7014d5d 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -881,7 +881,7 @@ var opt_carta_estados = [ {id: 'GRO', value: 'Guerrero'}, {id: 'HID', value: 'Hidalgo'}, {id: 'JAL', value: 'Jalisco'}, - {id: 'MEX', value: 'México'}, + {id: 'MEX', value: 'Estado de México'}, {id: 'MIC', value: 'Michoacán'}, {id: 'MOR', value: 'Morelos'}, {id: 'NAC', value: 'Nacional'}, From 8f74d24b14e7237ea360b54ba54208da8cb8ac35 Mon Sep 17 00:00:00 2001 From: El Mau Date: Wed, 26 Jan 2022 18:01:27 -0600 Subject: [PATCH 14/16] Fix - Issue #42 --- source/app/controllers/main.py | 10 ++++++++++ source/static/js/controller/invoices.js | 16 ---------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 7943af5..1b333ed 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -2,6 +2,7 @@ import falcon from middleware import get_template +from urllib.parse import unquote class AppEmpresas(object): @@ -111,6 +112,14 @@ class AppValues(object): def on_get(self, req, resp, table): values = req.params session = req.env['beaker.session'] + + if table == 'product': + original = values['name'] + try: + values['name'] = unquote(req.query_string.split('=')[1]) + except Exception as e: + values['name'] = original + if req.path in ('/values/titlelogin', '/values/empresas'): req.context['result'] = self._db.get_values(table, values, session) resp.status = falcon.HTTP_200 @@ -280,6 +289,7 @@ class AppProducts(object): def on_get(self, req, resp): values = req.params user = req.env['beaker.session']['userobj'] + if 'opt' in values: req.context['result'] = self._db.products_get(values, user) else: diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 8b2802c..6fd607f 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -1097,22 +1097,6 @@ function search_product_by_key(key){ } } }) - - //~ webix.ajax().get('/values/productokey', {'key': key}, { - //~ error: function(text, data, xhr) { - //~ msg_error('Error al consultar') - //~ }, - //~ success: function(text, data, xhr){ - //~ var values = data.json() - //~ if (values.ok){ - //~ set_product(values) - //~ } else { - //~ msg = 'No se encontró un producto con la clave: ' + key - //~ msg_error(msg) - //~ } - //~ } - //~ }) - } From e992103c575c1b59547c2fcf0bb598e52be6f7e5 Mon Sep 17 00:00:00 2001 From: El Mau Date: Wed, 26 Jan 2022 18:12:18 -0600 Subject: [PATCH 15/16] Fix - Issue #44 --- source/app/models/main.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/app/models/main.py b/source/app/models/main.py index 8ff48f9..3cf4462 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -4161,6 +4161,12 @@ class Productos(BaseModel): msg = 'Ya existe un producto con esta clave' data = {'ok': False, 'row': {}, 'new': False, 'msg': msg} return data + except Exception as e: + msg = str(e) + if 'productos_clave' in msg: + msg = 'Ya existe un producto con esta clave' + data = {'ok': False, 'row': {}, 'new': False, 'msg': msg} + return data obj = Productos.get(Productos.id==id) obj.impuestos = obj_taxes From 34df8882b3152225b632898838481330f49cb731 Mon Sep 17 00:00:00 2001 From: El Mau Date: Wed, 26 Jan 2022 22:28:15 -0600 Subject: [PATCH 16/16] Actualizar lista de cambios --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbaaabc..7059555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ v 1.45.4 [25-Ene-2022] ---------------------- - Error: Al timbrar carta porte. - Error: Al cancelar con Comercio Digital. + - Error: Issue #42 + - Mejora: Issue #44 * IMPORTANTE: Es necesario subir de nuevo tus certificados de sello, **solo** si timbras con Comercio Digital.