diff --git a/source/app/controllers/cfdi_xml.py b/source/app/controllers/cfdi_xml.py index 0351477..fc5087e 100644 --- a/source/app/controllers/cfdi_xml.py +++ b/source/app/controllers/cfdi_xml.py @@ -139,8 +139,9 @@ class CFDI(object): return self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8')) - def add_sello(self, sello): + def add_sello(self, sello, cert_txt): self._cfdi.attrib['Sello'] = sello + self._cfdi.attrib['Certificado'] = cert_txt return self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8')) def _to_pretty_xml(self, source): diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index e6d4505..bbcdf90 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -69,10 +69,12 @@ from settings import DEBUG, MV, log, template_lookup, COMPANIES, DB_SAT, \ PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES, DIR_FACTURAS from settings import USAR_TOKEN, API, DECIMALES_TAX -from .configpac import AUTH +# ~ from .configpac import AUTH # ~ v2 +from .cfdi_cert import SATCertificate + from settings import ( EXT, MXN, @@ -395,39 +397,34 @@ def to_slug(string): return value.replace(' ', '_') -def make_xml(data, certificado): - from .cfdi_xml import CFDI +# ~ def make_xml(data, certificado): + # ~ from .cfdi_xml import CFDI - token = _get_md5(certificado.rfc) - # ~ if USAR_TOKEN: - # ~ token = auth['PASS'] - # ~ if AUTH['DEBUG']: - # ~ token = AUTH['PASS'] + # ~ cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) + # ~ if DEBUG: + # ~ data['emisor']['Rfc'] = certificado.rfc + # ~ data['emisor']['RegimenFiscal'] = '603' - if DEBUG: - data['emisor']['Rfc'] = certificado.rfc - data['emisor']['RegimenFiscal'] = '603' + # ~ cfdi = CFDI() + # ~ xml = cfdi.get_xml(data) - cfdi = CFDI() - xml = cfdi.get_xml(data) + # ~ data = { + # ~ 'xsltproc': PATH_XSLTPROC, + # ~ 'xslt': _join(PATH_XSLT, 'cadena.xslt'), + # ~ 'xml': save_temp(xml, 'w'), + # ~ 'openssl': PATH_OPENSSL, + # ~ 'key': save_temp(certificado.key_enc, 'w'), + # ~ 'pass': token, + # ~ } + # ~ args = '"{xsltproc}" "{xslt}" "{xml}" | ' \ + # ~ '"{openssl}" dgst -sha256 -sign "{key}" -passin pass:"{pass}" | ' \ + # ~ '"{openssl}" enc -base64 -A'.format(**data) + # ~ sello = _call(args) - data = { - 'xsltproc': PATH_XSLTPROC, - 'xslt': _join(PATH_XSLT, 'cadena.xslt'), - 'xml': save_temp(xml, 'w'), - 'openssl': PATH_OPENSSL, - 'key': save_temp(certificado.key_enc, 'w'), - 'pass': token, - } - args = '"{xsltproc}" "{xslt}" "{xml}" | ' \ - '"{openssl}" dgst -sha256 -sign "{key}" -passin pass:"{pass}" | ' \ - '"{openssl}" enc -base64 -A'.format(**data) - sello = _call(args) + # ~ _kill(data['xml']) + # ~ _kill(data['key']) - _kill(data['xml']) - _kill(data['key']) - - return cfdi.add_sello(sello) + # ~ return cfdi.add_sello(sello) def timbra_xml(xml, auth): diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 413df7e..5250796 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -48,6 +48,8 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from dateutil import parser +from .cfdi_xml import CFDI + from settings import DEBUG, DB_COMPANIES, PATHS from .cfdi_cert import SATCertificate @@ -613,7 +615,7 @@ def get_client_balance(auth): pac = PACS[auth['pac']]() balance = pac.client_balance(auth) if pac.error: - balance = '-e' + balance = 'p/e' return balance @@ -625,3 +627,20 @@ def get_cert(args): return cert +def make_xml(data, certificado): + cert = SATCertificate(certificado.cer, certificado.key_enc.encode()) + if DEBUG: + data['emisor']['Rfc'] = certificado.rfc + data['emisor']['RegimenFiscal'] = '603' + + cfdi = CFDI() + xml = ET.parse(BytesIO(cfdi.get_xml(data).encode())) + + path_xslt = _join(PATHS['xslt'], 'cadena.xslt') + xslt = open(path_xslt, 'rb') + transfor = ET.XSLT(ET.parse(xslt)) + cadena = str(transfor(xml)).encode() + stamp = cert.sign(cadena) + xslt.close() + + return cfdi.add_sello(stamp, cert.cer_txt) diff --git a/source/app/models/main.py b/source/app/models/main.py index 414e786..1a3fd71 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -139,21 +139,26 @@ def validar_timbrar(): msg = 'Es necesario configurar un certificado de sellos' try: - obj = Certificado.select()[0] - except IndexError: + obj = Certificado.get(Certificado.es_fiel==False) + except Exception as e: return {'ok': False, 'msg': msg} if not obj.serie: return {'ok': False, 'msg': msg} - dias = obj.hasta - util.now() - if dias.days < 0: + diff = obj.hasta - utils.now() + if diff.days < 0: msg = 'El certificado ha vencido, es necesario cargar uno nuevo' return {'ok': False, 'msg': msg} + auth = Configuracion.get_({'fields': 'pac_auth'}) + if not auth: + msg = 'Es necesario configurar los datos de timbrado del PAC' + return {'ok': False, 'msg': msg} + msg = '' - if dias.days < 15: - msg = 'El certificado vence en: {} días.'.format(dias.days) + if diff.days < 15: + msg = 'El certificado vence en: {} días.'.format(diff.days) return {'ok': True, 'msg': msg} @@ -1079,15 +1084,13 @@ class Emisor(BaseModel): @classmethod def get_timbres(cls): - auth = cls.get_auth() - if not auth: - return 'c/e' + try: + obj = Emisor.select()[0] + except IndexError: + return 's/e' - pac = Configuracion.get_('lst_pac').lower() - if pac: - result = utils.get_client_balance(auth, pac) - else: - result = util.get_timbres(auth) + auth = Configuracion.get_({'fields': 'pac_auth'}) + result = utils.get_client_balance(auth) return result @classmethod @@ -4858,7 +4861,7 @@ class Facturas(BaseModel): frm_vu = FORMAT_PRECIO tmp = 0 emisor = Emisor.select()[0] - certificado = Certificado.select()[0] + certificado = Certificado.get(Certificado.es_fiel==False) is_edu = False comprobante = {} @@ -4888,7 +4891,7 @@ class Facturas(BaseModel): comprobante['Fecha'] = invoice.fecha.isoformat()[:19] comprobante['FormaPago'] = invoice.forma_pago comprobante['NoCertificado'] = certificado.serie - comprobante['Certificado'] = certificado.cer_txt + # ~ comprobante['Certificado'] = certificado.cer_txt comprobante['SubTotal'] = FORMAT.format(invoice.subtotal) comprobante['Moneda'] = invoice.moneda comprobante['TipoCambio'] = '1' @@ -5124,7 +5127,8 @@ class Facturas(BaseModel): 'complementos': complementos, } - return util.make_xml(data, certificado) + # ~ return util.make_xml(data, certificado) + return utils.make_xml(data, certificado) @classmethod def get_status_sat(cls, id): diff --git a/source/app/settings.py b/source/app/settings.py index ed389e4..3889ee2 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -217,6 +217,7 @@ PATHS = { 'BK': path_bk, 'LOCAL': path_local, 'SAT': path_sat, + 'xslt': PATH_XSLT, } VALUES_PDF = {