'; echo 'PROCESO DE TIMBRADO DE CFDI 3.3 CON COMPLEMENTO DE NÓMINA 1.2'; echo ''; echo 'LogoSAT'; ### 1. CONFIGURACIÓN INICIAL ###################################################### # 1.1 Configuración de zona horaria date_default_timezone_set('America/Mexico_City'); $Fec1 = date("d/m/Y"); $Fec2 = date("Y/m/d"); $Hora = date("H:i:s"); echo $Fec1." | ".$Hora."

"; # 1.2 Muestra la zona horaria predeterminada del servidor (opcional a mostrar) echo '
'; echo 'ZONA HORARIA PREDETERMINADA'; echo '
'; echo '
'; echo date_default_timezone_get(); echo '

'; ### 2. ASIGNACIÓN DE VALORES A VARIABLES ########################################## $SendaPEMS = "archs_pem/"; // 2.1 Directorio en donde se encuentran los archivos *.cer.pem y *.key.pem (para efectos de demostración se utilizan los que proporciona el SAT para pruebas). $SendaCFDI = "archs_cfdi/"; // 2.2 Directorio en donde se almacenarán los archivos *.xml (CFDIs). $SendaGRAFS = "archs_graf/"; // 2.3 Directorio en donde se almacenan los archivos .jpg (logo de la empresa) y .png (códigos bidimensionales). // 2.5 Datos de acceso del usuario (proporcionados por www.finkok.com) modo de integración (para pruebas) o producción. $username = "carlosrodriguez_rodriguez@hotmail.com"; $password = "Rorc760408$"; ### MUESTRA LOS DATOS DEL USUARIO QUE ESTÁ TIMBRANDO (OPCIONAL A MOSTRAR) ###### echo '
'; echo 'DATOS DEL USUARIO QUE ESTÁ TIMBRANDO'; echo '
'; echo '
'; echo 'USUARIO: '.$username."
"; echo 'PASSWORD: '.$password."
"; echo '

'; ### 3. DEFINICIÓN DE VARIABLES INICIALES ########################################## $noCertificado = "30001000000400002434"; // 3.1 Número de certificado. $file_cer = "EKU9003173C9.cer.pem"; // 3.2 Nombre del archivo .cer.pem $file_key = "EKU9003173C9.key.pem"; // 3.3 Nombre del archivo .cer.key ################################################################################### ### DATOS GENERALES DEL RECIBO DE NÓMINA ########################################## $TipoNomina = "O"; // Clave de TipoNomina: O= Nómina ordinaria o E= Nómina extraordinaria $RegistroPatronal = "Y3743947107"; // Registro patronal. $fact_serie = "A"; // Número de serie. $fact_folio = mt_rand(1000, 9999); // Número de folio. $NoRecNom = $fact_serie.$fact_folio; // Serie del RECIBO concatenado con el número de folio. $fact_tipcompr = "egreso"; // Tipo de comprobante. $fecha_fact = date("Y-m-d")."T".date("H:i:s"); // Fecha y hora de facturación. $metodoDePago = "NA"; // En nómina la clave del método de pago debe ser NA. // $formaDePago = "PAGO EN UNA SOLA EXHIBICION"; // Forma de pago. $TipoCambio = 1; // Tipo de cambio de la moneda. $moneda = "MXN"; // Moneda $TipoCambio = 1; // 4.16 Tipo de cambio de la moneda. $LugarExpedicion = "58000"; // Lugar de expedición. $fact_exportacion = "01"; // Atributo requerido para expresar si el comprobante ampara una operación de exportación. $totalPercepciones = "0.00"; // Total de percepciones. $totalDeducciones = "0.00"; // Total de deducciones. $totalOtrosPagos = "0.00"; // Suma de otros pagos. $Percep_TotalSueldos = "0.00"; // Percepciones, total sueldos. $Percep_TotalGravado = "0.00"; // Percepciones, total gravado. $Percep_TotalExento = "0.00"; // Percepciones, total exento. $TotalOtrasDeducciones = "0.00"; // Deducciones, total otras deducciones. $TotalImpuestosRetenidos = "0.00"; // Deducciones, toal impuestos retenidos. $subTotal = "0.00"; // SubTotal. $descuento = "0.00"; // descuento. $total = "0.00"; // Total. ### No. DE CFDI ASIGNADO (CONTROL INTERNO) ###### echo '
'; echo 'No. DE CFDI'; echo '
'; echo '
'; echo $NoRecNom; echo '

