Compare commits

...

28 Commits

Author SHA1 Message Date
El Mau a5b2a17d8c Cambios en el SAT 2022-03-27 22:17:40 -06:00
El Mau 93a273a841 Actualizar CHANGELOG 2022-03-27 22:17:13 -06:00
El Mau 36d2ce887b Cambios en el SAT 2022-03-27 22:15:42 -06:00
El Mau 0be7f898c1 Agregar nuevos PDFs de documentación 2022-03-14 13:03:22 -06:00
El Mau d6d6877c74 Cambios en el SAT 2022-03-10 15:25:40 -06:00
El Mau b1b73dae9f Validar fiel en todos los procesos 2022-02-09 22:17:00 -06:00
El Mau 1e2cac87e9 Validar FIEL en cada proceso 2022-02-09 21:39:50 -06:00
El Mau 99850bf14f Cambiar la lógica de descarga para evitar el error de token caducado 2022-02-06 11:17:30 -06:00
El Mau fb70cce117 Actualizar VERSION 2022-02-06 11:15:31 -06:00
El Mau 5416cff566 Mostrar fechas de descarga y token 2022-02-06 11:14:51 -06:00
El Mau 72fa18f511 Se cambia la lógica para evitar que el token caduque 2022-02-05 22:22:24 -06:00
Mauricio Baeza 7e69d19501 Agregar soporte para descargar metadatos 2021-09-02 23:39:11 -05:00
Mauricio Baeza 176415c1fe Actualizar lista de cambios y versión 2021-09-02 23:38:51 -05:00
Mauricio Baeza eb079a3d73 Agregar soporte para descargar metadatos 2021-09-02 23:36:17 -05:00
Mauricio Baeza 88821cd850 Agregar soporte para descargar metadatos 2021-09-02 23:34:51 -05:00
Mauricio Baeza 7882898066 Fix issue #2 2021-08-04 18:41:31 -05:00
Mauricio Baeza 2cd9dab247 Actualizar lista de cambios 2021-08-04 18:41:11 -05:00
Mauricio Baeza 8a51fd72b0 Fix - En fechas 2021-08-04 18:38:54 -05:00
Mauricio Baeza d6b1125968 Se agrega soporte para rangos de fechas y últimos días 2021-07-30 22:46:25 -05:00
Mauricio Baeza c655a3c8a1 Actualizar lista de cambios 2021-07-30 22:45:58 -05:00
Mauricio Baeza 98f9799a8d Agregar soporte para rangos de fechas 2021-07-30 22:43:40 -05:00
Mauricio Baeza 58b609c1f4 Agregar soporte para rangos de fechas 2021-07-29 22:09:02 -05:00
Mauricio Baeza 5d750f57ee Agregar soporte para intervalo de días 2021-07-28 22:36:14 -05:00
Mauricio Baeza c8767f56a3 Agregar soporte para intervalo de días 2021-07-27 23:17:55 -05:00
Mauricio Baeza b786493343 Fix issue #1 2021-07-16 15:35:33 -05:00
Mauricio Baeza b6a9acb8ba Fix issue #1 2021-07-16 15:34:45 -05:00
Mauricio Baeza 350e11333c Firmar con fiel en formato PEM 2021-07-15 18:08:07 -05:00
Mauricio Baeza bcbfd1eca3 Firmar con fiel en formato PEM 2021-07-15 18:07:38 -05:00
12 changed files with 259 additions and 73 deletions

View File

@ -1,5 +1,46 @@
# Lista de cambios
## v 0.1.0
## v 0.6.0 [27-Mar-22]
---
* Fix - Cambios del SAT
## v 0.5.1 [09-Feb-22]
---
* Fix - Validar fiel en cada proceso.
## v 0.5.0 [06-Feb-22]
---
* Se cambia la lógica para evitar el error de token caducado.
## v 0.4.0 [02-Sep-21]
---
* Se agrega soporte para descargar metadatos
## v 0.3.1 [04-Ago-21]
---
* Fix - Issue #2
## v 0.3.0 [30-Jul-21]
---
* Se agrega soporte para consultar por los últimos X días
* Se agrega soporte para consultar por rangos de fechas
## v 0.2.1 [16-Jul-21]
---
* Fix - Issue #1
## v 0.2.0 [15-Jul-21]
---
* Se agrega la posibilidad de firmar con fiel en formato PEM
## v 0.1.0 [15-Jul-21]
---
* Primera versión funcional de la descarga masiva

