Segunda parte del codigo si lo quieren ver completo sigan la liga ... del inicio
  Código PHP:
    // {{{ Valida Sello
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/...
     */ 
global $data, $xml;
 
$xsl = new DOMDocument;
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['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, descargdo del FTP del sat ...<br>";
    $no_cert = $data['no_cert'];
    $p1=substr($no_cert,0,6);
    $p2=substr($no_cert,6,6);
    $p3=substr($no_cert,12,2);
    $p4=substr($no_cert,14,2);
    $p5=substr($no_cert,16,2);
    $path = "ftp://ftp2.sat.gob.mx/certificados/FEA/$p1/$p2/$p3/$p4/$p5/$no_cert.cer";
    $der = file_get_contents($path);
    $pem = base64_encode($der);
    echo "path=$path<br>";
}
 
$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>";
}
 
}
// }}} Valida Sello
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 = trim(preg_replace('{</cfdi:.*$}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" />';
}
// Solo se quedo el tfd:
$xml_tfd = new DOMDocument();
$ok = $xml_tfd->loadXML($texto_tfd);
 
$xsl = new DOMDocument;
$xsl->load('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>";
}
 
$no_cert=$data['no_cert_sat'];
$p1=substr($no_cert,0,6);
$p2=substr($no_cert,6,6);
$p3=substr($no_cert,12,2);
$p4=substr($no_cert,14,2);
$p5=substr($no_cert,16,2);
$path = "ftp://ftp2.sat.gob.mx/certificados/FEA/$p1/$p2/$p3/$p4/$p5/$no_cert.cer";
echo "Certificado SAT $path<br>";
$der = file_get_contents($path);
$pem = base64_encode($der);
 
$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>";
 
}
// }}} Valida Sello
// {{{ Valida este XML en el servidor del SAT 
// ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/cfdi/WS_ConsultaCFDI.pdf
function valida_en_sat() {
    global $data;
    error_reporting(E_ALL);
    require_once('nusoap/nusoap.php');
    $url = "https://consultaqr.facturaelectronica.sat.gob.mx/consultacfdiservice.svc?wsdl";
 
    $soapclient = new nusoap_client($url,$esWSDL=true);
    $soapclient->soap_defencoding = 'UTF-8'; 
    $soapclient->decode_utf8 = false;
 
    $rfc_emisor = $data['rfc'];
    $rfc_receptor = $data['rfc_receptor'];
    $impo = (double)$data['total'];
    $impo=sprintf("%.6f", $impo);
    $impo = str_pad($impo,17,"0",STR_PAD_LEFT);
 
    $uuid = strtoupper($data['uuid']);
 
    $factura = "?re=$rfc_emisor&rr=$rfc_receptor&tt=$impo&id=$uuid";
 
    $prm = array('expresionImpresa'=>$factura);
 
    $buscar=$soapclient->call('Consulta',$prm);
 
    echo "<h3>El portal del SAT reporta</h3>";
    echo "El codigo: ".$buscar['ConsultaResult']['CodigoEstatus']."<br>";
    echo "El estado: ".$buscar['ConsultaResult']['Estado']."<br>";
 
}
function convierte($dec) {
    $hex=bcdechex($dec);
    $ser="";
    for ($i=1; $i<strlen($hex); $i=$i+2) {
        $ser.=substr($hex,$i,1);
    }
    return $ser;
}
function bcdechex($dec) {
    $last = bcmod($dec, 16);
    $remain = bcdiv(bcsub($dec, $last), 16);
    if($remain == 0) {
        return dechex($last);
    } else {
        return bcdechex($remain).dechex($last);
    }
}
function getpath($qry) {
global $xp;
$prm = array();
$nodelist = $xp->query($qry);
foreach ($nodelist as $tmpnode)  {
    $prm[] = trim($tmpnode->nodeValue);
    }
$ret = (sizeof($prm)<=1) ? $prm[0] : $prm;
return($ret);
}
function display_xml_errors() {
    global $texto;
    $lineas = explode("\n", $texto);
    $errors = libxml_get_errors();
 
    echo "<pre>";
    foreach ($errors as $error) {
        echo display_xml_error($error, $lineas);
    }
    echo "</pre>";
 
    libxml_clear_errors();
}
function display_xml_error($error, $lineas) {
    $return  = htmlspecialchars($lineas[$error->line - 1]) . "\n7";
    $return .= str_repeat('-', $error->column) . "^\n";
 
    switch ($error->level) {
        case LIBXML_ERR_WARNING:
            $return .= "Warning $error->code: ";
            break;
         case LIBXML_ERR_ERROR:
            $return .= "Error $error->code: ";
            break;
        case LIBXML_ERR_FATAL:
            $return .= "Fatal Error $error->code: ";
            break;
    }
 
    $return .= trim($error->message) .
               "\n  Linea: $error->line" .
               "\n  Columna: $error->column";
    echo "$return\n\n--------------------------------------------\n\n";
}
?></div></BODY></HTML> 
   
  http://www.lacorona.com.mx/fortiz/sat/cfdcvali.phps