'; ### 9. DATOS GENERALES DEL EMISOR ################################################# $emisor_rs = "ESCUELA KEMPER URGATE"; // 9.1 Nombre o Razón social. $emisor_rfc = "EKU9003173C9"; // 9.2 RFC (al momento de timbrar el SAT comprueba que el RFC se encuentre registrado y vigente en su base de datos) $emisor_ClaRegFis = "601"; // 9.3 Clave del Régimen fiscal. ### DATOS DEL EMPLEADO (RECEPTOR) ###################################################### $receptor_rfc = "MASO451221PM4"; // RFC del empleado. $receptor_nom = "MARIA OLIVIA MARTINEZ SAGAZ"; // Nombre del empleado. $DomicilioFiscalReceptor = "80290"; $RegimenFiscalReceptor = "605"; $UsoCFDI = "CN01"; $NumEmpleado = "001"; $CURP_Empleado = "GOVA550404MTSMLN15"; $Departamento = "SISTEMAS"; $Puesto = "PROGRAMADOR"; $NumSeguridadSocial = "43715435038"; $PeriodicidadPago = "04"; // Nomina ======================================== $FechaInicioRelLaboral = "2016-06-01"; // <====== $FechaPago = "2016-10-31"; $FechaInicialPago = "2016-10-17"; $FechaFinalPago = "2016-10-31"; // <====== $NumDiasPagados = "15"; $Antigüedad = "P21W"; $SalarioDiarioIntegrado = "304.00"; $TipoContrato = "01"; $TipoJornada = "01"; $TipoRegimen = "02"; $Banco = "012"; $CuentaBancaria = "6787543287"; $ClaveEntFed = "AGU"; $ClaveRiesgoPuesto = "1"; ### MUESTRA LA ZONA HORARIA PREDETERMINADA DEL SERVIDOR (OPCIONAL A MOSTRAR) ### echo '
'; echo 'FECHA Y HORA DE SOLICITUD DE TIMBRADO'; echo '
'; echo '
'; echo $fecha_fact; // 6.1 Se muestra solo para consultar y confirmar que sea la correcta. echo '