View File

@ -8,20 +8,13 @@ Descarga masiva del SAT
En orden de preferencia
Mauricio Baeza
* G1: `A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h`
```
Euros
IBAN: BE60 9671 0556 5870
SWIFT / BIC: TRWIBEB1XXX
```
* BCH: `qztd3l00xle5tffdqvh2snvadkuau2ml0uqm4n875d`
* FairCoin: `fJ7emvtyGfvcMuxk1nHSnS7gmeScdcZXL5`
* Monero: `43H43TpQKYdYcw2ZCnn2nbjDh3imNQg8RGYS4oP4p7Z8aeBHg6VpeaFfBoMzDTUUDdQBiGkiQUSydJB96m6MqiEuEeyoopQ`
* ETH: `0x61a4f614a30ff686445751ed8328b82b77ecfc69`
* XRP: `rLSn6Z3T8uCxbcd1oxwfGQN1Fdn5CyGujK` Tag: `6643162`
* LTC: `MBcgQ3LQJA4W2wsXknTdm2fxRSysLaBJHS`
* BTC: `3FhiXcXmAesmQzrNEngjHFnvaJRhU1AGWV`
Mira la [documentación](https://git.cuates.net/elmau/cfdi-descarga/wiki/Inicio)

View File

@ -1 +1 @@
0.1.0
0.6.0

Binary file not shown.

Binary file not shown.

BIN
doc/URLs.pdf Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
httpx
peewee
cryptography
cryptography==3.4.8
lxml

View File

@ -41,13 +41,26 @@ def _process_command_line_arguments():
parser.add_argument('-fn', '--fiel-nombre', help=help, default='fiel')
help = "Descargar por Tipo: t=todos(default), e=emitidas, r=recibidas"
parser.add_argument('-t', '--tipo', help=help, dest='type', default='t', choices=['t', 'e', 'r'])
parser.add_argument('-t', '--tipo', help=help,
dest='type', default='t', choices=['t', 'e', 'r'])
help = "Año de la descarga entre 2014 y el año actual (predeterminado)."
parser.add_argument('-a', '--año', help=help, dest='year', default=year, type=int, choices=range(2014, year+1))
parser.add_argument('-a', '--año', help=help,
dest='year', default=year, type=int, choices=range(2014, year+1))
help = "Mes de la descarga, el mes actual es el predeterminado"
parser.add_argument('-m', '--mes', help=help, dest='month', default=0, type=int, choices=range(13))
parser.add_argument('-m', '--mes', help=help,
dest='month', default=0, type=int, choices=range(13))
help = "Día de la descarga, de forma predeterminada no se usa"
parser.add_argument('-d', '--dia', help=help, dest='day', default=0, type=int, choices=range(32))
parser.add_argument('-d', '--dia', help=help,
dest='day', default=0, type=int, choices=range(31))
help = "Intervalo de días a partir de la fecha actual y hacia a atras"
parser.add_argument('-ud', '--ultimos-dias', help=help,
dest='last_days', default=0, type=int, choices=range(30))
help = "Fecha inicial AAAA-MM-DD"
parser.add_argument('-fi', '--fecha-inicial', help=help,
dest='date_start', default='')
help = "Fecha final AAAA-MM-DD"
parser.add_argument('-ff', '--fecha-final', help=help,
dest='date_end', default='')
help = 'Solicitar descarga'
parser.add_argument('-sd', '--solicitar-descarga', help=help,
@ -59,13 +72,19 @@ def _process_command_line_arguments():
parser.add_argument('-da', '--descargar-archivos', help=help,
action='store_true', default=False, required=False)
help = 'ID de solicitud'
parser.add_argument('-id', '--id-solicitud', dest='id_request', help=help, default='')
parser.add_argument('-id', '--id-solicitud', dest='id_request',
help=help, default='')
help = 'ID archivo'
parser.add_argument('-ida', '--id-archivo', dest='id_file', help=help, default='')
parser.add_argument('-ida', '--id-archivo', dest='id_file',
help=help, default='')
help = 'Ruta de descarga de archivos'
parser.add_argument('-dd', '--directorio-descargas', dest='path_download',
help=help, default='')
help = 'Descargar solo metadatos'
parser.add_argument('-md', '--metadata', help=help,
action='store_true', default=False, required=False)
args = parser.parse_args()
return args

View File

@ -19,11 +19,12 @@ from conf import TOKEN
class SATCertificate(object):
def __init__(self, cer=b'', key=b'', password=''):
def __init__(self, cer=b'', key=b'', pem=b'', password=''):
self._error = ''
self._init_values()
self._get_data_cer(cer)
self._get_data_key(key, password)
self._get_data_pem(pem)
def _init_values(self):
self._rfc = ''
@ -37,6 +38,7 @@ class SATCertificate(object):
self._cer_pem = ''
self._cer_txt = ''
self._key_enc = b''
self._key_pem = b''
self._p12 = b''
self._cer_modulus = 0
self._key_modulus = 0
@ -131,6 +133,14 @@ class SATCertificate(object):
)
return key_pem
def _get_data_pem(self, pem):
if not pem:
return
self._key_pem = serialization.load_pem_private_key(
pem, None, backend=default_backend())
return
# Not work
def _get_p12(self):
obj = serialization.pkcs12.serialize_key_and_certificates('test',
@ -144,7 +154,19 @@ class SATCertificate(object):
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
return base64.b64encode(firma).decode()
def _sign_with_pem(self, data, name_hash):
if name_hash == 'sha256':
type_hash = hashes.SHA256()
elif name_hash == 'sha1':
type_hash = hashes.SHA1()
firma = self._key_pem.sign(data, padding.PKCS1v15(), type_hash)
return base64.b64encode(firma).decode()
def sign_sha1(self, data, password=''):
if self._key_pem:
return self._sign_with_pem(data, 'sha1')
private_key = self._get_key(password)
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA1())
return base64.b64encode(firma).decode()

View File

@ -8,6 +8,8 @@ from datetime import datetime, timedelta
import httpx
import lxml.etree as ET
from conf import TIMEOUT
class SATWebService():
BASE = 'https://cfdidescargamasivasolicitud.clouda.sat.gob.mx'
@ -29,6 +31,8 @@ class SATWebService():
'Content-type': 'text/xml;charset="utf-8"',
'Accept': 'text/xml',
'Cache-Control': 'no-cache',
'Expect': '100-continue',
'Accept-Encoding': 'gzip, deflate',
}
NS = {
's': 'http://schemas.xmlsoap.org/soap/envelope/',
@ -148,38 +152,69 @@ class SATWebService():
nsmap = {'s': self.NS['s'], None: self.XMLNS}
node_name = 's:Body/AutenticaResponse/AutenticaResult'
token = result.find(node_name, namespaces=nsmap).text
# ~ print(f'Token: {token}')
return token
def _get_data_req(self, args):
NSMAP = {'s': self.NS['s'], 'des': self.NS['des'], 'xd': self.NS['xd']}
# ~ NSMAP = {'s': self.NS['s'], 'des': self.NS['des'], 'xd': self.NS['xd']}
# ~ NSMAP = {'s': self.NS['s'], 'xd': self.NS['xd']}
NSMAP = {'s': self.NS['s']}
FORMAT = '%Y-%m-%dT%H:%M:%S'
date_start = args['date_start']
date_end = args['date_end']
msg = f'Descarga desde: {date_start} hasta: {date_end}'
print(msg)
node_name = f"{{{self.NS['s']}}}Envelope"
root = ET.Element(node_name, nsmap=NSMAP)
node_name = f"{{{self.NS['s']}}}Header"
body = ET.SubElement(root, node_name)
header = ET.SubElement(root, node_name)
node_name = 'ActivityId'
attr = {'CorrelationId': '806aad0d-ef46-443b-9741-040c8e8e8c7d'}
nsmap = {None: 'http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics'}
activity = ET.SubElement(header, node_name, attr, nsmap=nsmap)
activity.text = 'e906cfb4-f706-43de-94d0-5cc935be1aaa'
node_name = f"{{{self.NS['s']}}}Body"
body = ET.SubElement(root, node_name)
node_name = f"{{{self.NS['des']}}}SolicitaDescarga"
request_down = ET.SubElement(body, node_name)
node_name = f"{{{self.NS['des']}}}solicitud"
attr = {
'RfcSolicitante': self._cert.rfc,
'FechaFinal': date_end.strftime(FORMAT),
'FechaInicial': date_start.strftime(FORMAT),
'TipoSolicitud': 'CFDI',
args['rfc']: self._cert.rfc,
nsmap = {
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xsd': 'http://www.w3.org/2001/XMLSchema',
}
body = ET.SubElement(root, node_name, nsmap=nsmap)
# ~ node_name = f"{{{self.NS['des']}}}SolicitaDescarga"
node_name = "SolicitaDescarga"
nsmap = {None: 'http://DescargaMasivaTerceros.sat.gob.mx'}
request_down = ET.SubElement(body, node_name, nsmap=nsmap)
# ~ node_name = f"{{{self.NS['des']}}}solicitud"
node_name = "solicitud"
type_request = 'CFDI'
if args['metadata']:
type_request = 'Metadata'
attr = {
'FechaInicial': date_start.strftime(FORMAT),
'FechaFinal': date_end.strftime(FORMAT),
'RfcSolicitante': self._cert.rfc,
'TipoSolicitud': type_request,
# ~ 'RfcACuentaTerceros': '',
}
if args['rfc'] == 'RfcEmisor':
attr['RfcEmisor'] = self._cert.rfc
request = ET.SubElement(request_down, node_name, attr)
node_name = 'RfcReceptores'
node_receptores = ET.SubElement(request, node_name)
node_name = 'RfcReceptor'
node_receptor = ET.SubElement(node_receptores, node_name)
if args['rfc'] == 'RfcReceptor':
node_receptor.text = self._cert.rfc
nsmap = {None: self.NS['xd']}
signature = ET.SubElement(request, 'Signature', nsmap=nsmap)
signed_info = ET.SubElement(signature, 'SignedInfo', nsmap=nsmap)
@ -192,7 +227,8 @@ class SATWebService():
attr = {'Algorithm': 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'}
signature_method = ET.SubElement(signed_info, node_name, attr)
attr = {'URI': '#_0'}
# ~ attr = {'URI': '#_0'}
attr = {'URI': ''}
reference = ET.SubElement(signed_info, 'Reference', attr)
transforms = ET.SubElement(reference, 'Transforms')
ET.SubElement(transforms, 'Transform', attr1)
@ -220,18 +256,25 @@ class SATWebService():
x_serial_number.text = str(self._cert.serial_number2)
x_cert.text = self._cert.cer_txt
# ~ soap = ET.tostring(root, pretty_print=True, encoding='utf-8')
soap = ET.tostring(root)
# ~ soap = b'<?xml version="1.0"?>\n' + ET.tostring(root, pretty_print=True, encoding='utf-8')
soap = ET.tostring(root, pretty_print=True)
# ~ print(soap.decode())
return soap
def request_download(self, args):
headers = self.HEADERS.copy()
headers['SOAPAction'] = self.ACTIONS['REQ']
headers['Host'] = 'srvsolicituddescargamaster.cloudapp.net'
headers['Authorization'] = f'WRAP access_token="{self._token}"'
data = self._get_data_req(args)
response = httpx.post(self.URL['REQ'], data=data, headers=headers)
try:
response = httpx.post(self.URL['REQ'],
data=data, headers=headers, timeout=TIMEOUT)
except httpx.TimeoutException as exc:
print(exc)
return
if response.status_code != httpx.codes.OK:
self._error = f'Status: {response.status_code} - {response.text}'
return
@ -244,7 +287,7 @@ class SATWebService():
return data
def _get_data_verify(self, args):
NSMAP = {'s': self.NS['s'], 'des': self.NS['des'], 'xd': self.NS['xd']}
NSMAP = {'soapenv': self.NS['s'], 'des': self.NS['des'], 'xd': self.NS['xd']}
node_name = f"{{{self.NS['s']}}}Envelope"
root = ET.Element(node_name, nsmap=NSMAP)
@ -277,7 +320,8 @@ class SATWebService():
attr = {'Algorithm': 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'}
signature_method = ET.SubElement(signed_info, node_name, attr)
attr = {'URI': '#_0'}
# ~ attr = {'URI': '#_0'}
attr = {'URI': ''}
reference = ET.SubElement(signed_info, 'Reference', attr)
transforms = ET.SubElement(reference, 'Transforms')
ET.SubElement(transforms, 'Transform', attr1)
@ -330,7 +374,7 @@ class SATWebService():
return data
def _get_data_download(self, args):
NSMAP = {'s': self.NS['s'], 'des': self.NS['des'], 'xd': self.NS['xd']}
NSMAP = {'soapenv': self.NS['s'], 'des': self.NS['des'], 'xd': self.NS['xd']}
node_name = f"{{{self.NS['s']}}}Envelope"
root = ET.Element(node_name, nsmap=NSMAP)
@ -363,7 +407,8 @@ class SATWebService():
attr = {'Algorithm': 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'}
signature_method = ET.SubElement(signed_info, node_name, attr)
attr = {'URI': '#_0'}
# ~ attr = {'URI': '#_0'}
attr = {'URI': ''}
reference = ET.SubElement(signed_info, 'Reference', attr)
transforms = ET.SubElement(reference, 'Transforms')
ET.SubElement(transforms, 'Transform', attr1)
@ -402,7 +447,13 @@ class SATWebService():
headers['Authorization'] = f'WRAP access_token="{self._token}"'
data = self._get_data_download(args)
response = httpx.post(self.URL['DOWN'], data=data, headers=headers)
try:
response = httpx.post(self.URL['DOWN'],
data=data, headers=headers, timeout=TIMEOUT)
except httpx.TimeoutException as exc:
print(exc)
return
if response.status_code != httpx.codes.OK:
self._error = f'Status: {response.status_code} - {response.text}'
return

View File

@ -3,7 +3,7 @@
import getpass
import uuid
from calendar import monthrange
from datetime import datetime
from datetime import datetime, timedelta
from pathlib import Path
from time import sleep
@ -33,7 +33,7 @@ def join(*paths):
return Path(paths[0]).joinpath(*paths[1:])
def _validate_fiel_args(args):
def _validate_fiel_args(args, need_key=False):
fiel_path = args.fiel_dir
fiel_name = args.fiel_nombre
@ -50,14 +50,15 @@ def _validate_fiel_args(args):
path_cer = join(fiel_path, f'{fiel_name}.cer')
path_key = join(fiel_path, f'{fiel_name}.key')
path_enc = join(fiel_path, f'{fiel_name}.enc')
path_pem = join(fiel_path, f'{fiel_name}.pem')
if not path_cer.is_file():
msg = f'No se encontró el archivo CER. \nRuta: {path_cer}'
log.error(msg)
return False, {}
if not path_key.is_file():
msg = f'No se encontró el archivo KEY. \nRuta: {path_cer}'
if need_key and not path_key.is_file():
msg = f'No se encontró el archivo KEY. \nRuta: {path_key}'
log.error(msg)
return False, {}
@ -65,16 +66,23 @@ def _validate_fiel_args(args):
'path_cer': path_cer,
'path_key': path_key,
'path_enc': path_enc,
'path_pem': path_pem,
}
return True, data
def fiel_validar(args):
result, data = _validate_fiel_args(args)
result, data = _validate_fiel_args(args, True)
if not result:
return
password = getpass.getpass('Introduce la contraseña del archivo KEY: ')
try:
password = getpass.getpass('Introduce la contraseña del archivo KEY: ')
except KeyboardInterrupt:
msg = 'Proceso cancelado'
log.info(msg)
return
if not password:
msg = 'La contraseña es requerida para validar la FIEL'
log.error(msg)
@ -82,7 +90,7 @@ def fiel_validar(args):
cer = data['path_cer'].read_bytes()
key = data['path_key'].read_bytes()
cert = SATCertificate(cer, key, password)
cert = SATCertificate(cer, key, password=password)
if cert.error:
msg = f'{cert.error}\n\nNo podrás conectarte el SAT.'
@ -110,19 +118,43 @@ def base_datos():
return
def _get_cert(data):
key = b''
pem = b''
cer = data['path_cer'].read_bytes()
if data['path_enc'].is_file():
key = data['path_enc'].read_bytes()
elif data['path_pem'].is_file():
pem = data['path_pem'].read_bytes()
cert = SATCertificate(cer, key, pem)
return cert
def _to_date(str_date, end=False):
error = ''
dt = None
try:
parts = str_date.split('-')
if end:
dt = datetime(int(parts[0]), int(parts[1]), int(parts[2]), 23, 59, 59)
else:
dt = datetime(int(parts[0]), int(parts[1]), int(parts[2]), 0, 0, 0)
except Exception as e:
error = 'Fecha inválida'
return error, dt
def _validate_requests_args(args):
result, data = _validate_fiel_args(args)
if not result:
return False, {}
if not data['path_enc'].is_file():
msg = f"No se encontró la FIEL encriptada. \nRuta: {data['path_enc']}"
if not data['path_enc'].is_file() and not data['path_pem'].is_file():
msg = f"No se encontró la FIEL [enc|pem].\nRuta: {data['path_enc']}"
log.error(msg)
return False, {}
cer = data['path_cer'].read_bytes()
key = data['path_enc'].read_bytes()
cert = SATCertificate(cer, key)
cert = _get_cert(data)
if not cert.is_valid_time:
msg = 'La FIEL no es vigente'
@ -134,6 +166,32 @@ def _validate_requests_args(args):
data['year'] = args.year
data['month'] = args.month
data['day'] = args.day
data['metadata'] = args.metadata
now = today()
if args.last_days:
date_start = now.replace(hour=0, minute=0, second=0, microsecond=0) \
- timedelta(days=args.last_days)
date_end = now.replace(hour=23, minute=59, second=59, microsecond=0)
data['date_start'] = date_start
data['date_end'] = date_end
return True, data
if args.date_start and args.date_end:
error, date_start = _to_date(args.date_start)
if error:
log.error(error)
return False, {}
error, date_end = _to_date(args.date_end, True)
if error:
log.error(error)
return False, {}
data['date_start'] = date_start
data['date_end'] = date_end
return True, data
if data['day']:
if not validate_date(data['year'], data['month'], data['day']):
@ -141,8 +199,6 @@ def _validate_requests_args(args):
log.error(msg)
return False, {}
now = today()
month1 = month2 = data['month']
if month1 == 0:
month1 = 1
@ -165,14 +221,12 @@ def _validate_verificar_args(args):
if not result:
return False, {}
if not data['path_enc'].is_file():
msg = f"No se encontró la FIEL encriptada. \nRuta: {data['path_enc']}"
if not data['path_enc'].is_file() and not data['path_pem'].is_file():
msg = f"No se encontró la FIEL [enc|pem].\nRuta: {data['path_enc']}"
log.error(msg)
return False, {}
cer = data['path_cer'].read_bytes()
key = data['path_enc'].read_bytes()
cert = SATCertificate(cer, key)
cert = _get_cert(data)
if not cert.is_valid_time:
msg = 'La FIEL no es vigente'
@ -195,14 +249,12 @@ def _validate_download_args(args):
if not result:
return False, {}
if not data['path_enc'].is_file():
msg = f"No se encontró la FIEL encriptada. \nRuta: {data['path_enc']}"
if not data['path_enc'].is_file() and not data['path_pem'].is_file():
msg = f"No se encontró la FIEL [enc|pem].\nRuta: {data['path_enc']}"
log.error(msg)
return False, {}
cer = data['path_cer'].read_bytes()
key = data['path_enc'].read_bytes()
cert = SATCertificate(cer, key)
cert = _get_cert(data)
if not cert.is_valid_time:
msg = 'La FIEL no es vigente'
@ -290,6 +342,10 @@ def descargar_archivos(args):
else:
result = sat.verify(data)
files = result['files']
if result['EstadoSolicitud'] in ('1', '2'):
msg = 'Solicitud aún no aceptada...'
log.error(msg)
return
for f in files:
data['id_file'] = f
@ -322,9 +378,11 @@ def _validate_args(args):
return True, data
def _download(sat, data, key):
def _download(data, key):
OK = '5000'
sat = SATWebService(data['cert'])
result = _request_download(sat, data, key)
if result['CodEstatus'] != OK:
log.error(result)
@ -339,7 +397,9 @@ def _download(sat, data, key):
sleep(1)
while True:
sat = SATWebService(data['cert'])
result = sat.verify(data)
if result['EstadoSolicitud'] in ('1', '2'):
msg = 'Esperando un minuto más para volver a verificar...'
log.info(msg)
@ -382,12 +442,12 @@ def descargar(args):
return
if data['type'] == 'e':
_download(sat, data, 'RfcEmisor')
_download(data, 'RfcEmisor')
elif data['type'] == 'r':
_download(sat, data, 'RfcReceptor')
_download(data, 'RfcReceptor')
else:
_download(sat, data, 'RfcEmisor')
_download(sat, data, 'RfcReceptor')
_download(data, 'RfcEmisor')
_download(data, 'RfcReceptor')
return