Bueno eso falto mencionar que encontré este código.
Código PHP:
<HTML>
<HEAD>
<meta http-equiv="Expires" content="Mon, 26 Jul 1997 05:00:00 GMT">
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<TITLE>Validacion de Facturas electronicas CFD/CFDI XML</TITLE>
<link rel="STYLESHEET" href="../../fortiz.css" media="screen" type="text/css">
</HEAD>
<BODY>
<div align=center>
<H1>Validacion de Facturas Electronicas XML (CFD/CFDI)</H1>
<form method='post' enctype='multipart/form-data'>
Archivo <input type='file' name='arch' size='60'>
<INPUT TYPE="submit" VALUE="Valida" >
<br><br><hr>
</FORM>
<a href=../cfdcvali.phps>Codigo Fuente</a>
<?php
if (trim($_FILES['arch']['name'])=="") die("no arch");
if ($_FILES['arch']['error']==1 || $_FILES['arch']['size']==0) {
echo "<h1><red>NO SUBIO archivo, demasiado grande</red></h1>";
die();
}
$arch = $_FILES['arch']['tmp_name'];
$texto = file_get_contents($arch);
unlink($arch);
// Quita Addenda solo valida fiscal
$texto = preg_replace('{<Addenda.*/Addenda>}is', '<Addenda/>', $texto);
$texto = preg_replace('{<cfdi:Addenda.*/cfdi:Addenda>}is', '<cfdi:Addenda/>', $texto);
// Para ver en la Pantalla el XML recibido (sin addenda)
/* * Paquetes para ver bonito el codigo en la pantalla
* No son necesarios 'para validar'
* solo son para 'ver bonito' lo que se valida
* Son gratuitos se obtienen de pear.php.net
* http://pear.php.net/package/XML_Beautifier/
* http://pear.php.net/package/Text_Highlighter/
* */
require_once 'Beautifier.php';
require_once 'Highlighter.php';
$fmt = new XML_Beautifier();
$fmt->setOption("multilineTags", TRUE);
$paso = $fmt->formatString($texto);
if (substr($paso,0,10)!="XML_Parser") $texto=$paso; // XML correctamente formado
$hl =& Text_Highlighter::factory('XML',array('numbers'=>HL_NUMBERS_TABLE));
echo "<div style='height:300px; overflow:auto';";
echo $hl->highlight($texto);
echo "</div>";
libxml_use_internal_errors(true); // Gracias a Salim Giacoman
$xml = new DOMDocument();
$ok = $xml->loadXML($texto);
if (!$ok) {
display_xml_errors();
die();
}
// Con XPath obtenemos el valor de los atributos del XML
$xp = new DOMXpath($xml);
$rfc = getpath("//@rfc");
$data['rfc'] = utf8_decode($rfc[0]);
$data['rfc_receptor'] = utf8_decode($rfc[1]);
$data['total'] = getpath("//@total");
if (is_array($data['total'])) $data['total'] = $data['total'][0];
$data['version'] = getpath("//@version");
if (is_array($data['version'])) $data['version'] = $data['version'][0];
$data['version'] = trim($data['version']);
$data['seri'] = utf8_decode(trim(getpath("//@serie")));
$data['foli'] = trim(getpath("//@folio"));
$data['fecha'] = trim(getpath("//@fecha"));
$data['noap'] = trim(getpath("//@noAprobacion"));
$data['anoa'] = trim(getpath("//@anoAprobacion"));
$data['no_cert'] = getpath("//@noCertificado");
if (is_array($data['no_cert'])) $data['no_cert'] = $data['no_cert'][0];
$data['no_cert'] = trim($data['no_cert']);
$data['cert'] = getpath("//@certificado");
$data['sell'] = getpath("//@sello");
$data['sellocfd'] = getpath("//@selloCFD");
$data['sellosat'] = getpath("//@selloSAT");
$data['no_cert_sat'] = getpath("//@noCertificadoSAT");
$data['uuid'] = getpath("//@UUID");
// Valores guardados en un arreglo para ser usado por las funciones
// Conexion a la base de datos para leer la lista de Series/folios y CSD
// autorizados por el SAT
// http://www.lacorona.com.mx/fortiz/sat/valida.php para ver estas tablas
// myconn es una conexion a MI BASE DE DATOS
// yo uso adodb http://phplens.com/lens/adodb/docs-adodb.htm
// pero ya los parametros de conexion a mi base de datos no te digo ;)
require_once "myconn/myconn.inc.php";
$conn=myconn();
if ($data['version']=="2.0" || $data['version']=="2.2") {
valida_folio();
}
valida_certificado();
valida_xsd();
valida_sello();
if ($data['sellosat']!="") {
valida_sello_tfd();
}
if ($data['version']=="3.2") {
valida_en_sat();
}
// {{{ valida_folio()
function valida_folio() {
global $data,$conn;
$qry = "select * from cfdfolios where RFC='".$data['rfc']."' and
Serie='".$data['seri']."' and
FolioInicial <= ".$data['foli']." and
FolioFinal >= ".$data['foli'];
$rowfolios = $conn->getrow($qry);
if (trim($rowfolios['rfc'])==$data['rfc'] &&
trim($rowfolios['serie'])==$data['seri']) {
echo "<h3>Folio Autorizado</h3>";
if($data['noap']!=$rowfolios['noaprobacion'] || $data['anoa']!=$rowfolios['anoaprobacion']) {
echo "<h3><font color=red>El numero reportado no es el autorizado</font></h3>";
}
} else {
echo "<h3><font color=red>Folio no autorizado</font></h3>";
}
echo "<hr>";
}
// }}}
// {{{ Valida certificado
function valida_certificado() {
global $data,$conn;
$qry = "select * from cfdcsd where RFC='".$data['rfc']."' and
no_serie='".$data['no_cert']."'";
$rowcsd = $conn->getrow($qry);
if (trim($rowcsd['rfc'])==$data['rfc'] &&
trim($rowcsd['no_serie'])==$data['no_cert']) {
$fini=$rowcsd['fec_inicial_cert'];
$ffin=$rowcsd['fec_final_cert'];
echo "<h3>Certificado valido del $fini al $ffin</h3>";
} else {
echo "<h3>Certificado no autorizado</h3>";
}
echo "<hr>";
}
function valida_xsd() {
/*
* Todos los archivos que se requieren para hacer la validacion
* fueron descargados del portal del SAT pero los tengo localmente
* almacenados en mi maquina para que las validaciones ssean mas rapidas.
* Ademas el archivo prinicpal cfdv32.xsd esta 'un poco' modifcado para
* que importe los complementos
*
* La version de mi maquina los pueden obtener de la misma URL
*
* http://www.lacorona.com.mx/fortiz/sat/cfdv32.xsd
* http://www.lacorona.com.mx/fortiz/sat/ecc.xsd
* http://www.lacorona.com.mx/fortiz/sat/...
* */
global $data, $xml,$texto;
libxml_use_internal_errors(true); // Gracias a Salim Giacoman
switch ($data['version']) {
case "2.0":
echo "Version 2.0 CFD<br>";
$ok = $xml->schemaValidate("cfdv2complemento.xsd");
break;
case "2.2":
echo "Version 2.2 CFD<br>";
$ok = $xml->schemaValidate("cfdv22complemento.xsd");
break;
case "3.0":
echo "Version 3.0 (CFDI)<br>";
$ok = $xml->schemaValidate("cfdv3complemento.xsd");
break;
case "3.2":
echo "Version 3.2 CFDI<br>";
$ok = $xml->schemaValidate("cfdv32.xsd");
break;
default:
$ok = false;
echo "Version invalida ".$data['version']."<br>";
}
if ($ok) {
echo "<h3>Esquema valido</h3>";
} else {
echo "<h3>Estructura contra esquema incorrecta</h3>";
display_xml_errors();
}
echo "<hr>";
}
////////////////// Segunda parte...