'; ### PERCEPCIONES ############################################################### // ArraysPercepciones. $ArrayPercep_Clave = ['101', '102', '114', '116', '122', '1CH', '1SC']; $ArrayPercep_Concepto = ['SUELDO BASE', 'FONDO SOCIAL DE PREV MULT', 'COMPENSACION EXTRAORDINARIA', 'B O N O S I N D I C A L', 'D E S P E N S A', 'COMP HOMOLOG A SIMILARES PODER', 'COMPLEMENTO SALARIAL']; $ArrayPercep_ImporteExento = ['0', '77.28', '0', '224.17', '120.72', '0', '0']; $ArrayPercep_ImporteGravado = ['3184', '0', '1737.65', '0', '0', '125.5', '165.48']; $ArrayPercep_TipoPercepcion = ['001', '038', '038', '038', '029', '001', '001']; $ConceptPagNom_ValorUni = 0; for ($i=0; $icreateElement("cfdi:Comprobante"); $root = $xml->appendChild($root); $cadena_original='||'; $noatt= array(); #== 11.3 Rutina de integración de nodos ========================================= cargaAtt($root, array( "Version"=>"4.0", "Serie"=>$fact_serie, "Folio"=>$fact_folio, "Fecha"=>date("Y-m-d")."T".date("H:i:s"), "NoCertificado"=>$noCertificado, "SubTotal"=>$subTotal, "Descuento"=>$totalDeducciones, "Moneda"=>"MXN", "TipoCambio"=>$TipoCambio, "Total"=>$total, "TipoDeComprobante"=>"N", "Exportacion"=>$fact_exportacion, "MetodoPago"=>"PUE", "LugarExpedicion"=>$LugarExpedicion, ) ); #== 11.2 Se crea e inserta el primer nodo donde se declaran los namespaces ====== cargaAttSinIntACad($root, array( "xmlns:cfdi"=>"http://www.sat.gob.mx/cfd/4", "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance", "xmlns:nomina12"=>"http://www.sat.gob.mx/nomina12", "xsi:schemaLocation"=>"http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina12.xsd" ) ); ################################################################################################ $emisor = $xml->createElement("cfdi:Emisor"); $emisor = $root->appendChild($emisor); cargaAtt($emisor, array( "Rfc"=>$emisor_rfc, "Nombre"=>$emisor_rs, "RegimenFiscal"=>$emisor_ClaRegFis ) ); $receptor = $xml->createElement("cfdi:Receptor"); $receptor = $root->appendChild($receptor); cargaAtt($receptor, array( "Rfc"=>$receptor_rfc, "Nombre"=>$receptor_nom, "DomicilioFiscalReceptor"=>$DomicilioFiscalReceptor, "RegimenFiscalReceptor"=>$RegimenFiscalReceptor, "UsoCFDI"=>$UsoCFDI ) ); $conceptos = $xml->createElement("cfdi:Conceptos"); $conceptos = $root->appendChild($conceptos); $concepto = $xml->createElement("cfdi:Concepto"); $concepto = $conceptos->appendChild($concepto); cargaAtt($concepto, array( "ClaveProdServ"=>"84111505", "Cantidad"=>"1", "ClaveUnidad"=>"ACT", "Descripcion"=>utf8_decode("Pago de nómina"), "ValorUnitario"=>$ConceptPagNom_ValorUni, "Importe"=>$ConceptPagNom_Importe, "Descuento"=>$totalDeducciones, "ObjetoImp"=>"01", ) ); // INICIA CODIFICACIÓN DEL COMPLEMENTO DE NÓMINA 1.2 ########################### $complemento = $xml->createElement("cfdi:Complemento"); $complemento = $root->appendChild($complemento); $nomina = $xml->createElement("nomina12:Nomina"); $nomina = $complemento->appendChild($nomina); cargaAtt($nomina, array( "Version"=>"1.2", "TipoNomina"=>"O", "FechaPago"=>"2017-03-15", "FechaInicialPago"=>"2017-03-01", "FechaFinalPago"=>"2017-03-15", "NumDiasPagados"=>"15", "TotalPercepciones"=>$totalPercepciones, "TotalDeducciones"=>$totalDeducciones, "TotalOtrosPagos"=>$totalOtrosPagos ) ); $NominaEmisor = $xml->createElement("nomina12:Emisor"); $NominaEmisor = $nomina->appendChild($NominaEmisor); cargaAtt($NominaEmisor, array( "RegistroPatronal"=>"C111119110-0" ) ); // $EntidadSNCF = $xml->createElement("nomina12:EntidadSNCF"); // $EntidadSNCF = $NominaEmisor->appendChild($EntidadSNCF); // cargaAtt($EntidadSNCF, array( // "OrigenRecurso"=>"IP" // ) // ); $NominaReceptor = $xml->createElement("nomina12:Receptor"); $NominaReceptor = $nomina->appendChild($NominaReceptor); cargaAtt($NominaReceptor, array( "Curp"=>"VAAI901027HNLRRS07", "NumSeguridadSocial"=>"01131121161", "FechaInicioRelLaboral"=>"2001-11-16", "Antigüedad"=>"P799W", "TipoContrato"=>"01", "Sindicalizado"=>utf8_decode("Sí"), "TipoJornada"=>"01", "TipoRegimen"=>"02", "NumEmpleado"=>"143712", "Departamento"=>"Ejecutivo de Pruebas", "Puesto"=>"CHOFER", "RiesgoPuesto"=>"2", "PeriodicidadPago"=>"04", "SalarioBaseCotApor"=>"231.67", "SalarioDiarioIntegrado"=>"428.46", "ClaveEntFed"=>"MIC" ) ); $percepciones = $xml->createElement("nomina12:Percepciones"); $percepciones = $nomina->appendChild($percepciones); cargaAtt($percepciones, array( "TotalSueldos"=>$Percep_TotalSueldos, "TotalGravado"=>$Percep_TotalGravado, "TotalExento"=>$Percep_TotalExento ) ); // Ciclo "for", recopilación de datos de percepciones. =============== for ($i=0; $icreateElement("nomina12:Percepcion"); $percepcion = $percepciones->appendChild($percepcion); cargaAtt($percepcion, array( "TipoPercepcion"=>$ArrayPercep_TipoPercepcion[$i], "Clave"=>$ArrayPercep_Clave[$i], "Concepto"=>$ArrayPercep_Concepto[$i], "ImporteGravado"=>$ArrayPercep_ImporteGravado[$i], "ImporteExento"=>$ArrayPercep_ImporteExento[$i] ) ); } if (count($ArrayDeduc_TipoDeduccion)>0){ $deducciones = $xml->createElement("nomina12:Deducciones"); $deducciones = $nomina->appendChild($deducciones); cargaAtt($deducciones, array( "TotalOtrasDeducciones"=>$TotalOtrasDeducciones, "TotalImpuestosRetenidos"=>$TotalImpuestosRetenidos ) ); // Ciclo "for", recopilación de datos de deducciones. =============== for ($i=0; $icreateElement("nomina12:Deduccion"); $deduccion = $deducciones->appendChild($deduccion); cargaAtt($deduccion, array( "TipoDeduccion"=>$ArrayDeduc_TipoDeduccion[$i], "Clave"=>$ArrayDeduc_Clave[$i], "Concepto"=>$ArrayDeduc_Concepto[$i], "Importe"=>$ArrayDeduc_Importe[$i] ) ); } } if (count($ArrayOtrosPag_TipoOtroPago)>0){ $otrosPagos = $xml->createElement("nomina12:OtrosPagos"); $otrosPagos = $nomina->appendChild($otrosPagos); // cargaAtt($otrosPagos, array( // "TotalOtrosPagos"=>"100.00" // ) // ); // Ciclo "for", recopilación de datos de deducciones. =============== for ($i=0; $icreateElement("nomina12:OtroPago"); $otroPago = $otrosPagos->appendChild($otroPago); cargaAtt($otroPago, array( "TipoOtroPago"=>$ArrayOtrosPag_TipoOtroPago[$i], "Clave"=>$ArrayOtrosPag_Clave[$i], "Concepto"=>$ArrayOtrosPag_Concepto[$i], "Importe"=>$ArrayOtrosPag_Importe[$i] ) ); if ($ArrayOtrosPag_TipoOtroPago[$i]=="002"){ $SubAlEmpl = $xml->createElement("nomina12:SubsidioAlEmpleo"); $SubAlEmpl = $otroPago->appendChild($SubAlEmpl); cargaAtt($SubAlEmpl, array("SubsidioCausado"=>$ArrayOtrosPag_Importe[$i])); } } } #== 11.6 Termina de conformarse la "Cadena original" con doble || $cadena_original .= "|"; // Descomentar si se desea grabar la Cadena original en un archivo. // $file = fopen($SendaCFDI."CadenaOriginal_RecNom_".$NoRecNom.".txt", "w"); // fwrite($file, $cadena_original . PHP_EOL); // fclose($file); // chmod($SendaCFDI."CadenaOriginal_RecNom_".$NoRecNom.".txt", 0777); #=== Muestra la cadena original (opcional a mostrar) ======================= echo '
'; echo 'CADENA ORIGINAL'; echo '
'; echo '
'; echo $cadena_original; echo '

