Descarga de certificados desde el SAT
Es necesario descargar los certificados de los PAC para poder validar el atributo SelloCFDI
del nodo tfd:TimbreFiscalDigital
porque no viene incluido en la estructura.
Siendo así, se utilizan las clases CfdiUtils\Certificado\SatCertificateNumber
y la clase CfdiUtils\Certificado\CerRetriever
.
SatCertificateNumber
contiene el método remoteUrl(): string
que devuelve una URL que apunta a https://rdc.sat.gob.mx/rccf/
.
El problema es que a partir de 2018-09-12 en el servidor rdc.sat.gob.mx
el servidor web retorna certificados
para el protocolo https
vigentes y expirados:
- Expirado:
4D:CE:6C:8E:0D:C6:4C:E3
vigente hasta2018-09-22 16:07:04 GMT
- Vigente:
00:A7:06:AA:42:44:4E:E4:E9:00:00:00:00:58:08:91:5B
vigente hasta2020-09-12 16:41:28 GMT
No hay una tendencia, de una muestra de 1,000 descargas realizada el 2018-10-17 17:30 GMT-5
el resultado fue:
incorrectas 2,853 (28.53%) y correctas 7,147 (71.47%) por lo que la posibilidad de obtener un certificado incorrecto
es cercana al 30%.
Como resultado, la conexión segura al servidor no se puede establecer y esto generará que falle el proceso de descarga del certificado.
Al fallar la descarga del certificado entonces fallará la validación TFDSELLO01
que verifica que
El Sello SAT del Timbre Fiscal Digital corresponde al certificado SAT. Por lo tanto, si se está usando
la librería CfdiUtils
para comprobar un CFDI con Timbre Fiscal Digital entonces constantemente se tendrá
el problema de validación TFDSELLO01
hasta que el SAT solucione el problema de configuración.
Como una posible solución, si al validar un CFDI se obtiene un error TFDSELLO01
se podría reintentar validar.
<?php
$maxAttempts = 10;
$sleepTime = 1 * 1000;
$currentAttempt = 1;
do {
/** @var \CfdiUtils\CfdiValidator33 $validator */
$asserts = $validator->validateXml(file_get_contents('cfdi.xml'));
if ($asserts->exists('TFDSELLO01')) {
$assert = $asserts->get('TFDSELLO01');
if ($assert->getStatus()->isError()) {
if ($currentAttempt <= $maxAttempts) {
$currentAttempt = $currentAttempt + 1;
usleep($sleepTime);
continue;
}
}
}
} while (false);
// $asserts podría tener el código 'TFDSELLO01' con estado de error después de haberlo intentado 10 veces
Personalmente, no recomiendo deshabilitar la seguridad del protocolo HTTPS, pero es una posible solución.
Se puede desactivar usando el downloader genérico XmlResourceRetriever\Downloader\PhpDownloader
y estableciendo un contexto que desactive la verificación de la siguiente manera.
<?php
$context = stream_context_create([
'ssl' => ['verify_peer' => false],
]);
$downloader = new \XmlResourceRetriever\Downloader\PhpDownloader($context);
/* Establecer en un objeto de tipo xmlResolver */
/** @var \CfdiUtils\XmlResolver\XmlResolver $xmlResolver */
$xmlResolver->setDownloader($downloader);
/* Establecer directamente en un objeto validador */
/** @var \CfdiUtils\CfdiValidator33 $validator */
$validator->getXmlResolver()->setDownloader($downloader);
/* Establecer directamente en un objeto creador de CFDI 3.3 */
/** @var \CfdiUtils\CfdiCreator33 $creator */
$creator->getXmlResolver()->setDownloader($downloader);
También se puede desactivar la verificación de SSL creando un descargador que implemente
XmlResourceRetriever\Downloader\DownloaderInterface
y en el método downloadTo
hacer caso omiso de las validaciones.