$xml_cfdi_base64
$username
$password
XML;
#== 12.6 Proceso para guardar los datos que se envían al servidor en un archivo .XML ========================
$NomArchSoap = $SendaCFDI."SOAP_Envio_Factura_".$NoFac.".xml";
#== 12.6.1 Si el archivo ya se encuentra se elimina ===========================
if (file_exists ($NomArchSoap)==true){
unlink($NomArchSoap);
}
#== 12.6.2 Se crea el archivo .XML con el SOAP ================================
// Descomentar si se desea gragar en un archivo el SOAP de envío al servidor.
// $fp = fopen($NomArchSoap,"a");
// fwrite($fp, $cfdixml);
// fclose($fp);
// chmod($NomArchSoap, 0777);
#=== 12.7 Muestra el contenido del SOAP que se envía al servidor del PAC (REQUEST) =========================
echo '';
echo 'CONTENIDO DEL SOAP QUE SE ENVIA AL SERVIDOR DEL PAC';
echo '
';
echo '';
echo htmlspecialchars($cfdixml);
echo '
';
#== 12.8 Se envía el contenido del SOAP al servidor del PAC =====================
curl_setopt($process, CURLOPT_HTTPHEADER, array('Content-Type: text/xml',' charset=utf-8'));
curl_setopt($process, CURLOPT_POSTFIELDS, $cfdixml);
curl_setopt($process, CURLOPT_RETURNTRANSFER, true);
curl_setopt($process, CURLOPT_POST, true);
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($process, CURLOPT_SSL_VERIFYHOST, false);
$RespServ = curl_exec($process);
#== 12.9 Se muestra la respuesta del servidor del PAC (opcional a mostrar) ================
echo '';
echo 'RESPUESTA DEL SERVIDOR DEL PAC';
echo '
';
echo '';
echo htmlspecialchars($RespServ);
echo '
';
curl_close($process);
## FIN DEL PROCESO DE TIMBRADO #################################################
## 13. PROCESOS POSTERIORES AL TIMBRADO ########################################
#== 13.1 Se asigna la respuesta del servidor a una variable de tipo DOM ====
$VarXML = new DOMDocument();
$VarXML->loadXML($RespServ);
#== 13.2 Se graba la respuesta del servidor a un archivo .xml
// Descomentar si se desea gragar el archivo con la respuesta del servidor.
// $VarXML->save($SendaCFDI."RespServ_Factura_".$NoFac.".xml");
// chmod($SendaCFDI."RespServ_Factura_".$NoFac.".xml", 0777);
echo "
";
#== 13.3 Se asigna el contenido del tag "xml" a una variable ===============
$RespServ = $VarXML->getElementsByTagName('xml');
#== 13.4 Se obtiene el valor del nodo ======================================
$valor_del_nodo = "";
foreach($RespServ as $Nodo){
$valor_del_nodo = $Nodo->nodeValue;
}
#== Si el nodo contiene datos se realizan los siguientes procesos ======
if($valor_del_nodo != ""){
// unlink($SendaCFDI."xlst_".$NoFac.".xml"); <-- Puede ser descomentado para eliminar el archivo .XML sin timbrar.
#== 13.5 Se muestra el .XML ya timbrado (CFDI V 3.2), opcional a mostrar =====
echo '';
echo 'FACTURA .XML (CFDI) YA TIMBRADA';
echo '
';
echo '';
echo htmlspecialchars($Nodo->nodeValue);
echo '
';
#=== 13.6 Guardando el CFDI en archivo .XML ============================
$NomArchXML = "CFDI-40_Factura_".$NoFac.".xml";
$NomArchPDF = "CFDI-40_Factura_".$NoFac.".pdf";
$xmlt = new DOMDocument();
$xmlt->loadXML($valor_del_nodo);
$xmlt->save($SendaCFDI.$NomArchXML);
chmod($SendaCFDI.$NomArchXML, 0777);
#== 13.7 Procesos para extraer datos del Timbre Fiscal del CFDI =========
$docXML = new DOMDocument();
$docXML->load($SendaCFDI."CFDI-40_Factura_".$NoFac.".xml");
$params = $docXML->getElementsByTagName("Comprobante");
foreach ($params as $param) {
$VersionCFDI = $param->getAttribute("Version");
$Total = $param->getAttribute('Total');
$Serie = $param->getAttribute('Serie');
$Folio = $param->getAttribute('Folio');
}
$SerieFolio = $Serie.$Folio;
$comprobante = $docXML->getElementsByTagName("TimbreFiscalDigital");
#== 13.8 Se obtienen contenidos de los atributos y se asignan a variables para ser mostrados =======
foreach($comprobante as $timFis){
$version_timbre = $timFis->getAttribute('Version');
$sello_SAT = $timFis->getAttribute('SelloSAT');
$cert_SAT = $timFis->getAttribute('NoCertificadoSAT');
$sello_CFD = $timFis->getAttribute('SelloCFD');
$tim_fecha = $timFis->getAttribute('FechaTimbrado');
$tim_uuid = $timFis->getAttribute('UUID');
echo '';
echo 'Serie y Folio: '.$SerieFolio.'
';
echo 'Versión de CFDI: '.$VersionCFDI.'
';
echo 'Versión de timbre: '.$version_timbre.'
';
echo 'Sello del SAT: '.$sello_SAT.'
';
echo 'Certificado del SAT: '.$cert_SAT.'
';
echo 'Sello del CFDI: '.$sello_CFD.'
';
echo 'Fecha de timbrado: '.$tim_fecha.'
';
echo 'Folio fiscal: '.$tim_uuid.'
';
echo 'Importe total: '.$Total.'
';
echo '
';
}
$params = $docXML->getElementsByTagName('Emisor');
foreach ($params as $param) {
$Emisor_RFC = $param->getAttribute('Rfc');
}
$params = $docXML->getElementsByTagName('Receptor');
foreach ($params as $param) {
$Receptor_RFC = $param->getAttribute('Rfc');
}
$params = $docXML->getElementsByTagName('Comprobante');
foreach ($params as $param) {
$total = $param->getAttribute('Total');
}
#== 13.9 Se crea el archivo .PNG con codigo bidimensional =================================
$filename = "archs_graf/Img_".$tim_uuid.".png";
$CadImpTot = ProcesImpTot($total);
$Cadena = "?re=".$Emisor_RFC."&rr=".$Receptor_RFC."&tt=".$CadImpTot."&id=".$tim_uuid;
QRcode::png($Cadena, $filename, 'H', 3, 2);
chmod($filename, 0777);
echo '';
echo 'GRÁFICO "QR" RESULTANTE.';
echo '
';
echo '
';
#== 13.10 Se crea código HTML para mostrar opciones al usuario.
?>
TODO supply a title
getElementsByTagName('CodigoError');
foreach($codigoError as $NodoStatus){
$valorNod = $NodoStatus->nodeValue;
}
echo '';
echo 'CÓDIGO DE ERROR.';
echo '
';
echo '';
echo $valorNod;
echo '
';
}
##### FIN DE PROCEDIMIENTOS ####################################################
### 14. FUNCIONES DEL MÓDULO ###################################################
# 14.1 Función que integra los nodos al archivo .XML y forma la "Cadena original".
function cargaAtt(&$nodo, $attr){
global $xml, $cadena_original;
$quitar = array('sello'=>1,'noCertificado'=>1,'certificado'=>1);
foreach ($attr as $key => $val){
$val = preg_replace('/\s\s+/', ' ', $val);
$val = trim($val);
if (strlen($val)>0){
$val = str_replace("|","/",$val);
$nodo->setAttribute($key,$val);
if (!isset($quitar[$key]))
if (substr($key,0,3) != "xml" &&
substr($key,0,4) != "xsi:")
$cadena_original .= $val . "|";
}
}
}
# 14.2 Función que integra los nodos al archivo .XML sin integrar a la "Cadena original".
function cargaAttSinIntACad(&$nodo, $attr){
global $xml;
$quitar = array('sello'=>1,'noCertificado'=>1,'certificado'=>1);
foreach ($attr as $key => $val){
$val = preg_replace('/\s\s+/', ' ', $val);
$val = trim($val);
if (strlen($val)>0){
$val = str_replace("|","/",$val);
$nodo->setAttribute($key,$val);
if (!isset($quitar[$key]))
if (substr($key,0,3) != "xml" &&
substr($key,0,4) != "xsi:");
}
}
}
# 14.3 Funciónes que da formato al "Importe total" como lo requiere el SAT para ser integrado al código QR.
function ProcesImpTot($ImpTot){
$ImpTot = number_format($ImpTot, 4); // <== Se agregó el 30 de abril de 2017.
$ArrayImpTot = explode(".", $ImpTot);
$NumEnt = $ArrayImpTot[0];
$NumDec = ProcesDecFac($ArrayImpTot[1]);
return $NumEnt.".".$NumDec;
}
function ProcesDecFac($Num){
$FolDec = "";
if ($Num < 10){$FolDec = "00000".$Num;}
if ($Num > 9 and $Num < 100){$FolDec = $Num."0000";}
if ($Num > 99 and $Num < 1000){$FolDec = $Num."000";}
if ($Num > 999 and $Num < 10000){$FolDec = $Num."00";}
if ($Num > 9999 and $Num < 100000){$FolDec = $Num."0";}
return $FolDec;
}