'; #== 11.8 Proceso para obtener el sello digital del archivo .pem.key ======== $keyid = openssl_get_privatekey(file_get_contents($SendaPEMS.$file_key)); openssl_sign($cadena_original, $crypttext, $keyid, OPENSSL_ALGO_SHA256); openssl_free_key($keyid); #== 11.9 Se convierte la cadena digital a Base 64 ========================== $sello = base64_encode($crypttext); #=== Muestra el sello (opcional a mostrar) ================================= echo '
'; echo 'SELLO'; echo '
'; echo '
'; echo $sello; echo '

'; #== 11.10 Proceso para extraer el certificado del sello digital ============ $file = $SendaPEMS.$file_cer; // Ruta al archivo $datos = file($file); $certificado = ""; $carga=false; for ($i=0; $i'; echo 'CERTIFICADO DEL SELLO DIGITAL'; echo ''; echo '
'; echo $certificado; echo '

'; #== 11.12 Se continua con la integración de nodos =========================== $root->setAttribute("Sello",$sello); $root->setAttribute("Certificado",$certificado); # Certificado. #== Fin de la integración de nodos ========================================= $NomArchCFDI = $SendaCFDI."PreCFDI-40_RecNom_".$NoRecNom.".xml"; #=== 11.12 Se guarda el archivo .XML antes de ser timbrado ======================= $cfdi = $xml->saveXML(); $xml->formatOutput = true; $xml->save($NomArchCFDI); // Guarda el archivo .XML (sin timbrar) en el directorio predeterminado. unset($xml); #=== 11.13 Se dan permisos de escritura al archivo .xml. ========================= chmod($NomArchCFDI, 0777); ##### FIN DE LA CREACIÓN DEL ARCHIVO .XML ANTES DE SER TIMBRADO #################################################### ### 12. PROCESO DE TIMBRADO ######################################################## #=== Se muestra el .XML antes de ser timbrado (opcional a mostrar)========== echo '
'; echo 'ARCHIVO .XML A TIMBRAR'; echo '
'; echo '
'; echo htmlspecialchars($cfdi); echo '

