Exemplo n.º 1
0
function valida_sello_tfd()
{
    global $data, $texto;
    if ($data['sell'] != $data['sellocfd']) {
        echo "<h3>sello Comprobante diferente que sello TFD!, manipulado?</h3>";
    }
    // Quita la parte del CFDI
    $texto_tfd = preg_replace('{<cfdi:Comprobante.*<tfd:}is', '<tfd:', $texto);
    $texto_tfd = preg_replace('{<retenciones:Retenciones.*<tfd:}is', '<tfd:', $texto_tfd);
    $texto_tfd = trim(preg_replace('{/>.*$}is', '/>', $texto_tfd));
    // Si no tiene el namespace definido, se agrega
    if (strpos($texto_tfd, "xmlns:tfd") === FALSE) {
        $texto_tfd = substr($texto_tfd, 0, -2) . ' xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" />';
    }
    // echo htmlspecialchars($texto_tfd);
    // Solo se quedo el tfd:
    $xml_tfd = new DOMDocument();
    $ok = $xml_tfd->loadXML($texto_tfd);
    $xsl = new DOMDocument();
    $xsl->load('xslt/cadenaoriginal_TFD_1_0.xslt');
    $proc = new XSLTProcessor();
    $proc->importStyleSheet($xsl);
    $cadena = $proc->transformToXML($xml_tfd);
    echo "Cadena Original TFD<br><p align=left>{$cadena}</p><br>";
    if (!mb_check_encoding($cadena, "utf-8")) {
        echo "<h3>Error no esta en UTF-8!</h3>";
    }
    // Certificado del PAC
    $pem = get_sat_cert($data['no_cert_sat']);
    $cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($pem, 64) . "-----END CERTIFICATE-----\n";
    // file_put_contents("/tmp/llave.cer.pem",$cert);
    $pubkeyid = openssl_get_publickey(openssl_x509_read($cert));
    $ok = openssl_verify($cadena, base64_decode($data['sellosat']), $pubkeyid, OPENSSL_ALGO_SHA1);
    if ($ok == 1) {
        echo "<h3>Sello TFD ok</h3>";
    } else {
        echo "<h3>Sello TFD incorrecto</h3>";
        while ($msg = openssl_error_string()) {
            echo $msg . "\n";
        }
    }
    openssl_free_key($pubkeyid);
    echo "<hr>";
}
Exemplo n.º 2
0
function valida_sello()
{
    /*
     * Todos los archivos que se requieren para generar la cadena original
     * fueron descargados del portal del SAT pero los tengo localmente
     * almacenados en mi maquina para que el proceso sea mas rapido.
     *
     * Todos los archivos estan modificacion por el numero de version 2 a 1,
     * para que no mande warning PHP
     *
     * La version de mi maquina los pueden obtener de la misma URL
     *
     * http://www.lacorona.com.mx/fortiz/sat/cadenaoriginal_TFD_1_0.xslt
     * http://www.lacorona.com.mx/fortiz/sat/ecc.xslt
     * http://www.lacorona.com.mx/fortiz/sat/...
     *
     * [dev@www sat]$ ls *xslt
     * Divisas.xslt                   cfdiregistrofiscal.xslt  nomina11.xslt
     * TuristaPasajeroExtranjero.xslt detallista.xslt          pfic.xslt
     * cadenaoriginal_2_0.xslt        donat11.xslt             spei.xslt
     * cadenaoriginal_2_2.xslt        ecc.xslt                 terceros11.xslt
     * cadenaoriginal_3_0.xslt        iedu.xslt                utilerias.xslt
     * cadenaoriginal_3_2.xslt        implocal.xslt          ventavehiculos.xslt
     * cadenaoriginal_TFD_1_0.xslt    leyendasFisc.xslt
     *
     *
     * */
    global $data, $xml;
    $xsl = new DOMDocument();
    if ($data['tipo'] == "retenciones") {
        switch ($data['version']) {
            case "1.0":
                $xsl->load('retenciones.xslt');
                $algo = OPENSSL_ALGO_SHA1;
                break;
            default:
                echo "version incorrecta " . $data['tipo'] . " " . $data['version'] . "\n";
                break;
        }
    } else {
        switch ($data['version']) {
            case "2.0":
                $xsl->load('cadenaoriginal_2_0.xslt');
                if (substr($data['fecha'], 0, 4) < 2011) {
                    echo "md5 \n";
                    $algo = OPENSSL_ALGO_MD5;
                } else {
                    echo "sha1 \n";
                    $algo = OPENSSL_ALGO_SHA1;
                }
                break;
            case "2.2":
                echo "2.2\n";
                $xsl->load('cadenaoriginal_2_2.xslt');
                echo "sha1 \n";
                $algo = OPENSSL_ALGO_SHA1;
                break;
            case "3.0":
                $xsl->load('cadenaoriginal_3_0.xslt');
                if (substr($data['fecha'], 0, 4) < 2011) {
                    echo "md5 \n";
                    $algo = OPENSSL_ALGO_MD5;
                } else {
                    echo "sha1 \n";
                    $algo = OPENSSL_ALGO_SHA1;
                }
                break;
            case "3.2":
                echo "3.2\n";
                $xsl->load('cadenaoriginal_3_2.xslt');
                echo "sha1 \n";
                $algo = OPENSSL_ALGO_SHA1;
                break;
            default:
                echo "version incorrecta " . $data['tipo'] . " " . $data['version'] . "\n";
                break;
        }
    }
    $proc = new XSLTProcessor();
    $proc->importStyleSheet($xsl);
    $cadena = $proc->transformToXML($xml);
    echo "Cadena Original<br><p align=left>{$cadena}</p><br>";
    if ($algo == OPENSSL_ALGO_SHA1) {
        $sha1 = sha1($cadena);
        echo "hash sha1={$sha1}<br>";
    } else {
        $md5 = md5($cadena);
        echo "hash md5={$md5}<br>";
    }
    if (!mb_check_encoding($cadena, "utf-8")) {
        echo "<h3>Error no esta en UTF-8!</h3>";
    }
    /* 
     * El domicilio es opcional, pero si no lo ponemos el xslt del SAT genera 
     * doble pip en el pais ..., dice que el sello es correcto pero los PACs 
     * que validan bien lo rechazan ... 
     * */
    $doble = preg_match('/.\\|\\|./', $cadena);
    if ($doble === 1) {
        echo "<h3><font color=red>La cadena tiene doble pipes en medio ...</font></h3>";
    }
    // Primer certificado (o unico) del emisor
    // Los demas certificados es del PAC, Timbre, etc.
    $pem = sizeof($data['cert']) <= 1 ? $data['cert'] : $data['cert'][0];
    $pem = eregi_replace("[\n|\r|\n\r]", '', $pem);
    $pem = preg_replace('/\\s\\s+/', '', $pem);
    // Si no incluye el certificado bajarlo del FTP del sat ....
    if (strlen($pem) == 0) {
        echo "No incluye certificado interno, descargarlo del FTP del sat ...<br>";
        $pem = get_sat_cert($data['no_cert']);
    }
    $cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($pem, 64) . "-----END CERTIFICATE-----\n";
    $pubkeyid = openssl_get_publickey(openssl_x509_read($cert));
    if (!$pubkeyid) {
        echo "Certificado interno Incorrecto, descargarlo del FTP del sat ...<br>";
        $pem = get_sat_cert($data['no_cert']);
        $cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($pem, 64) . "-----END CERTIFICATE-----\n";
        $pubkeyid = openssl_get_publickey(openssl_x509_read($cert));
    }
    $ok = openssl_verify($cadena, base64_decode($data['sell']), $pubkeyid, $algo);
    if ($ok == 1) {
        echo "<h3>Sello ok</h3>";
    } else {
        echo "<h3>Sello incorrecto</h3>";
        while ($msg = openssl_error_string()) {
            echo $msg . "\n";
        }
    }
    openssl_free_key($pubkeyid);
    echo "<hr>";
    $paso = openssl_x509_parse($cert);
    $serial = convierte($paso['serialNumber']);
    if ($serial != $data['no_cert']) {
        echo "Serie reportada " . $data['no_cert'] . " serie usada {$serial}<br>";
    }
}