Cambios en el SAT

This commit is contained in:
El Mau 2022-03-27 22:17:40 -06:00
commit a5b2a17d8c
9 changed files with 74 additions and 22 deletions

View File

@ -1,5 +1,9 @@
# Lista de cambios
## v 0.6.0 [27-Mar-22]
---
* Fix - Cambios del SAT
## v 0.5.1 [09-Feb-22]
---

View File

@ -1 +1 @@
0.5.1
0.6.0

Binary file not shown.

Binary file not shown.

BIN
doc/URLs.pdf Normal file

Binary file not shown.

View File

@ -51,7 +51,7 @@ def _process_command_line_arguments():
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))
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))

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,12 +152,14 @@ 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}')
# ~ 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']
@ -165,28 +171,50 @@ class SATWebService():
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)
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"
request_down = ET.SubElement(body, node_name)
# ~ 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 = f"{{{self.NS['des']}}}solicitud"
node_name = "solicitud"
type_request = 'CFDI'
if args['metadata']:
type_request = 'Metadata'
attr = {
'RfcSolicitante': self._cert.rfc,
'FechaFinal': date_end.strftime(FORMAT),
'FechaInicial': date_start.strftime(FORMAT),
'FechaFinal': date_end.strftime(FORMAT),
'RfcSolicitante': self._cert.rfc,
'TipoSolicitud': type_request,
args['rfc']: self._cert.rfc,
# ~ '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)
@ -199,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)
@ -227,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
@ -251,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)
@ -284,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)
@ -337,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)
@ -370,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)
@ -409,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

@ -342,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