'; #== 12.1 Se crea una variable de tipo DOM y se le carga el CFDI ================================= $xml2 = new DOMDocument(); $xml2->loadXML($cfdi); #== 12.2 Convirtiendo el contenido del CFDI a BASE 64 ====================== $xml_cfdi_base64 = base64_encode($cfdi); #== 12.3 Datos de acceso al servidor de pruebas ============================ $process = curl_init('https://demo-facturacion.finkok.com/servicios/soap/stamp.wsdl'); #== 12.4 Datos de acceso al servidor de producción ========================= # $process = curl_init('https://facturacion.finkok.com/servicios/soap/stamp.wsdl'); #== 12.5 Creando el SOAP de envío ============================================== $cfdixml = << $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_RecNom_".$NoRecNom.".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 grabar el SOAP de envío en un archivo. // $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 // $VarXML->save($SendaCFDI."RespServ_RecNom_".$NoRecNom.".xml"); // chmod($SendaCFDI."RespServ_RecNom_".$NoRecNom.".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 ====================================== 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_".$NoRecNom.".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 'ARCHIVO .XML (CFDI CON COMPLEMENTO DE NÓMINA) YA TIMBRADO'; echo '
'; echo '
'; echo htmlspecialchars($Nodo->nodeValue); echo '

'; #=== 13.6 Guardando el CFDI en archivo .XML ============================ $NomArchXML = "CFDI-40_RecNom_".$NoRecNom.".xml"; $NomArchPDF = "CFDI-40_RecNom_".$NoRecNom.".pdf"; $xmlt = new DOMDocument(); $xmlt->loadXML($valor_del_nodo); $xmlt->save($SendaCFDI.$NomArchXML); chmod($SendaCFDI.$NomArchXML, 0777); #== 13.6.1 Convertir archivo .XML a UTF-8 (OPCIONAL). // $file_name = $SendaCFDI.$NomArchXML; // $f = file_get_contents($file_name); // $f = iconv("WINDOWS-1252", "UTF-8", $f); // file_put_contents($file_name, "\xEF\xBB\xBF".$f); #== 13.7 Procesos para extraer datos del Timbre Fiscal del CFDI ========= $docXML = new DOMDocument(); $docXML->load($SendaCFDI."CFDI-40_RecNom_".$NoRecNom.".xml"); $params = $docXML->getElementsByTagName("Comprobante"); foreach ($params as $param) { $VersionCFDI = $param->getAttribute("Version"); } $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 '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.'
'; } #== 13.8.1 Se muestra el número de factura asignado por el sistema local (no asingado por el SAT). echo 'No. de factura asignado por el sistema local: '.$NoRecNom.'

'; $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 ''.$filename.''; #== 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 = utf8_encode(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 = utf8_encode(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); $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; }