<?php
	if(!isset($_SESSION)) session_start();
	require_once "modelos/cfdi.php";
	require_once "modelos/pagos.php";
	require_once "modelos/bd.php";
	require_once "config.php";
	require_once "ws_conexion.php";
	header('Content-Type: application/json');
	
	//Se toman parametros recibidos
	$json = file_get_contents('php://input');
	$data = json_decode($json);
	
	if (strlen($json) > 5){
		$pAccion = $data->pAccion;
	} else {
		$pAccion = "0";
	}
	
	//Invocamos armado segun tipo de parametro recibido
	switch ($pAccion) {
		//TIMBRADO FACTURA
		case 'cfdi_factura':
			$pIdEmpresa = $data->pIdEmpresa;
			$pTipoSistema = $data->pTipoSistema;
			$pIdFactura = $data->pIdFactura;
		
			$response = timbrado_factura($pIdEmpresa, $pTipoSistema, $pIdFactura, $conn);
			echo json_encode($response);
			break;
			
		//TIMBRADO NOTA DE CREDITO
		case 'cfdi_nota': 
		
			$pIdEmpresa = $data->pIdEmpresa;
			$pTipoSistema = $data->pTipoSistema;
			$pIdNota = $data->pIdNota;
		
			$response = timbrado_nota($pIdEmpresa, $pTipoSistema, $pIdNota, $conn);
			echo json_encode($response);
			break;
		
		
		//TIMBRADO COMPLEMENTO
		case 'cfdi_complemento':
		
			$pIdEmpresa = $data->pIdEmpresa;
			$pTipoSistema = $data->pTipoSistema;
			$pIdPago = $data->pIdPago;
			
			$response = timbrado_pago($pIdEmpresa, $pTipoSistema, $pIdPago, $conn);
			echo json_encode($response);
			break;
		default:
			echo json_encode("La peticion recibida es incorrecta, intente nuevamente");
			break;
	}
	
	
	/////////////////////////////////////////////////////////////////////////////////
	////			1		TIMBRADO FACTURA 									/////
	/////////////////////////////////////////////////////////////////////////////////
	function timbrado_factura($idEmpresa, $tipoSistema, $idFactura, $conexion){
		
		/*echo "idEmpresa". $idEmpresa;
		echo "Tipo sistema". $tipoSistema;
		echo "idFactura". $idFactura;*/
		
		try {
			//Obtener datos de encabezado
			$stmt = $conexion->prepare("call setivera_facturacion.Facturas_ObtenerEncabezado('$idEmpresa','$tipoSistema','$idFactura')");
			$stmt->execute();	
				
			$numRegistrosEncabezado = $stmt->rowCount();
			$datosEncabezado = [];
			
			if($numRegistrosEncabezado > 0) {
				while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_encabezado_factura();
					$respuesta->Serie = $row["Serie"];
					$respuesta->Folio = $row["Folio"];
					$respuesta->Fecha = $row["Fecha"];
					$respuesta->FormaPago = $row["FormaPago"];
					$respuesta->Subtotal = $row["Subtotal"];
					$respuesta->Descuento = $row["Descuento"];
					$respuesta->Moneda = $row["moneda"];
					$respuesta->TipoCambio = $row["tipocambio"];
					$respuesta->Total = $row["Total"];
					$respuesta->TipoComprobante = $row["TipoComprobante"];
					$respuesta->MetodoPago = $row["MetodoPago"];
					$respuesta->LugarExpedicion = $row["LugarExpedicion"];
					$respuesta->RFC = $row["RFC"];
					$respuesta->RazonSocial = $row["RazonSocial"];
					$respuesta->RFCReceptor = $row["RFCReceptor"];
					$respuesta->RSReceptor = $row["RSReceptor"];
					$respuesta->Pais = $row["pais"];
					$respuesta->RegIdTrib = $row["RegIdTrib"];
					$respuesta->UsoCFDI = $row["UsoCFDI"];
					$respuesta->DomEmisor = $row["DomEmisor"];
					$respuesta->DomReceptor = $row["DomReceptor"];
					$respuesta->TotalImpuestoTrasladado = $row["TotalImpuestoTrasladado"];
					$respuesta->ClaveImpuestoGral = $row["ClaveImpuestoGral"];
					$respuesta->FactorGral = $row["FactorGral"];
					$respuesta->TasaoCuotaGral = $row["TasaoCuotaGral"];
					$respuesta->ImporteIVAGral = $row["ImporteIVAGral"];
					
					$respuesta->NoExtEmisor = $row["NoExtEmisor"];
					$respuesta->ColEmisor = $row["ColEmisor"];
					$respuesta->CPEmisor = $row["CPEmisor"];
					$respuesta->LocalidadEmisor = $row["LocalidadEmisor"];
					$respuesta->MunicipioEmisor = $row["MunicipioEmisor"];
					$respuesta->EstadoEmisor = $row["EstadoEmisor"];
					$respuesta->PaisEmisor = $row["PaisEmisor"];
					$respuesta->NoExtReceptor = $row["NoExtReceptor"];
					$respuesta->ColReceptor = $row["ColReceptor"];
					$respuesta->CPReceptor = $row["CPReceptor"];
					$respuesta->LocalidadReceptor = $row["LocalidadReceptor"];
					$respuesta->MunicipioReceptor = $row["MunicipioReceptor"];
					$respuesta->EstadoReceptor = $row["EstadoReceptor"];
					$respuesta->PaisReceptor = $row["PaisReceptor"];
					$respuesta->Correo = $row["CuentaCorreo"];
					
					$datosEncabezado[] = $respuesta;
					//return json_encode($datosEncabezado);
				};
				$stmt->closeCursor();
			} else {
				return "No se pudieron obtener los datos del encabezado del CFDI";
			}
			
			//Obtener detalle de conceptos de factura 
			$stmt2 = $conexion->prepare("call setivera_facturacion.Facturas_ObtenerDetalleConceptos('$idEmpresa','$tipoSistema','$idFactura')");
			$stmt2->execute();	
				
			$numRegistrosDetalle = $stmt2->rowCount();
			$datosDetalle = [];
			
			if($numRegistrosDetalle > 0) {
				//while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
				while($row = $stmt2->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_detalle_factura();
					$respuesta->ProdoServ = $row["ProdoServ"];
					$respuesta->ClaveUnidad = $row["ClaveUnidad"];
					$respuesta->Unidad = $row["Unidad"];
					
					$respuesta->NomServicio = $row["NomServicio"];
					$respuesta->desc_buque = $row["desc_buque"];
					
					$respuesta->desc_viaje = $row["desc_viaje"];
					$respuesta->descservicio = $row["descservicio"];
					$respuesta->Hora_Inicio = $row["Hora_Inicio"];
					$respuesta->Hora_Termino = $row["Hora_Termino"];
					$respuesta->TRB = $row["TRB"];
					$respuesta->Eslora = $row["Eslora"];
					$respuesta->SERVICIO = $row["SERVICIO"];
					$respuesta->Cantidad = $row["Cantidad"];
					$respuesta->ValorUnitario = $row["ValorUnitario"];
					$respuesta->Importe = $row["Importe"];
					$respuesta->Descuento = $row["Descuento"];
					$respuesta->BaseTraslado = $row["BaseTraslado"];
					$respuesta->ClaveImpuesto = $row["ClaveImpuesto"];
					$respuesta->Factor = $row["Factor"];
					$respuesta->TasaoCuota = $row["TasaoCuota"];
					$respuesta->ImporteTraslado = $row["ImporteTraslado"];
					$datosDetalle[] = $respuesta;
				};
				$stmt2->closeCursor();
				//return json_encode($datosDetalle);
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			
			//Obtención de parametros de timbrado PAC
			//Obtener detalle de conceptos de factura 
			$stmt3 = $conexion->prepare("call setivera_facturacion.obtener_parametros_pac()");
			$stmt3->execute();	
				
			$numRegistrosDetalle = $stmt2->rowCount();
			$datosPAC = [];
			
			if($numRegistrosDetalle > 0) {
				//while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
				while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_configuracion_pac();
					$respuesta->token = $row["token"];
					$respuesta->pem_cer = $row["pem_cer"];
					$respuesta->pem_key = $row["pem_key"];
					$respuesta->logo = $row["logo"];
					$respuesta->url_ws = $row["url_ws"];
					$datosPAC[] = $respuesta;
				};
				$stmt3->closeCursor();
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			
			/////////////////////////////////////////////
			//////////////  ARMADO DEL JSON /////////////
			/////////////////////////////////////////////
			
			//Variables Auxiliares
			$mensaje = "";
			$temp = 0;
			$permitirTimbrado = false;
			$tieneExentos = 0;
			$NoCertificado = "30001000000400002447";
			
			$JSONrequest = new Peticion;
			$cfdi = new CFDI_JSON;
			$datosCUSTOMDATA = new Addenda;
			
			try {
				//DATOS GENERALES
				$mensaje = "Error al llenar el encabezado (datos generales del nodo comprobante)";
				//$cfdi->NoCertificado = $datosEncabezado[0]->NoCertificado;
				$cfdi->NoCertificado = $NoCertificado;
				$cfdi->Serie = $datosEncabezado[0]->Serie;
				$cfdi->Folio = $datosEncabezado[0]->Folio;
				$cfdi->SubTotal = $datosEncabezado[0]->Subtotal;
				$cfdi->Moneda = $datosEncabezado[0]->Moneda;
				$cfdi->CondicionesDePago = "NA";
				$cfdi->TipoCambio = $datosEncabezado[0]->TipoCambio;
				$cfdi->Total = $datosEncabezado[0]->Total;
				$cfdi->TipoDeComprobante = $datosEncabezado[0]->TipoComprobante;
				$cfdi->MetodoPago = $datosEncabezado[0]->MetodoPago;
				$cfdi->FormaPago = $datosEncabezado[0]->FormaPago;
				if (floatval($datosEncabezado[0]->Descuento) >0){
					$cfdi->Descuento = $datosEncabezado[0]->Descuento;
				}
				$cfdi->LugarExpedicion = $datosEncabezado[0]->LugarExpedicion;
				//$cfdi->Confirmacion = null;
				$cfdi->LugarExpedicion = $datosEncabezado[0]->LugarExpedicion;
				
				$mensaje = "Error al parsear la fecha al formato requerido por el PAC --> YYYY-MM-DDTHH:MM:SS";
				$comp = explode(" ", $datosEncabezado[0]->Fecha);
				$fechacomp = explode("/", $comp[0]);
				$horacomp = explode(":", $comp[1]);
				$cfdi->Fecha = $fechacomp[2] . "-" . $fechacomp[1] . "-" . $fechacomp[0] . "T" . $comp[1];
				
				//CFDI RELACIONADOS
				$mensaje = "Error al llenar el nodo CfdiRelacionados";
				//$cfdi->CfdiRelacionados = null;
				
				//EMISOR
				$mensaje = "Error al llenar el nodo Emisor";
				$wcemisor = new Emisor();
				
				
				//DEBUG
				//$wcemisor->Rfc = $datosEncabezado[0]->RFC;
				$wcemisor->Rfc = "IIA040805DZ4";
				$wcemisor->Nombre = $datosEncabezado[0]->RazonSocial;
				//$wcemisor->RegimenFiscal = $datosEncabezado[0]->RegimenFiscal;
				$wcemisor->RegimenFiscal = "601";
				$cfdi->Emisor = $wcemisor;
				
				
				//RECEPTOR
				$mensaje = "Error al llenar el nodo Receptor";
				$wcreceptor = new Receptor();
				
				$wcreceptor->Rfc = $datosEncabezado[0]->RFCReceptor;
				$wcreceptor->Nombre = $datosEncabezado[0]->RSReceptor;
				if ($datosEncabezado[0]->Pais == "MEX"){
				} else {
					$wcreceptor->NumRegIdTrib = $datosEncabezado[0]->RegIdTrib;
					$wcreceptor->ResidenciaFiscal = $datosEncabezado[0]->Pais;
				}
				$wcreceptor->UsoCFDI = $datosEncabezado[0]->UsoCFDI;
				$cfdi->Receptor = $wcreceptor;
				
				//ADDENDA
				$mensaje = "Error al llenar el nodo Addenda";
				//$cfdi->Addenda = null;
				
				//CAMPOS PDF
				$mensaje = "Error al llenar el nodo CamposPDF";
				$infoPDF = new CamposPDF();
				$infoPDF->tipoComprobante = "FACTURA";
				$infoPDF->Comentarios = "ESTE COMPROBANTE NO TIENE COMENTARIOS ADICIONALES" ;
				
				$infoPDF->calleEmisor = $datosEncabezado[0]->DomEmisor;
				$infoPDF->noExteriorEmisor = $datosEncabezado[0]->NoExtEmisor;
				$infoPDF->noInteriorEmisor = "";
				$infoPDF->coloniaEmisor = $datosEncabezado[0]->ColEmisor;
				$infoPDF->codigoPostalEmisor = $datosEncabezado[0]->CPEmisor;
				$infoPDF->localidadEmisor = $datosEncabezado[0]->LocalidadEmisor;
				$infoPDF->municipioEmisor = $datosEncabezado[0]->MunicipioEmisor;
				$infoPDF->estadoEmisor = $datosEncabezado[0]->EstadoEmisor;
				$infoPDF->paisEmisor = $datosEncabezado[0]->PaisEmisor;
				
				$infoPDF->calleReceptor = $datosEncabezado[0]->DomReceptor;
				$infoPDF->noExteriorReceptor = $datosEncabezado[0]->NoExtReceptor;
				$infoPDF->noInteriorReceptor = "";
				$infoPDF->coloniaReceptor = $datosEncabezado[0]->ColReceptor;
				$infoPDF->codigoPostalReceptor = $datosEncabezado[0]->CPReceptor;
				$infoPDF->localidadReceptor = $datosEncabezado[0]->LocalidadReceptor;
				$infoPDF->municipioReceptor = $datosEncabezado[0]->MunicipioReceptor;
				$infoPDF->estadoReceptor = $datosEncabezado[0]->EstadoReceptor;
				$infoPDF->paisReceptor = $datosEncabezado[0]->PaisReceptor;

				//CONCEPTOS
				//$ac[] = [];
				for ($x = 0; $x < count($datosDetalle); $x++){
					$mensaje = "Error al llenar la información general del nodo del concepto " . strval($x + 1);
					
					$wc = new Concepto();
					$wc->ClaveProdServ = $datosDetalle[$x]->ProdoServ;
					$wc->Cantidad = $datosDetalle[$x]->Cantidad;
					$wc->ClaveUnidad = $datosDetalle[$x]->ClaveUnidad;
					$wc->Unidad = $datosDetalle[$x]->Unidad;
					//$wc->Descripcion = $datosDetalle[$x]->desc_viaje . "\r\n" . $datosDetalle[$x]->descservicio . "\r\n" . $datosDetalle[$x]->Hora_Inicio . "\r\n " . $datosDetalle[$x]->Hora_Termino . "\r\n" . $datosDetalle[$x]->SERVICIO;
					
					//$wc->Descripcion = $datosDetalle[$x]->NomServicio . "\r\n" . $datosDetalle[$x]-> desc_buque . "\r\n" . $datosDetalle[$x]->desc_viaje . "\r\n" . $datosDetalle[$x]->descservicio . "\r\n" . $datosDetalle[$x]->Hora_Inicio. "\r\n" . $datosDetalle[$x]->Hora_Termino . "\r\n" . $datosDetalle[$x]->TRB . "\r\n" . $datosDetalle[$x]->SERVICIO;
					$wc->Descripcion = str_replace("\r\n\r\n\r\n\r\n\r\n\r\n\r\n"," ",$datosDetalle[$x]->NomServicio . "\r\n" . $datosDetalle[$x]-> desc_buque . "\r\n" . $datosDetalle[$x]->desc_viaje . "\r\n" . $datosDetalle[$x]->descservicio . "\r\n" . $datosDetalle[$x]->Hora_Inicio. "\r\n" . $datosDetalle[$x]->Hora_Termino . "\r\n" . $datosDetalle[$x]->TRB . "\r\n" . $datosDetalle[$x]->SERVICIO);
					
					$wc->ValorUnitario = $datosDetalle[$x]->ValorUnitario;
					$wc->Importe = $datosDetalle[$x]->Importe;
					
					if (floatval($datosDetalle[$x]->Descuento) > 0){
						$wc->Descuento = $datosDetalle[$x]->Descuento;
					}
					//$wc->CuentaPredial = null;
					
					
					//IMPUESTOS DEL CONCEPTO
					//$arregloTrasConc[] = new TrasladoConcepto();
					//$arregloRetConc[] = new RetencionConcepto();
					$arregloTrasConc = array();
					$wtrasConc = new TrasladoConcepto();
					$wretConc = new RetencionConcepto();
					$wimpConc = new ImpuestosConcepto();
					
					$mensaje = "Error al llenar los traslados del concepto " . strval($x +1);
					if ($datosDetalle[$x]->Factor == "Exento"){
						$tieneExentos = 1;
					} else {
						$wtrasConc->Importe = number_format(floatval($datosDetalle[$x]->ImporteTraslado) , 2);
						$wtrasConc->TasaOCuota = number_format(floatval($datosDetalle[$x]->TasaoCuota) , 6);
					}
					$wtrasConc->Base = $datosDetalle[$x]->BaseTraslado;
					$wtrasConc->Impuesto = $datosDetalle[$x]->ClaveImpuesto;
					$wtrasConc->TipoFactor = $datosDetalle[$x]->Factor;
					$arregloTrasConc[] = $wtrasConc;
					$wimpConc->Traslados = $arregloTrasConc;
					
					$mensaje = "Error al llenar las retenciones del concepto " . strval($x +1);
					//$wretConc = null;
					//$arregloRetConc[] = $wretConc;
					//$wimpConc->Retenciones = $arregloRetConc;
					
					$wc->Impuestos = $wimpConc;
					//$wc->InformacionAduanera = null;
					//$wc->ComplementoConcepto = null;
					$ac[] = $wc;
				}
				$cfdi->Conceptos = $ac;
			
				$mensaje = "Error al llenar los impuestos generales del comprobante";
				$wim = new Impuestos();
				//arreglo_tot_tras [] = new Traslado();
				//arreglo_tot_ret [] = new Retencion();
				$tot_tras = new Traslado();
				$tot_ret = new Retencion();
				$totalImpRet = 1;
				$totalImpTras = 1;
				
				$wim->TotalImpuestosTrasladados = $datosEncabezado[0]->TotalImpuestoTrasladado;
				//$wim->TotalImpuestosRetenidos = $datosEncabezado[0]->TotalImpuestoRetenido;
				
				if (floatval($datosEncabezado[0]->TotalImpuestoTrasladado) > 0){
						$tot_tras->Importe = $datosEncabezado[0]->TotalImpuestoTrasladado;
						$tot_tras->Impuesto = $datosEncabezado[0]->ClaveImpuestoGral;
						$tot_tras->TasaOCuota = $datosEncabezado[0]->TasaoCuotaGral;
						$tot_tras->TipoFactor = $datosEncabezado[0]->FactorGral;
				}
				$arreglo_tot_tras [] = $tot_tras;
				$wim->Traslados = $arreglo_tot_tras;
				
				//if (floatval($datosEncabezado[0]->TotalImpuestoTrasladado) > 0){
				//		if (floatval(datosDetalle[$x]->TotalImpuestoRetenido) > 0){
				//			$tot_ret->Impuesto = "";
				//			$tot_ret->Importe = "";
				// 		}	
				// 		$arreglo_tot_ret [] = $tot_ret;
				// 		$wim->Retenciones = $arreglo_tot_ret;	
				//}
				
				
				$cfdi->Impuestos = $wim;
				
				$JSONrequest->Comprobante = $cfdi;
				$JSONrequest->CamposPDF = $infoPDF;
				
				//*********[CORREOS]********************				
				$arrayCorreos = array();				
				array_push($arrayCorreos, $datosEncabezado[0]->Correo);								
				$listaCorreos = new Correos();
				$listaCorreos->Correos = $arrayCorreos;				
				$JSONrequest->EnviarCFDI = $listaCorreos;
				
				$mensaje = "Error al generar el Base64 de la petición armada";
				
				$logoEmpresa = base64_encode(file_get_contents($datosPAC[0]->logo));
				$JSONrequest->logo = $logoEmpresa;
				$jsonresult = json_encode($JSONrequest);
				$cleanJSONtmp = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $jsonresult);
				
				$cleanJSONobj = json_decode($cleanJSONtmp); //Se convierte a objeto ya sin nulos
				$cleanJSON = json_encode($cleanJSONobj, JSON_PRETTY_PRINT);	//Otra vez se manda a json ya sin nulos
				
				$mensaje = "Error al guardar el JSON de la petición en filesystem";
				file_put_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json", $cleanJSON);
				
				//$jsonB64 = base64_encode( file_get_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json") );
				//return $jsonB64;
				
				//ENVIO A PAC
				$mensaje = "Error al obtener los sellos del cliente en formato PEM del filesystem";
				$objConexion = new Conexion($datosPAC[0]->url_ws);
				
				$jsonB64 = base64_encode( file_get_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json") );
				$keyPEM = file_get_contents($datosPAC[0]->pem_key);
				$cerPEM = file_get_contents($datosPAC[0]->pem_cer);
				$plantilla = 'sisproc1';
				
				$mensaje = "Error al consumir servicio web del PAC";
				$resultadoTimbrado = json_decode($objConexion->operacion_timbrarJSON2($datosPAC[0]->token, $jsonB64, $keyPEM, $cerPEM, $plantilla, $logoEmpresa));
				
				$usrRespuesta = new RespuestaTimbrado();
				//CONSUMO DE RESPUESTA
				if (intval($resultadoTimbrado->codigo) == 200 || intval($resultadoTimbrado->codigo) == 307){
					//Timbrado correcto
					
					//1 - Guardado en Filesystem
					$mensaje = "Error al guardar el PDF y XML del timbrado en el filesystem";
					$archivosCFDI = json_decode($resultadoTimbrado->datos);
					$PDF_response = str_replace("\/","/",str_replace("\n","", $archivosCFDI->PDF));
					$XML_response = str_replace('\"','"',str_replace("\n","", $archivosCFDI->XML));
					file_put_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml", $XML_response);
					$ifp = fopen("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf", "wb" ); 
					fwrite( $ifp, base64_decode( $PDF_response) ); 
					fclose( $ifp );
					//file_put_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf", file_get_contents($PDF_response)); //TODO: Crear estructura segun fecha de timbrado
					
					
					//Deserializar XML para sacar información del timbrado
					$mensaje = "Error al Extraer datos del XML del comprobante timbrado";
					try {
						$XML_response = str_replace("tfd:", "", str_replace("cfdi:","", file_get_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml")));

						$Comprobante = new SimpleXMLElement($XML_response);
						
						$pArrFecha = explode("T", $Comprobante["Fecha"]);
						$pArrYMD = explode("-", $pArrFecha[0]);
	
						$pFechaEmision = $pArrYMD[2] . "/" . $pArrYMD[1] . "/" . $pArrYMD[0] . " " . $pArrFecha[1];
						$pFolio = $Comprobante["Folio"];
						$pSerie = $Comprobante["Serie"];
						$pSubtotal = $Comprobante["SubTotal"];
						$pTotal = $Comprobante["Total"];
						$pDescuento = $Comprobante["Descuento"];
						if ($pDescuento === null){
							$pDescuento = "0.00";	//No siempre aprece, por eso se verifica que no quede vacío
						}
						$pURL_PDF = "boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf";
						$pURL_XML = "boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml";
						//$idEmpresa
						//$tipoSistema
						//$idFactura
						$pIdServicio = "999";
						$pTipoFactura = $pSerie;
						$pIVA = $Comprobante->Impuestos["TotalImpuestosTrasladados"];
						if ($pIVA === null){
							$pIVA = "0.00"; 		//No siempre aparece, por eso se verifica que no quede vacío
						}
						
						$pRFC_Emisor = $Comprobante->Emisor["Rfc"];
						$pRazon_Social_Emisor = $Comprobante->Emisor["Nombre"];
						$pRFC_Receptor = $Comprobante->Receptor["Rfc"];
						$pRazon_Social_Receptor = $Comprobante->Receptor["Nombre"];
						$pUUID = $Comprobante->Complemento->TimbreFiscalDigital["UUID"];
					} catch (Exception $ex){
						//Error de timbrado
						$usrRespuesta->mensaje = $resultadoTimbrado->mensaje;
						$usrRespuesta->estado = "0";
						return $usrRespuesta;
					}
									
					//Llamado a proc BD
					$mensaje = "Error al guardar datos del timbrado en Base de Datos";
					try {
						$stmt3 = $conexion->prepare("call setivera_facturacion.emision_facturas_insertar('$idEmpresa','$tipoSistema','$idFactura','$pTipoFactura' ,'$pFolio' ,'$pSerie' ,'$pUUID' ,'$pRFC_Emisor' ,'$pRazon_Social_Emisor' ,'$pRFC_Receptor' ,'$pRazon_Social_Receptor' ,'$pFechaEmision' ,'$pSubtotal' ,'$pDescuento' ,'$pIVA' ,'$pTotal' ,'$pURL_PDF' ,'$pURL_XML')");
						$stmt3->execute();	
							
						$numRegistrosGuardado = $stmt3->rowCount();
						if($numRegistrosGuardado > 0) {
							while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) {
								$pTransaccionGuardado = $row["Transaccion"];
								$pMensajeGuardado = $row["Mensaje"];
							};
							$stmt3->closeCursor();
							if (intval($pTransaccionGuardado) == 1){
								//Proceso terminado
								//Respuesta al usuario
								$usrRespuesta->estado = $pTransaccionGuardado;
								$usrRespuesta->mensaje = "Timbrado correcto de comprobante " . $pSerie . "_" . $pFolio . " con UUID " . $pUUID . ". ";
								return $usrRespuesta;
							} else {
								//Error al guardar en BD
								//Respuesta al usuario
								$usrRespuesta->estado = $pTransaccionGuardado;
								$usrRespuesta->mensaje = "Error al almacenar en BD resultado del timbrado: " . $pMensajeGuardado;
								return $usrRespuesta;
							}
						} else {
							$usrRespuesta->mensaje = $mensaje;
							$usrRespuesta->estado = "0";
							return $usrRespuesta;
						}
					} catch (Exception $ex){
						$usrRespuesta->mensaje = $mensaje;
							$usrRespuesta->estado = "0";
							return $usrRespuesta;
					}
					
				} else {
					//Error de timbrado
					$usrRespuesta->mensaje = $resultadoTimbrado->mensaje;
					$usrRespuesta->estado = "0";
					return $usrRespuesta;
				}
				
			} catch (Exception $e){
				return "Error en el armado de peticion de timbrado seccion DATOS GENERALES: " . $mensaje . "\r\n" . $e;
			}
			
		} catch (Exception $e){
			return "Error en obtención de datos de BD para petición de timbrado: " . $e;
		}
	}
	
	
	
	/////////////////////////////////////////////////////////////////////////////////
	////			2		TIMBRADO NOTAS DE CREDITO							/////
	/////////////////////////////////////////////////////////////////////////////////
	function timbrado_nota($idEmpresa, $tipoSistema, $idFactura, $conexion){
		try {
			//Obtener datos de encabezado
			$stmt = $conexion->prepare("call setivera_facturacion.NotasCredito_ObtenerEncabezado('$idEmpresa','$tipoSistema','$idFactura')");
			$stmt->execute();	
				
			$numRegistrosEncabezado = $stmt->rowCount();
			$datosEncabezado = [];
			
			if($numRegistrosEncabezado > 0) {
				while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_encabezado_factura();
					$respuesta->Serie = $row["Serie"];
					$respuesta->Folio = $row["Folio"];
					$respuesta->Fecha = $row["Fecha"];
					$respuesta->FormaPago = $row["FormaPago"];
					$respuesta->Subtotal = $row["Subtotal"];
					$respuesta->Descuento = "0.00";
					$respuesta->Moneda = $row["moneda"];
					$respuesta->TipoCambio = $row["tipocambio"];
					$respuesta->Total = $row["Total"];
					$respuesta->TipoComprobante = $row["TipoComprobante"];
					$respuesta->MetodoPago = $row["MetodoPago"];
					$respuesta->LugarExpedicion = $row["LugarExpedicion"];
					$respuesta->RFC = $row["RFC"];
					$respuesta->RazonSocial = $row["RazonSocial"];
					$respuesta->RFCReceptor = $row["RFCReceptor"];
					$respuesta->RSReceptor = $row["RSReceptor"];
					$respuesta->Pais = $row["pais"];
					$respuesta->RegIdTrib = $row["RegIdTrib"];
					$respuesta->UsoCFDI = $row["UsoCFDI"];
					$respuesta->DomEmisor = $row["DomEmisor"];
					$respuesta->DomReceptor = $row["DomReceptor"];
					$respuesta->TotalImpuestoTrasladado = $row["TotalImpuestoTrasladado"];
					$respuesta->ClaveImpuestoGral = $row["ClaveImpuestoGral"];
					$respuesta->FactorGral = $row["FactorGral"];
					$respuesta->TasaoCuotaGral = $row["TasaoCuotaGral"];
					$respuesta->ImporteIVAGral = $row["ImporteIVAGral"];
					
					$respuesta->NoExtEmisor = $row["NoExtEmisor"];
					$respuesta->ColEmisor = $row["ColEmisor"];
					$respuesta->CPEmisor = $row["CPEmisor"];
					$respuesta->LocalidadEmisor = $row["LocalidadEmisor"];
					$respuesta->MunicipioEmisor = $row["MunicipioEmisor"];
					$respuesta->EstadoEmisor = $row["EstadoEmisor"];
					$respuesta->PaisEmisor = $row["PaisEmisor"];
					$respuesta->NoExtReceptor = $row["NoExtReceptor"];
					$respuesta->ColReceptor = $row["ColReceptor"];
					$respuesta->CPReceptor = $row["CPReceptor"];
					$respuesta->LocalidadReceptor = $row["LocalidadReceptor"];
					$respuesta->MunicipioReceptor = $row["MunicipioReceptor"];
					$respuesta->EstadoReceptor = $row["EstadoReceptor"];
					$respuesta->PaisReceptor = $row["PaisReceptor"];
					$respuesta->Correo = $row["CuentaCorreo"];
					
					$datosEncabezado[] = $respuesta;
					//return json_encode($datosEncabezado);
				};
				$stmt->closeCursor();
			} else {
				return "No se pudieron obtener los datos del encabezado del CFDI";
			}
			
			//Obtener detalle de conceptos de factura 
			$stmt2 = $conexion->prepare("call setivera_facturacion.NotasCredito_ObtenerDetalleConceptos('$idEmpresa','$tipoSistema','$idFactura')");
			$stmt2->execute();	
				
			$numRegistrosDetalle = $stmt2->rowCount();
			$datosDetalle = [];
			
			if($numRegistrosDetalle > 0) {
				//while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
				while($row = $stmt2->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_detalle_factura();
					$respuesta->ProdoServ = $row["ProdoServ"];
					$respuesta->ClaveUnidad = $row["ClaveUnidad"];
					$respuesta->Unidad = $row["Unidad"];
					
					$respuesta->NomServicio = $row["NomServicio"];
					$respuesta->desc_buque = $row["desc_buque"];
					
					$respuesta->desc_viaje = $row["desc_viaje"];
					$respuesta->descservicio = $row["descservicio"];
					$respuesta->Hora_Inicio = $row["Hora_Inicio"];
					$respuesta->Hora_Termino = $row["Hora_Termino"];
					$respuesta->TRB = $row["TRB"];
					$respuesta->Eslora = $row["Eslora"];
					$respuesta->SERVICIO = $row["SERVICIO"];
					$respuesta->Cantidad = $row["Cantidad"];
					$respuesta->ValorUnitario = $row["ValorUnitario"];
					$respuesta->Importe = $row["Importe"];
					$respuesta->Descuento = $row["Descuento"];
					$respuesta->BaseTraslado = $row["BaseTraslado"];
					$respuesta->ClaveImpuesto = $row["ClaveImpuesto"];
					$respuesta->Factor = $row["Factor"];
					$respuesta->TasaoCuota = $row["TasaoCuota"];
					$respuesta->ImporteTraslado = $row["ImporteTraslado"];
					$datosDetalle[] = $respuesta;
					
				};
				$stmt2->closeCursor();
				//return json_encode($datosDetalle);
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			
			//Obtención de parametros de timbrado PAC
			//Obtener detalle de conceptos de factura 
			$stmt3 = $conexion->prepare("call setivera_facturacion.obtener_parametros_pac()");
			$stmt3->execute();	
				
			$numRegistrosDetalle = $stmt2->rowCount();
			$datosPAC = [];
			
			if($numRegistrosDetalle > 0) {
				//while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
				while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_configuracion_pac();
					$respuesta->token = $row["token"];
					$respuesta->pem_cer = $row["pem_cer"];
					$respuesta->pem_key = $row["pem_key"];
					$respuesta->logo = $row["logo"];
					$respuesta->url_ws = $row["url_ws"];
					$datosPAC[] = $respuesta;
				};
				$stmt3->closeCursor();
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			//Obtener relaciones del comprobante
			$smt4 = $conexion->prepare("call setivera_facturacion.NotasCredito_ObtenerRelacion('$idEmpresa','$tipoSistema','$idFactura')");
			$smt4->execute();	
				
			$numRegistrosRelacion = $stmt2->rowCount();
			$datosRelacion = [];
			
			if($numRegistrosRelacion > 0) {
				//while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
				while($row = $smt4->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_relacion_cfdi();
					$respuesta->IdUUIDFactura = $row["IdUUIDFactura"];
					$respuesta->DoctoRelacion = $row["DoctoRelacion"];
					$respuesta->folioCFDI = $row["folioCFDI"];
					$datosRelacion[] = $respuesta;
				};
				$smt4->closeCursor();
				//return json_encode($datosRelacion);
			} else {
				return "No se pudieron obtener los datos de las relaciones del CFDI";
			}
			
			
			
			/////////////////////////////////////////////
			//////////////  ARMADO DEL JSON /////////////
			/////////////////////////////////////////////
			
			//Variables Auxiliares
			$mensaje = "";
			$temp = 0;
			$permitirTimbrado = false;
			$tieneExentos = 0;
			$NoCertificado = "30001000000400002447";
			
			$JSONrequest = new Peticion;
			$cfdi = new CFDI_JSON;
			$datosCUSTOMDATA = new Addenda;
			
			try {
				//DATOS GENERALES
				$mensaje = "Error al llenar el encabezado (datos generales del nodo comprobante)";
				//$cfdi->NoCertificado = $datosEncabezado[0]->NoCertificado;
				$cfdi->NoCertificado = $NoCertificado;
				$cfdi->Serie = $datosEncabezado[0]->Serie;
				$cfdi->Folio = $datosEncabezado[0]->Folio;
				$cfdi->SubTotal = $datosEncabezado[0]->Subtotal;
				$cfdi->Moneda = $datosEncabezado[0]->Moneda;
				$cfdi->CondicionesDePago = "NA";
				$cfdi->TipoCambio = $datosEncabezado[0]->TipoCambio;
				$cfdi->Total = $datosEncabezado[0]->Total;
				$cfdi->TipoDeComprobante = $datosEncabezado[0]->TipoComprobante;
				$cfdi->MetodoPago = $datosEncabezado[0]->MetodoPago;
				$cfdi->FormaPago = $datosEncabezado[0]->FormaPago;
				if (floatval($datosEncabezado[0]->Descuento) >0){
					$cfdi->Descuento = $datosEncabezado[0]->Descuento;
				}
				$cfdi->LugarExpedicion = $datosEncabezado[0]->LugarExpedicion;
				//$cfdi->Confirmacion = null;
				$cfdi->LugarExpedicion = $datosEncabezado[0]->LugarExpedicion;
				
				$mensaje = "Error al parsear la fecha al formato requerido por el PAC --> YYYY-MM-DDTHH:MM:SS";
				$comp = explode(" ", $datosEncabezado[0]->Fecha);
				$fechacomp = explode("/", $comp[0]);
				$horacomp = explode(":", $comp[1]);
				$cfdi->Fecha = $fechacomp[2] . "-" . $fechacomp[1] . "-" . $fechacomp[0] . "T" . $comp[1];
				
				//CFDI RELACIONADOS
				$mensaje = "Error al llenar el nodo CfdiRelacionados";
				
				$relacionados = new CfdiRelacionados();
				$relacionados->TipoRelacion = $datosRelacion[0]->DoctoRelacion;
				
				for ($r = 0; $r < count($datosRelacion); $r++){
					$arrRelacionados[] = $datosRelacion[$r]->IdUUIDFactura;
					
					//PRUEBA ETIQUETAS EN NOTA DE CREDITO
					$etiquetaRelacionFolio = new EtiquetaAddenda();
					
					$vfrelx = "";
					if($datosRelacion[$r]->folioCFDI == null){
						$vfrelx = "";
					} else {
						$vfrelx = strval($datosRelacion[$r]->folioCFDI);
					}
					$etiquetaRelacionFolio->nombre = "Factura Rel: ";
					$etiquetaRelacionFolio->valor = $vfrelx;
					$arregloEtiquetas[] = $etiquetaRelacionFolio;
					
					$etiquetaRelacionUUID = new EtiquetaAddenda();
					$etiquetaRelacionUUID->nombre = "UUID Rel: ";
					$etiquetaRelacionUUID->valor = $datosRelacion[$r]->IdUUIDFactura;
					$arregloEtiquetas[] = $etiquetaRelacionUUID;
				}
				$relacionados->CfdiRelacionado = $arrRelacionados;
				$cfdi->CfdiRelacionados = $relacionados;
				
				//EMISOR
				$mensaje = "Error al llenar el nodo Emisor";
				$wcemisor = new Emisor();
				
				
				//DEBUG
				//$wcemisor->Rfc = $datosEncabezado[0]->RFC;
				$wcemisor->Rfc = "IIA040805DZ4";
				$wcemisor->Nombre = $datosEncabezado[0]->RazonSocial;
				//$wcemisor->RegimenFiscal = $datosEncabezado[0]->RegimenFiscal;
				$wcemisor->RegimenFiscal = "601";
				$cfdi->Emisor = $wcemisor;
				
				
				//RECEPTOR
				$mensaje = "Error al llenar el nodo Receptor";
				$wcreceptor = new Receptor();
				
				$wcreceptor->Rfc = $datosEncabezado[0]->RFCReceptor;
				$wcreceptor->Nombre = $datosEncabezado[0]->RSReceptor;
				if ($datosEncabezado[0]->Pais == "MEX"){
				} else {
					$wcreceptor->NumRegIdTrib = $datosEncabezado[0]->RegIdTrib;
					$wcreceptor->ResidenciaFiscal = $datosEncabezado[0]->Pais;
				}
				$wcreceptor->UsoCFDI = $datosEncabezado[0]->UsoCFDI;
				$cfdi->Receptor = $wcreceptor;
				
				//ADDENDA
				$mensaje = "Error al llenar el nodo Addenda";
				//$cfdi->Addenda = null;
				
				//CAMPOS PDF
				$mensaje = "Error al llenar el nodo CamposPDF";
				$infoPDF = new CamposPDF();
				$infoPDF->tipoComprobante = "NOTA DE CREDITO";
				$infoPDF->Comentarios = "ESTE COMPROBANTE NO TIENE COMENTARIOS ADICIONALES" ;
				
				$infoPDF->calleEmisor = $datosEncabezado[0]->DomEmisor;
				$infoPDF->noExteriorEmisor = $datosEncabezado[0]->NoExtEmisor;
				$infoPDF->noInteriorEmisor = "";
				$infoPDF->coloniaEmisor = $datosEncabezado[0]->ColEmisor;
				$infoPDF->codigoPostalEmisor = $datosEncabezado[0]->CPEmisor;
				$infoPDF->localidadEmisor = $datosEncabezado[0]->LocalidadEmisor;
				$infoPDF->municipioEmisor = $datosEncabezado[0]->MunicipioEmisor;
				$infoPDF->estadoEmisor = $datosEncabezado[0]->EstadoEmisor;
				$infoPDF->paisEmisor = $datosEncabezado[0]->PaisEmisor;
				
				$infoPDF->calleReceptor = $datosEncabezado[0]->DomReceptor;
				$infoPDF->noExteriorReceptor = $datosEncabezado[0]->NoExtReceptor;
				$infoPDF->noInteriorReceptor = "";
				$infoPDF->coloniaReceptor = $datosEncabezado[0]->ColReceptor;
				$infoPDF->codigoPostalReceptor = $datosEncabezado[0]->CPReceptor;
				$infoPDF->localidadReceptor = $datosEncabezado[0]->LocalidadReceptor;
				$infoPDF->municipioReceptor = $datosEncabezado[0]->MunicipioReceptor;
				$infoPDF->estadoReceptor = $datosEncabezado[0]->EstadoReceptor;
				$infoPDF->paisReceptor = $datosEncabezado[0]->PaisReceptor;
				
				/*
				$respuesta->NoExtReceptor = $row["NoExtReceptor"];
				$respuesta->ColReceptor = $row["ColReceptor"];
				$respuesta->CPReceptor = $row["CPReceptor"];
				$respuesta->LocalidadReceptor = $row["LocalidadReceptor"];
				$respuesta->MunicipioReceptor = $row["MunicipioReceptor"];
				$respuesta->EstadoReceptor = $row["EstadoReceptor"];
				$respuesta->PaisReceptor = $row["PaisReceptor"];
				*/
				
				$infoPDF->etiquetas = $arregloEtiquetas;
				
				//CONCEPTOS
				//$ac[] = [];
				for ($x = 0; $x < count($datosDetalle); $x++){
					$mensaje = "Error al llenar la información general del nodo del concepto " . strval($x + 1);
					
					$wc = new Concepto();
					$wc->ClaveProdServ = $datosDetalle[$x]->ProdoServ;
					$wc->Cantidad = $datosDetalle[$x]->Cantidad;
					$wc->ClaveUnidad = $datosDetalle[$x]->ClaveUnidad;
					$wc->Unidad = $datosDetalle[$x]->Unidad;
					
					//$wc->Descripcion = $datosDetalle[$x]->desc_viaje . "\r\n" . $datosDetalle[$x]->descservicio . "\r\n" . $datosDetalle[$x]->Hora_Inicio . "\r\n " . $datosDetalle[$x]->Hora_Termino . "\r\n" . $datosDetalle[$x]->SERVICIO;
					
					//$wc->Descripcion = $datosDetalle[$x]->NomServicio . "\r\n" . $datosDetalle[$x]-> desc_buque . "\r\n" . $datosDetalle[$x]->desc_viaje . "\r\n" . $datosDetalle[$x]->descservicio . "\r\n" . $datosDetalle[$x]->Hora_Inicio. "\r\n" . $datosDetalle[$x]->Hora_Termino . "\r\n" . $datosDetalle[$x]->TRB . "\r\n" . $datosDetalle[$x]->SERVICIO;
					$wc->Descripcion = str_replace("\r\n\r\n\r\n\r\n\r\n\r\n\r\n"," ",$datosDetalle[$x]->NomServicio . "\r\n" . $datosDetalle[$x]-> desc_buque . "\r\n" . $datosDetalle[$x]->desc_viaje . "\r\n" . $datosDetalle[$x]->descservicio . "\r\n" . $datosDetalle[$x]->Hora_Inicio. "\r\n" . $datosDetalle[$x]->Hora_Termino . "\r\n" . $datosDetalle[$x]->TRB . "\r\n" . $datosDetalle[$x]->SERVICIO);
					
					$wc->ValorUnitario = $datosDetalle[$x]->ValorUnitario;
					$wc->Importe = $datosDetalle[$x]->Importe;
					
					if (floatval($datosDetalle[$x]->Descuento) > 0){
						$wc->Descuento = $datosDetalle[$x]->Descuento;
					}
					//$wc->CuentaPredial = null;
					
					
					//IMPUESTOS DEL CONCEPTO
					//$arregloTrasConc[] = new TrasladoConcepto();
					//$arregloRetConc[] = new RetencionConcepto();
					$arregloTrasConc = array();
					$wtrasConc = new TrasladoConcepto();
					$wretConc = new RetencionConcepto();
					$wimpConc = new ImpuestosConcepto();
					
					$mensaje = "Error al llenar los traslados del concepto " . strval($x +1);
					if ($datosDetalle[$x]->Factor == "Exento"){
						$tieneExentos = 1;
					} else {
							$wtrasConc->Importe = number_format(floatval($datosDetalle[$x]->ImporteTraslado) , 2);
							$wtrasConc->TasaOCuota = number_format(floatval($datosDetalle[$x]->TasaoCuota) , 6);
					}
					$wtrasConc->Base = $datosDetalle[$x]->BaseTraslado;
					$wtrasConc->Impuesto = $datosDetalle[$x]->ClaveImpuesto;
					$wtrasConc->TipoFactor = $datosDetalle[$x]->Factor;
					$arregloTrasConc[] = $wtrasConc;
					$wimpConc->Traslados = $arregloTrasConc;
					
					$mensaje = "Error al llenar las retenciones del concepto " . strval($x +1);
					//$wretConc = null;
					//$arregloRetConc[] = $wretConc;
					//$wimpConc->Retenciones = $arregloRetConc;
					
					$wc->Impuestos = $wimpConc;
					//$wc->InformacionAduanera = null;
					//$wc->ComplementoConcepto = null;
					$ac[] = $wc;
				}
				$cfdi->Conceptos = $ac;
			
				$mensaje = "Error al llenar los impuestos generales del comprobante";
				$wim = new Impuestos();
				//arreglo_tot_tras [] = new Traslado();
				//arreglo_tot_ret [] = new Retencion();
				$tot_tras = new Traslado();
				$tot_ret = new Retencion();
				$totalImpRet = 1;
				$totalImpTras = 1;
				
				$wim->TotalImpuestosTrasladados = $datosEncabezado[0]->TotalImpuestoTrasladado;
				//$wim->TotalImpuestosRetenidos = $datosEncabezado[0]->TotalImpuestoRetenido;
				
				if (floatval($datosEncabezado[0]->TotalImpuestoTrasladado) > 0){
						$tot_tras->Importe = $datosEncabezado[0]->TotalImpuestoTrasladado;
						$tot_tras->Impuesto = $datosEncabezado[0]->ClaveImpuestoGral;
						$tot_tras->TasaOCuota = $datosEncabezado[0]->TasaoCuotaGral;
						$tot_tras->TipoFactor = $datosEncabezado[0]->FactorGral;
				}
				$arreglo_tot_tras [] = $tot_tras;
				$wim->Traslados = $arreglo_tot_tras;
				
				//if (floatval($datosEncabezado[0]->TotalImpuestoTrasladado) > 0){
				//		if (floatval(datosDetalle[$x]->TotalImpuestoRetenido) > 0){
				//			$tot_ret->Impuesto = "";
				//			$tot_ret->Importe = "";
				// 		}	
				// 		$arreglo_tot_ret [] = $tot_ret;
				// 		$wim->Retenciones = $arreglo_tot_ret;	
				//}
				
				
				$cfdi->Impuestos = $wim;
				
				$JSONrequest->Comprobante = $cfdi;
				$JSONrequest->CamposPDF = $infoPDF;
				
				//*********[CORREOS]********************				
				$arrayCorreos = array();				
				array_push($arrayCorreos, $datosEncabezado[0]->Correo);								
				$listaCorreos = new Correos();
				$listaCorreos->Correos = $arrayCorreos;				
				$JSONrequest->EnviarCFDI = $listaCorreos;
				
				$mensaje = "Error al generar el Base64 de la petición armada";
				
				$logoEmpresa = base64_encode(file_get_contents($datosPAC[0]->logo));
				$JSONrequest->logo = $logoEmpresa;
				$jsonresult = json_encode($JSONrequest);
				$cleanJSONtmp = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $jsonresult);
				
				$cleanJSONobj = json_decode($cleanJSONtmp); //Se convierte a objeto ya sin nulos
				$cleanJSON = json_encode($cleanJSONobj, JSON_PRETTY_PRINT);	//Otra vez se manda a json ya sin nulos
				
				
				$mensaje = "Error al guardar el JSON de la petición en filesystem";
				file_put_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json", $cleanJSON);
				
				//ENVIO A PAC
				$mensaje = "Error al obtener los sellos del cliente en formato PEM del filesystem";
				$objConexion = new Conexion($datosPAC[0]->url_ws);
				
				$jsonB64 = base64_encode( file_get_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json") );
				$keyPEM = file_get_contents($datosPAC[0]->pem_key);
				$cerPEM = file_get_contents($datosPAC[0]->pem_cer);
				$plantilla = 'sisproc1';
				
				$mensaje = "Error al consumir servicio web del PAC";
				$resultadoTimbrado = json_decode($objConexion->operacion_timbrarJSON2($datosPAC[0]->token, $jsonB64, $keyPEM, $cerPEM, $plantilla, $logoEmpresa));
				
				$usrRespuesta = new RespuestaTimbrado();
				//CONSUMO DE RESPUESTA
				if (intval($resultadoTimbrado->codigo) == 200 || intval($resultadoTimbrado->codigo) == 307){
					//Timbrado correcto
					
					//1 - Guardado en Filesystem
					$mensaje = "Error al guardar el PDF y XML del timbrado en el filesystem";
					$archivosCFDI = json_decode($resultadoTimbrado->datos);
					$PDF_response = str_replace("\/","/",str_replace("\n","", $archivosCFDI->PDF));
					$XML_response = str_replace('\"','"',str_replace("\n","", $archivosCFDI->XML));
					file_put_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml", $XML_response);
					$ifp = fopen("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf", "wb" ); 
					fwrite( $ifp, base64_decode( $PDF_response) ); 
					fclose( $ifp );
					//file_put_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf", file_get_contents($PDF_response)); //TODO: Crear estructura segun fecha de timbrado
					
					
					//Deserializar XML para sacar información del timbrado
					$mensaje = "Error al Extraer datos del XML del comprobante timbrado";
					try {
						$XML_response = str_replace("tfd:", "", str_replace("cfdi:","", file_get_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml")));

						$Comprobante = new SimpleXMLElement($XML_response);
						
						$pArrFecha = explode("T", $Comprobante["Fecha"]);
						$pArrYMD = explode("-", $pArrFecha[0]);
	
						$pFechaEmision = $pArrYMD[2] . "/" . $pArrYMD[1] . "/" . $pArrYMD[0] . " " . $pArrFecha[1];
						$pFolio = $Comprobante["Folio"];
						$pSerie = $Comprobante["Serie"];
						$pSubtotal = $Comprobante["SubTotal"];
						$pTotal = $Comprobante["Total"];
						$pDescuento = $Comprobante["Descuento"];
						if ($pDescuento === null){
							$pDescuento = "0.00";	//No siempre aprece, por eso se verifica que no quede vacío
						}
						$pURL_PDF = "boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf";
						$pURL_XML = "boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml";
						//$idEmpresa
						//$tipoSistema
						//$idFactura
						
						$pTipoFactura = $pSerie;
						$pIVA = $Comprobante->Impuestos["TotalImpuestosTrasladados"];
						if ($pIVA === null){
							$pIVA = "0.00"; 		//No siempre aparece, por eso se verifica que no quede vacío
						}
						
						$pRFC_Emisor = $Comprobante->Emisor["Rfc"];
						$pRazon_Social_Emisor = $Comprobante->Emisor["Nombre"];
						$pRFC_Receptor = $Comprobante->Receptor["Rfc"];
						$pRazon_Social_Receptor = $Comprobante->Receptor["Nombre"];
						$pUUID = $Comprobante->Complemento->TimbreFiscalDigital["UUID"];
					} catch (Exception $ex){
						//Error de timbrado
						$usrRespuesta->mensaje = $resultadoTimbrado->mensaje;
						$usrRespuesta->estado = "0";
						return $usrRespuesta;
					}
									
					//Llamado a proc BD
					$mensaje = "Error al guardar datos del timbrado en Base de Datos";
					try {
						$stmt3 = $conexion->prepare("call setivera_facturacion.emision_facturas_insertar('$idEmpresa','$tipoSistema','$idFactura','$pTipoFactura' ,'$pFolio' ,'$pSerie' ,'$pUUID' ,'$pRFC_Emisor' ,'$pRazon_Social_Emisor' ,'$pRFC_Receptor' ,'$pRazon_Social_Receptor' ,'$pFechaEmision' ,'$pSubtotal' ,'$pDescuento' ,'$pIVA' ,'$pTotal' ,'$pURL_PDF' ,'$pURL_XML')");
						$stmt3->execute();	
							
						$numRegistrosGuardado = $stmt3->rowCount();
						if($numRegistrosGuardado > 0) {
							while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) {
								$pTransaccionGuardado = $row["Transaccion"];
								$pMensajeGuardado = $row["Mensaje"];
							};
							$stmt3->closeCursor();
							if (intval($pTransaccionGuardado) == 1){
								//Proceso terminado
								//Respuesta al usuario
								$usrRespuesta->estado = $pTransaccionGuardado;
								$usrRespuesta->mensaje = "Timbrado correcto de comprobante " . $pSerie . "_" . $pFolio . " con UUID " . $pUUID . ". ";
								return $usrRespuesta;
							} else {
								//Error al guardar en BD
								//Respuesta al usuario
								$usrRespuesta->estado = $pTransaccionGuardado;
								$usrRespuesta->mensaje = "Error al almacenar en BD resultado del timbrado: " . $pMensajeGuardado;
								return $usrRespuesta;
							}
						} else {
							$usrRespuesta->mensaje = $mensaje;
							$usrRespuesta->estado = "0";
							return $usrRespuesta;
						}
					} catch (Exception $ex){
						$usrRespuesta->mensaje = $mensaje;
						$usrRespuesta->estado = "0";
						return $usrRespuesta;
					}
					
				} else {
					//Error de timbrado
					$usrRespuesta->mensaje = $resultadoTimbrado->mensaje;
					$usrRespuesta->estado = "0";
					return $usrRespuesta;
				}
				
			} catch (Exception $e){
				return "Error en el armado de peticion de timbrado seccion DATOS GENERALES: " . $mensaje . "\r\n" . $e;
			}
			
		} catch (Exception $e){
			return "Error en obtención de datos de BD para petición de timbrado: " . $e;
		}
	}
	
	
	
	/////////////////////////////////////////////////////////////////////////////////
	////			3		TIMBRADO RECIBOS PAGO								/////
	/////////////////////////////////////////////////////////////////////////////////
	function timbrado_pago($idEmpresa, $tipoSistema, $idPago, $conexion){
		try {
			
			//Obtención de parametros de timbrado PAC
			$stmt3 = $conexion->prepare("call setivera_facturacion.obtener_parametros_pac()");
			$stmt3->execute();
				
			$numRegistrosDetalle = $stmt3->rowCount();
			$datosPAC = [];
			
			if($numRegistrosDetalle > 0) {
				while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_configuracion_pac();
					$respuesta->token = $row["token"];
					$respuesta->pem_cer = $row["pem_cer"];
					$respuesta->pem_key = $row["pem_key"];
					$respuesta->logo = $row["logo"];
					$respuesta->url_ws = $row["url_ws"];
					$datosPAC[] = $respuesta;
				};
				$stmt3->closeCursor();
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			//Obtener datos generales del comprobante y concepto unico en ceros
			$stmt = $conexion->prepare("call setivera_facturacion.Complementos_ObtenerEncabezado('$idEmpresa','$tipoSistema','$idPago')");
			$stmt->execute();	
				
			$numRegistrosEncabezado = $stmt->rowCount();
			$datosEncabezado = [];
			
			if($numRegistrosEncabezado > 0) {
				while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_pagos_encabezado();
					
					$respuesta->VERSION = $row["VERSION"];
					$respuesta->Serie = $row["Serie"];
					$respuesta->Folio = $row["Folio"];
					$respuesta->Fecha_Timbrado = $row["Fecha_Timbrado"];
					$respuesta->Subtotal = $row["Subtotal"];
					$respuesta->Moneda = $row["Moneda"];
					$respuesta->Total = $row["Total"];
					$respuesta->TipoComprobante = $row["TipoComprobante"];
					$respuesta->LugarExpedicion = $row["LugarExpedicion"];
					$respuesta->RFCEmisor = $row["RFCEmisor"];
					$respuesta->RFCReceptor = $row["RFCReceptor"];
					$respuesta->NombreEmisor = $row["NombreEmisor"];
					$respuesta->RegFiscal = $row["RegFiscal"];
					$respuesta->RFCReceptor = $row["RFCReceptor"];
					$respuesta->NomReceptor = $row["NomReceptor"];
					$respuesta->pais = $row["pais"];
					$respuesta->RegIdTrib = $row["RegIdTrib"];
					$respuesta->UsoCFDI = $row["UsoCFDI"];
					$respuesta->DomEmisor = $row["DomEmisor"];
					$respuesta->NoExtEmisor = $row["NoExtEmisor"];
					$respuesta->ColEmisor = $row["ColEmisor"];
					$respuesta->CPEmisor = $row["CPEmisor"];
					$respuesta->LocalidadEmisor = $row["LocalidadEmisor"];
					$respuesta->MunicipioEmisor = $row["MunicipioEmisor"];
					$respuesta->EstadoEmisor = $row["EstadoEmisor"];
					$respuesta->PaisEmisor = $row["PaisEmisor"];
					$respuesta->DomReceptor = $row["DomReceptor"];
					$respuesta->NoExtReceptor = $row["NoExtReceptor"];
					$respuesta->ColReceptor = $row["ColReceptor"];
					$respuesta->CPReceptor = $row["CPReceptor"];
					$respuesta->LocalidadReceptor = $row["LocalidadReceptor"];
					$respuesta->MunicipioReceptor = $row["MunicipioReceptor"];
					$respuesta->EstadoReceptor = $row["EstadoReceptor"];
					$respuesta->PaisReceptor = $row["PaisReceptor"];
					$respuesta->CveProdoServ = $row["CveProdoServ"];
					$respuesta->Cantidad = $row["Cantidad"];
					$respuesta->ClaveUnidad = $row["ClaveUnidad"];
					$respuesta->Descripcion = $row["Descripcion"];
					$respuesta->ValorUnitario = $row["ValorUnitario"];
					$respuesta->Importe = $row["Importe"];
					$respuesta->Correo = $row["CuentaCorreo"];
					
					$datosEncabezado[] = $respuesta;
					
				};
				//return json_encode($datosEncabezado);
				$stmt->closeCursor();
			} else {
				return "No se pudieron obtener los datos del encabezado del CFDI";
			}
			
			//Datos generales del complemento para recepción de pagos 
			$smt5 = $conexion->prepare("call setivera_facturacion.Complementos_ObtenerDatosPago('$idEmpresa','$tipoSistema','$idPago')");
			$smt5->execute();	
				
			$numRegistrosRelacion = $smt5->rowCount();
			$datosPago = [];
			
			if($numRegistrosRelacion > 0) {
				while($row = $smt5->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_pagos_datospago();
					$respuesta->VERSION = $row["VERSION"];
					$respuesta->Fecha_Pago = $row["Fecha_Pago"];
					$respuesta->FormaPagoP = $row["FormaPagoP"];
					$respuesta->FormaPago = $row["FormaPago"];
					$respuesta->Moneda = $row["Moneda"];
					$respuesta->TipoCambio = $row["TipoCambio"];
					$respuesta->Monto = $row["Monto"];
					$respuesta->TipoCadPago = $row["TipoCadPago"];
					$respuesta->CertPago = $row["CertPago"];
					$respuesta->CadPago = $row["CadPago"];
					$respuesta->SelloPago = $row["SelloPago"];
					$respuesta->RFCEmisorCtaOrd = $row["RFCEmisorCtaOrd"];
					$respuesta->NomBancoOrdExt = $row["NomBancoOrdExt"];
					$respuesta->CtaOrdenante = $row["CtaOrdenante"];
					$respuesta->NumOperacion = $row["NumOperacion"];
					$respuesta->RFCEmisorCtaBen = $row["RFCEmisorCtaBen"];
					$respuesta->CtaBeneficiario = $row["CtaBeneficiario"];

					$datosPago[] = $respuesta;
				};
				$smt5->closeCursor();
				//return json_encode($datosPago);
			} else {
				return "No se pudieron obtener los datos de las relaciones del CFDI";
			}
			
			//Detalle de los pagos amparados por el comprobante (1 a muchos)
			$stmt2 = $conexion->prepare("call setivera_facturacion.Complementos_ObtenerDetallePago('$idEmpresa','$tipoSistema','$idPago')");
			$stmt2->execute();	
				
			$numRegistrosDetalle = $stmt2->rowCount();
			$datosDetalle = [];
			
			if($numRegistrosDetalle > 0) {
				while($row = $stmt2->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_pagos_detallepago();
					$respuesta->Iddocumento = $row["Iddocumento"];
					$respuesta->Serie = $row["Serie"];
					$respuesta->Folio = $row["Folio"];
					$respuesta->MetodoPago = $row["MetodoPago"];
					$respuesta->MonedaDR = $row["MonedaDR"];
					$respuesta->TipoCambioDR = $row["TipoCambioDR"];
					$respuesta->NumParcialidad = $row["NumParcialidad"];
					$respuesta->ImpSaldoAnt = $row["ImpSaldoAnt"];
					$respuesta->ImpPagado = $row["ImpPagado"];
					$respuesta->ImpSaldoInsoluto = $row["ImpSaldoInsoluto"];
					$datosDetalle[] = $respuesta;
				};
				$stmt2->closeCursor();
				//return json_encode($datosDetalle);
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			/*
			//CFDIs relacionados al comprobante a timbrar (SOLO SI ES SUSTITUCIÓN DE CFDI) - NO SE USA
			$smt4 = $conexion->prepare("call facturacion.Complementos_ObtenerRelacionados('$idEmpresa','$tipoSistema','$idPago')");
			$smt4->execute();	
				
			$numRegistrosRelacion = $smt4->rowCount();
			$datosRelacion = [];
			
			if($numRegistrosRelacion > 0) {
				//while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
				while($row = $smt4->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_relacion_cfdi();
					$respuesta->IdUUIDFactura = $row["UUID"];
					$respuesta->DoctoRelacion = $row["TipoRelacion"];
					$datosRelacion[] = $respuesta;
				};
				$smt4->closeCursor();
				return json_encode($datosRelacion);
			} else {
				return "No se pudieron obtener los datos de las relaciones del CFDI";
			}
			*/
			
			
			
			/////////////////////////////////////////////
			//////////////  ARMADO DEL JSON /////////////
			/////////////////////////////////////////////
			
			//Variables Auxiliares
			$mensaje = "";
			$temp = 0;
			$permitirTimbrado = false;
			$tieneExentos = 0;
			$NoCertificado = "30001000000400002447";
			
			$JSONrequest = new PeticionPagos();
			$datosCUSTOMDATA = new Addenda();
			
			try {
				$mensaje = "Error al llenar los datos generales del nodo Comprobante";
				//DATOS GENERALES
				$wcomprp = new CFDI_JSON_Pago();
				$wcomprp->Serie = $datosEncabezado[0]->Serie;
				$wcomprp->Folio = $datosEncabezado[0]->Folio; 
				
				$comp = explode(" ", $datosEncabezado[0]->Fecha_Timbrado);
				$fechacomp = explode("/", $comp[0]);
				$horacomp = explode(":", $comp[1]);
				$wcomprp->Fecha = $fechacomp[2] . "-" . $fechacomp[1] . "-" . $fechacomp[0] . "T" . $comp[1];
				$wcomprp->NoCertificado =  $NoCertificado;
				$wcomprp->SubTotal =  $datosEncabezado[0]->Subtotal;
				$wcomprp->Descuento = null;
				$wcomprp->Moneda =  $datosEncabezado[0]->Moneda;
				$wcomprp->Total =  $datosEncabezado[0]->Total;
				$wcomprp->TipoDeComprobante =  $datosEncabezado[0]->TipoComprobante;
				$wcomprp->LugarExpedicion =  $datosEncabezado[0]->LugarExpedicion;
				$wcomprp->Confirmacion = null;
				
				$mensaje = "Error al llenar los datos del emisor y receptor del pago";
				/*
				//EMISOR Y RECEPTOR
				$emisorPago = new Emisor();
				$emisorPago->Rfc = $datosEncabezado[0]->RFCEmisor;
				$emisorPago->Nombre = $datosEncabezado[0]->NombreEmisor;
				$emisorPago->RegimenFiscal = $datosEncabezado[0]->RegFiscal;
				$wcomprp->Emisor = $emisorPago;
				*/
				//DEBUG
				$emisorPago = new Emisor();
				$emisorPago->Rfc = "IIA040805DZ4";
				$emisorPago->Nombre = $datosEncabezado[0]->NombreEmisor;
				$emisorPago->RegimenFiscal = "601";
				$wcomprp->Emisor = $emisorPago;
				
				$receptorPago = new Receptor();
				$receptorPago->Rfc = $datosEncabezado[0]->RFCReceptor;
				$receptorPago->Nombre = $datosEncabezado[0]->NomReceptor;
				if ($datosEncabezado[0]->pais == "MEX"){
				} else {
					$receptorPago->NumRegIdTrib = $datosEncabezado[0]->RegIdTrib;
					$receptorPago->ResidenciaFiscal = $datosEncabezado[0]->pais;
				}
				$receptorPago->UsoCFDI = $datosEncabezado[0]->UsoCFDI;
				$wcomprp->Receptor = $receptorPago;
				
				$mensaje = "Error al agregar los CFDIs relacionados al pago";
				//CFDI RELACIONADOS (NO SE USA DE MOMENTO)
				//$cfdiRelacionadosPago = new CfdiRelacionados;
				$wcomprp->CfdiRelacionados = null;
				
				//CONCEPTO UNICO EN CEROS
				$mensaje = "Error al agregar el concepto unico en ceros al pago";
				$concepto = new ConceptoPagos();
				$concepto->ClaveProdServ = $datosEncabezado[0]->CveProdoServ;
				$concepto->Cantidad = $datosEncabezado[0]->Cantidad;
				$concepto->ClaveUnidad  = $datosEncabezado[0]->ClaveUnidad;
				$concepto->Descripcion = $datosEncabezado[0]->Descripcion;
				$concepto->ValorUnitario = $datosEncabezado[0]->ValorUnitario;
				$concepto->Importe = $datosEncabezado[0]->Importe;
				$concepto->Descuento = null;
				
				$listaConceptosPago[] = $concepto;
				$wcomprp->Conceptos = $listaConceptosPago;
				
				//COMPLEMENTO DE RECEPCIÓN DE PAGOS
				//Arreglo de pagos
				$cpagos = new ComplementoPagos();
				$detallePago = new DetallePago();
				
				$contenedorPagos = new ContenedorPago();
				$contenedorPagos->Version = $datosPago[0]->VERSION;
				
				$mensaje = "Error al llenar los datos generales del complemento de pagos";
				$comp2 = explode(" ", $datosPago[0]->Fecha_Pago);
				$fechacomp2 = explode("/", $comp2[0]);
				$detallePago->FechaPago = $fechacomp2[2] . "-" . $fechacomp2[1] . "-" . $fechacomp2[0] . "T" . $comp2[1];
				$detallePago->FormaDePagoP = $datosPago[0]->FormaPago; //Diferencia entre este y FormaPagoP?
				$detallePago->MonedaP = $datosPago[0]->Moneda;
				
				if ($datosPago[0]->Moneda == "MXN"){
					$detallePago->TipoCambioP = null;
				} else {
					$detallePago->TipoCambioP = $datosPago[0]->TipoCambio;
				}
				
				$detallePago->Monto = $datosPago[0]->Monto;
				$detallePago->NumOperacion = null;
				$detallePago->RfcEmisorCtaOrd = $datosPago[0]->RFCEmisorCtaOrd;
				$detallePago->NomBancoOrdExt = $datosPago[0]->NomBancoOrdExt;
				$detallePago->CtaOrdenante = $datosPago[0]->CtaOrdenante;
				$detallePago->RfcEmisorCtaBen = $datosPago[0]->RFCEmisorCtaBen;
				$detallePago->CtaBeneficiario = $datosPago[0]->CtaBeneficiario;
				$detallePago->TipoCadPago = $datosPago[0]->TipoCadPago;
				$detallePago->CertPago = $datosPago[0]->CertPago;
				$detallePago->CadPago = $datosPago[0]->CadPago;
				$detallePago->SelloPago = $datosPago[0]->SelloPago;
				
				$mensaje = "Error al agregar el detalle de impuestos al complemento de pagos";
				$detallePago->Impuestos = null;
				
				//DATOS DE CADA COMPROBANTE PAGADO TOTAL O PARCIALMENTE
				$mensaje = "Error al agregar el detalle de los comprobantes pagados al complemento de pagos, probablemente el detalle de relaciones pagadas viene vacío";
				for ($x = 0; $x < count($datosDetalle); $x++){
					$mensaje = "Error al agregar el detalle del comprobante pagado numero " . strval($x + 1) . " de " . strval(count($datosDetalle)) . ". Revise la información almacenada en BD." ;
					$tmpPago = new DoctoRelacionadoPago();
					
					$tmpPago->IdDocumento = $datosDetalle[$x]->Iddocumento;
					$tmpPago->Serie = $datosDetalle[$x]->Serie;
					$tmpPago->Folio = $datosDetalle[$x]->Folio;
					$tmpPago->MonedaDR = $datosDetalle[$x]->MonedaDR;
					
					if ($datosDetalle[$x]->MonedaDR == "MXN"){
						$tmpPago->TipoCambioDR = null;
					} else {
						$tmpPago->TipoCambioDR = $datosDetalle[$x]->TipoCambioDR;
					}
	
					$tmpPago->MetodoDePagoDR = $datosDetalle[$x]->MetodoPago;
					$tmpPago->NumParcialidad = $datosDetalle[$x]->NumParcialidad;
					$tmpPago->ImpSaldoAnt = $datosDetalle[$x]->ImpSaldoAnt;
					$tmpPago->ImpPagado = $datosDetalle[$x]->ImpPagado;
					$tmpPago->ImpSaldoInsoluto = $datosDetalle[$x]->ImpSaldoInsoluto;
				
					$detallePago->DoctoRelacionado [] = $tmpPago;
				}
				$contenedorPagos->Pago [] = $detallePago;
				
				$cpagos->Pagos = $contenedorPagos;
				$wcomprp->Complemento[] = $cpagos;
				
				$wcomprp->Addenda = null;
				$JSONrequest->Comprobante = $wcomprp;

				
				//CAMPOS PDF
				$mensaje = "Error al llenar el nodo CamposPDF";
				$infoPDF = new CamposPDF();
				$infoPDF->tipoComprobante = "COMPLEMENTO DE PAGO";
				$infoPDF->Comentarios = "ESTE COMPROBANTE NO TIENE COMENTARIOS ADICIONALES" ;
				
				$infoPDF->calleEmisor = $datosEncabezado[0]->DomEmisor;
				$infoPDF->noExteriorEmisor = $datosEncabezado[0]->NoExtEmisor;
				$infoPDF->noInteriorEmisor = "";
				$infoPDF->coloniaEmisor = $datosEncabezado[0]->ColEmisor;
				$infoPDF->codigoPostalEmisor = $datosEncabezado[0]->CPEmisor;
				$infoPDF->localidadEmisor = $datosEncabezado[0]->LocalidadEmisor;
				$infoPDF->municipioEmisor = $datosEncabezado[0]->MunicipioEmisor;
				$infoPDF->estadoEmisor = $datosEncabezado[0]->EstadoEmisor;
				$infoPDF->paisEmisor = $datosEncabezado[0]->PaisEmisor;
				
				$infoPDF->calleReceptor = $datosEncabezado[0]->DomReceptor;
				$infoPDF->noExteriorReceptor = $datosEncabezado[0]->NoExtReceptor;
				$infoPDF->noInteriorReceptor = "";
				$infoPDF->coloniaReceptor = $datosEncabezado[0]->ColReceptor;
				$infoPDF->codigoPostalReceptor = $datosEncabezado[0]->CPReceptor;
				$infoPDF->localidadReceptor = $datosEncabezado[0]->LocalidadReceptor;
				$infoPDF->municipioReceptor = $datosEncabezado[0]->MunicipioReceptor;
				$infoPDF->estadoReceptor = $datosEncabezado[0]->EstadoReceptor;
				$infoPDF->paisReceptor = $datosEncabezado[0]->PaisReceptor;
				
				/*
				$infoPDF->calleEmisor = $datosEncabezado[0]->DomEmisor;
				$infoPDF->noExteriorEmisor = "xx";
				$infoPDF->noInteriorEmisor = "xx";
				$infoPDF->coloniaEmisor = "xx";
				$infoPDF->codigoPostalEmisor = "xx";
				$infoPDF->localidadEmisor = "xx";
				$infoPDF->municipioEmisor = "xx";
				$infoPDF->estadoEmisor = "xx";
				$infoPDF->paisEmisor = "xx";
				
				$infoPDF->calleReceptor = $datosEncabezado[0]->DomReceptor;
				$infoPDF->noExteriorReceptor = "xx";
				$infoPDF->noInteriorReceptor = "xx";
				$infoPDF->coloniaReceptor = "xx";
				$infoPDF->codigoPostalReceptor = "xx";
				$infoPDF->localidadReceptor = "xx";
				$infoPDF->municipioReceptor = "xx";
				$infoPDF->estadoReceptor = "xx";
				$infoPDF->paisReceptor = "xx";
				
				//PRUEBA ETIQUETAS EN NOTA DE CREDITO
				$etiquetaRelacionFolio = new EtiquetaAddenda();
				$etiquetaRelacionFolio->nombre = "Relacion factura:";
				$etiquetaRelacionFolio->valor = "5567";
				
				$etiquetaRelacionUUID = new EtiquetaAddenda();
				$etiquetaRelacionUUID->nombre = "Relacion UUID:";
				$etiquetaRelacionUUID->valor = "ASDFASDFSDF-ASFSDFS-F-SDFSDF";
				
				$infoPDF->etiquetas = [$etiquetaRelacionFolio, $etiquetaRelacionUUID];
				
				*/
				
				$JSONrequest->CamposPDF = $infoPDF;
				
				//*********[CORREOS]********************				
				$arrayCorreos = array();				
				array_push($arrayCorreos, $datosEncabezado[0]->Correo);								
				$listaCorreos = new Correos();
				$listaCorreos->Correos = $arrayCorreos;				
				$JSONrequest->EnviarCFDI = $listaCorreos;
				
				$mensaje = "Error al generar el Base64 de la petición armada";
				
				$logoEmpresa = base64_encode(file_get_contents($datosPAC[0]->logo));
				$JSONrequest->logo = $logoEmpresa;
				$jsonresult = json_encode($JSONrequest);
				$cleanJSONtmp = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $jsonresult);
				
				$cleanJSONobj = json_decode($cleanJSONtmp); //Se convierte a objeto ya sin nulos
				$cleanJSON = json_encode($cleanJSONobj, JSON_PRETTY_PRINT);	//Otra vez se manda a json ya sin nulos
				
				//return $cleanJSON;
				
				$mensaje = "Error al guardar el JSON de la petición en filesystem";
				file_put_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json", $cleanJSON);
				
				//ENVIO A PAC
				$mensaje = "Error al obtener los sellos del cliente en formato PEM del filesystem";
				$objConexion = new Conexion($datosPAC[0]->url_ws);
				
				$jsonB64 = base64_encode( file_get_contents("peticiones/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".json") );
				$keyPEM = file_get_contents($datosPAC[0]->pem_key);
				$cerPEM = file_get_contents($datosPAC[0]->pem_cer);
				$plantilla = 'pagos2';
				
				$mensaje = "Error al consumir servicio web del PAC";
				$resultadoTimbrado = json_decode($objConexion->operacion_timbrarJSON2($datosPAC[0]->token, $jsonB64, $keyPEM, $cerPEM, $plantilla, $logoEmpresa));
				
				$usrRespuesta = new RespuestaTimbrado();
				//CONSUMO DE RESPUESTA
				if (intval($resultadoTimbrado->codigo) == 200 || intval($resultadoTimbrado->codigo) == 307){
					//Timbrado correcto
					
					//1 - Guardado en Filesystem
					$mensaje = "Error al guardar el PDF y XML del timbrado en el filesystem";
					$archivosCFDI = json_decode($resultadoTimbrado->datos);
					$PDF_response = str_replace("\/","/",str_replace("\n","", $archivosCFDI->PDF));
					$XML_response = str_replace('\"','"',str_replace("\n","", $archivosCFDI->XML));
					file_put_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml", $XML_response);
					$ifp = fopen("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf", "wb" ); 
					fwrite( $ifp, base64_decode( $PDF_response) ); 
					fclose( $ifp );
					//file_put_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf", file_get_contents($PDF_response)); //TODO: Crear estructura segun fecha de timbrado
					
					
					//Deserializar XML para sacar información del timbrado
					$mensaje = "Error al Extraer datos del XML del comprobante timbrado";
					try {
						$XML_response = str_replace("tfd:", "", str_replace("cfdi:","", file_get_contents("boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml")));

						$Comprobante = new SimpleXMLElement($XML_response);
						
						$pArrFecha = explode("T", $Comprobante["Fecha"]);
						$pArrYMD = explode("-", $pArrFecha[0]);
	
						$pFechaEmision = $pArrYMD[2] . "/" . $pArrYMD[1] . "/" . $pArrYMD[0] . " " . $pArrFecha[1];
						$pFolio = $Comprobante["Folio"];
						$pSerie = $Comprobante["Serie"];
						$pSubtotal = $Comprobante["SubTotal"];
						$pTotal = $Comprobante["Total"];
						$pDescuento = $Comprobante["Descuento"];
						if ($pDescuento === null){
							$pDescuento = "0.00";	//No siempre aprece, por eso se verifica que no quede vacío
						}
						$pURL_PDF = "boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".pdf";
						$pURL_XML = "boveda/" . $datosEncabezado[0]->Serie . "_" . $datosEncabezado[0]->Folio . ".xml";
						//$idEmpresa
						//$tipoSistema
						//$idPago
						
						$pTipoFactura = $pSerie;
						$pIVA = $Comprobante->Impuestos["TotalImpuestosTrasladados"];
						if ($pIVA === null){
							$pIVA = "0.00"; 		//No siempre aparece, por eso se verifica que no quede vacío
						}
						
						$pRFC_Emisor = $Comprobante->Emisor["Rfc"];
						$pRazon_Social_Emisor = $Comprobante->Emisor["Nombre"];
						$pRFC_Receptor = $Comprobante->Receptor["Rfc"];
						$pRazon_Social_Receptor = $Comprobante->Receptor["Nombre"];
						$pUUID = $Comprobante->Complemento->TimbreFiscalDigital["UUID"];
					} catch (Exception $ex){
						//Error de timbrado
						$usrRespuesta->mensaje = $resultadoTimbrado->mensaje;
						$usrRespuesta->estado = "0";
						return $usrRespuesta;
					}
					
					//Llamado a proc BD
					$mensaje = "Error al guardar datos del timbrado en Base de Datos";
					try {
						$stmt3 = $conexion->prepare("call setivera_facturacion.emision_facturas_insertar('$idEmpresa','$tipoSistema','$idPago','$pTipoFactura' ,'$pFolio' ,'$pSerie' ,'$pUUID' ,'$pRFC_Emisor' ,'$pRazon_Social_Emisor' ,'$pRFC_Receptor' ,'$pRazon_Social_Receptor' ,'$pFechaEmision' ,'$pSubtotal' ,'$pDescuento' ,'$pIVA' ,'$pTotal' ,'$pURL_PDF' ,'$pURL_XML')");
						$stmt3->execute();	
							
						$numRegistrosGuardado = $stmt3->rowCount();
						if($numRegistrosGuardado > 0) {
							while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) {
								$pTransaccionGuardado = $row["Transaccion"];
								$pMensajeGuardado = $row["Mensaje"];
							};
							$stmt3->closeCursor();
							if (intval($pTransaccionGuardado) == 1){
								//Proceso terminado
								//Respuesta al usuario
								$usrRespuesta->estado = $pTransaccionGuardado;
								$usrRespuesta->mensaje = "Timbrado correcto de comprobante " . $pSerie . "_" . $pFolio . " con UUID " . $pUUID . ". ";
								return $usrRespuesta;
							} else {
								//Error al guardar en BD
								//Respuesta al usuario
								$usrRespuesta->estado = $pTransaccionGuardado;
								$usrRespuesta->mensaje = "Error al almacenar en BD resultado del timbrado: " . $pMensajeGuardado;
								return $usrRespuesta;
							}
						} else {
							$usrRespuesta->mensaje = $mensaje;
							$usrRespuesta->estado = "0";
							return $usrRespuesta;
						}
					} catch (Exception $ex){
						$usrRespuesta->mensaje = $mensaje;
						$usrRespuesta->estado = "0";
						return $usrRespuesta;
					}
					
				} else {
					//Error de timbrado
					$usrRespuesta->mensaje = $resultadoTimbrado->mensaje;
					$usrRespuesta->estado = "0";
					return $usrRespuesta;
				}
				
			} catch (Exception $e){
				return "Error en el armado de peticion de timbrado seccion DATOS GENERALES: " . $mensaje . "\r\n" . $e;
			}
			
		} catch (Exception $e){
			return "Error en obtención de datos de BD para petición de timbrado: " . $e;
		}
	}
	
	
	
?>