nes/gpt-4o-copilot/completions] took 540.9497800003737 ms
2025-05-08 17:42:46.690 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:42:46.690 [info] [streamChoices] request done: headerRequestId: [5ba84038-bdae-421c-8346-15b4e2c65ec1] model deployment ID: []
2025-05-08 17:43:33.233 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 510.5271230000071 ms
2025-05-08 17:43:33.235 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:43:33.239 [info] [streamChoices] request done: headerRequestId: [977960eb-5a42-473d-a460-4990c74a8cd8] model deployment ID: []
2025-05-08 17:43:33.905 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 418.57897200016305 ms
2025-05-08 17:43:33.907 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:43:33.909 [info] [streamChoices] request done: headerRequestId: [634c011b-e9f8-4af6-a48d-4a9354e9981f] model deployment ID: []
2025-05-08 17:43:35.277 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 608.5587290003896 ms
2025-05-08 17:43:35.280 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:43:35.284 [info] [streamChoices] request done: headerRequestId: [6741c5b0-4d70-46e6-bd32-c9b3629948d8] model deployment ID: []
2025-05-08 17:43:35.286 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 431.02239099983126 ms
2025-05-08 17:43:35.303 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:43:35.304 [info] [streamChoices] request done: headerRequestId: [ee62ad00-b0fe-4fe3-900b-a1d3b904d8cf] model deployment ID: []
2025-05-08 17:43:35.574 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 371.70352700026706 ms
2025-05-08 17:43:35.577 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:43:35.577 [info] [streamChoices] request done: headerRequestId: [fc38f048-634c-445a-af81-aaa85bfeee68] model deployment ID: []
2025-05-08 17:43:37.316 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 377.87556300032884 ms
2025-05-08 17:43:37.318 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:43:37.319 [info] [streamChoices] request done: headerRequestId: [ec877919-335c-4bad-8381-ee3f0208236d] model deployment ID: []
2025-05-08 17:45:05.113 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 479.33753499994054 ms
2025-05-08 17:45:05.115 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:45:05.119 [info] [streamChoices] request done: headerRequestId: [bfb94af8-b115-4b72-a5cb-2e7cc5271c73] model deployment ID: []
2025-05-08 17:49:29.988 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 533.1840059999377 ms
2025-05-08 17:49:29.991 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:49:29.992 [info] [streamChoices] request done: headerRequestId: [12bdf263-d23c-4938-b402-d774eb939c08] model deployment ID: []
2025-05-08 17:49:48.291 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 432.09137400006875 ms
2025-05-08 17:49:48.294 [info] [streamChoices] solution 0 returned. finish reason: [stop]
2025-05-08 17:49:48.295 [info] [streamChoices] request done: headerRequestId: [7dab3faf-5f1e-4c01-b23a-b1ea128df019] model deployment ID: []
2025-05-08 17:50:59.870 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o "300", "message" => "ERROR - [wsInvoiceSF] Parametros incompletos para el Servicio Web, faltan el Propoietario de la Aplicación");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bRecId == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan el ID del CFDI a actualizar");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatPAC == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos del PAC");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatGen == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsInvoiceSF] Parametros incompletos para el Servicio Web, faltan los Datos Generales");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatEmi == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos del Emisor");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatRec == "" or $bDatArt == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos del Receptor");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatArt == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos de los Articulos");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
### 0. EXTRACCION DE PARAMETROS PARA EL CFDI ######################################################
#== Primero, extraemos el JSON del string en base 64
$bdDatPAC = base64_decode($bDatPAC);
$bdDatGen = base64_decode($bDatGen);
$bdDatEmi = base64_decode($bDatEmi);
$bdDatRec = base64_decode($bDatRec);
$bdDatArt = base64_decode($bDatArt);
if($bDatRel <> "")
{
$bdDatRel = base64_decode($bDatRel);
}
if ($tipoTest == 1){
#== Desplegado de los parametros en formato JSON
echo $bdDatPAC;
echo '
';
echo '
';
echo $bdDatGen;
echo '
';
echo '
';
echo $bdDatEmi;
echo '
';
echo '
';
echo $bdDatRec;
echo '
';
echo '
';
echo $bdDatArt;
echo '
';
echo '
';
echo $bdDatDoc;
echo '
';
echo '
';
}
#== Segundo, decodificamos el JSON a un arreglo
$abdDatPAC = json_decode($bdDatPAC,true);
$abdDatGen = json_decode($bdDatGen,true);
$abdDatEmi = json_decode($bdDatEmi,true);
$abdDatRec = json_decode($bdDatRec,true);
$abdDatArt = json_decode($bdDatArt,true);
$abdDatDoc = json_decode($bdDatDoc,true);
if($bDatRel <> "")
{
$abdDatRel = json_decode($bdDatRel,true);
}
#== Datos y Variables para OAuth Token
$coa_ClientId = $abdDatGen["C_OAuth_client_id"];
$coa_ClientSecret = $abdDatGen["C_OAuth_client_secret"];
$coa_RefreshToken = $abdDatGen["C_OAuth_refresh_token"];
$coa_GrantType = $abdDatGen["C_OAuth_grant_type"];
$coa_RedirectUri = $abdDatGen["C_OAuth_redirect_uri"];
$coa_AuthUrl = "https://accounts.zoho.com/oauth/v2/token";
#----------------------------------------------------------------
# JFA: 2021-06-12
# Obtenemos el access_token
#----------------------------------------------------------------
$access_token = oauth($appOwner, 'ZCreator', $coa_RefreshToken, $coa_ClientId, $coa_ClientSecret, $coa_RedirectUri, $coa_GrantType, $coa_AuthUrl);
#== Conexión a Zoho Creator para el detalle del CFDI
// Added by FFR para el manejo de Complementos de Pago con 1 o multiples documentos relacionados
$request_url = 'https://creator.zoho.com/api/v2/'.$appOwner.'/'.$applnkname.'/report/cfdi_cp_query/'.$bRecId;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Zoho-oauthtoken ' . $access_token));
$r = curl_exec($ch);
$array = json_decode($r);
$bdDatDoc = $array->data->jsonDoctosRel;
$abdDatDoc = json_decode($bdDatDoc,true);
$dirBase = realpath("../");
### CÓDIGO FUENTE, FACTURACIÓN ELECTRÓNICA CFDI VERSIÓN 3.2 ACORDE A LOS REQUIRIMIENTOS DEL SAT, ANEXO 20.
### 1. CONFIGURACIÓN INICIAL ######################################################
# 1.1 Configuración de zona horaria
date_default_timezone_set('America/Mexico_City'); //
if($tipoTest > 0){
# 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. DEFINICIÓN DE CONSTANTES ###################################################
$SendaPEMS = "archs_pem/";
$SendaCFDI = "archs_cfdi/";
$SendaGRAFS = "archs_graf/";
$SendaXSD = "archs_xsd/";
// 2.1 Datos de acceso del usuario (proporcionados por el PAC).
if($abdDatPAC["tipoTim"] == 1){
## Timbrado en producción
$urlPAC = "https://solucionfactible.com/ws/services/Timbrado?wsdl";
}
else
{
## Timbrado en pruebas
$urlPAC = "https://testing.solucionfactible.com/ws/services/Timbrado?wsdl";
}
$username = $abdDatPAC["username"];
$password = $abdDatPAC["password"];
if($tipoTest > 0){
$username = "testing@solucionfactible.com";
$password = "timbrado.SF.16672";
$urlPAC = "https://testing.solucionfactible.com/ws/services/Timbrado?wsdl";
}
$valorNod = '';
$metodoDePago = "";
if ($tipoTest > 0){
### 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 'URL: '.$urlPAC."
";
echo '
';
}
### 3. DEFINICIÓN DE VARIABLES INICIALES ##########################################
$noCertificado = $abdDatGen["Certificado_SAT"];
$file_cer = $abdDatGen["Archivo_CER"];
$file_key = $abdDatGen["Archivo_KEY"];
$organi_id_ZB = $abdDatGen["organization_id_ZB"];
$authtoken_ZB = $abdDatGen["authtoken_ZB"];
$authtoken_ZC = $abdDatGen["authtoken_ZC"];
//echo $access_token;
### 4. DESTINATARIOS DE E-MAILS, PERSONAS A QUIENES LES LLEGARÁ DE MANERA ADJUNTA LA FACTURA ELECTRÓNICA EN ARCHIVOS .XML Y .PDF
$CadenaEmails = $abdDatGen["CadenaEmails"];
$CadenaEmails = "ffaccinetto@aptus-legal.com";
### 5. DATOS GENERALES DE LA FACTURA ##############################################
$fact_serie = $abdDatGen["comprobante_serie"];
$fact_folio = $abdDatGen["comprobante_folio"];
if ($bFolioN <> ""){
$fact_folio = $bFolioN;
}
$NoFac = $fact_serie.$fact_folio;
$fact_tipcompr = $abdDatGen["comprobante_tipo"];
$fact_exportacion = $abdDatGen["comprobante_exportacion"];
$subTotal = $abdDatGen["subTotal"];
$total = $abdDatGen["Total"];
$fecha_fact = $abdDatGen["comprobante_fecha"];
$condicionesDePago = $abdDatGen["condicionesDePago"];
$LugarExpedicion = utf8_decode($abdDatGen["LugarExpedicion"]);
$moneda = $abdDatGen["moneda"];
$invoiceNumber = utf8_decode($abdDatGen["invoiceNumber"]);
$invoiceID = $abdDatGen["invoiceID"];
$paymentID = $abdDatGen["paymentID"];
$TipoRelacion = $abdDatGen["TipoRelacion"];
### 5.1 DATOS GENERALES DEL PAGO ##############################################
$FechaPago = $abdDatGen["FechaPago"];
$FormaDePagoP = $abdDatGen["FormaDePagoP"];
$MonedaP = $abdDatGen["MonedaP"];
$Monto = number_format($abdDatGen["Monto"],2,'.','');
$TipoCambioP = number_format($abdDatGen["TipoCambioP"],6,'.','');
$NumOperacion = utf8_decode($abdDatGen["NumOperacion"]);
$RfcEmisorCtaOrd = utf8_decode($abdDatGen["RfcEmisorCtaOrd"]);
$NomBancoOrdExt = utf8_decode($abdDatGen["NomBancoOrdExt"]);
$CtaOrdenante = utf8_decode($abdDatGen["CtaOrdenante"]);
$RfcEmisorCtaBen = utf8_decode($abdDatGen["RfcEmisorCtaBen"]);
$CtaBeneficiario = utf8_decode($abdDatGen["CtaBeneficiario"]);
$TipoCadPago = utf8_decode($abdDatGen["TipoCadPago"]);
$CertPago = $abdDatGen["CertPago"];
$CadPago = $abdDatGen["CadPago"];
$SelloPago = $abdDatGen["SelloPago"];
if ($tipoTest > 0){
### 6. 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 '
';
}
### 7. ARRAYS QUE CONTIENEN LOS ARTICULOS QUE FORMAN PARTE DE LA VENTA ############
### 8. DATOS GENERALES DEL EMISOR #################################################
$emisor_rs = utf8_decode($abdDatEmi["emisor_rs"]);
$emisor_rfc = utf8_decode($abdDatEmi["emisor_rfc"]);
$emisor_regfis = utf8_decode($abdDatEmi["emisor_regfis"]);
### 9. DATOS GENERALES DEL RECEPTOR (CLIENTE) #####################################
$RFC_Recep = utf8_decode($abdDatRec["RFC_Recep"]);
if (strlen($RFC_Recep)==12){$RFC_Recep = " ".$RFC_Recep; }else{$RFC_Recep = $RFC_Recep;}
$receptor_rfc = $RFC_Recep;
$receptor_rs = utf8_decode($abdDatRec["receptor_rs"]);
$receptor_uso = utf8_decode($abdDatGen["usoCFDI"]);
$receptor_regfis = utf8_decode($abdDatRec["receptor_regfis"]);
$receptor_cp = utf8_decode($abdDatRec["receptor_cp"]);
if($TipPDFGen == 1)
{
$receptor_cal = utf8_decode($abdDatRec["receptor_cal"]);
$receptor_ne = utf8_decode($abdDatRec["receptor_ne"]);
$receptor_ni = utf8_decode($abdDatRec["receptor_ni"]);
$receptor_col = utf8_decode($abdDatRec["receptor_col"]);
$receptos_loc = utf8_decode($abdDatRec["receptor_loc"]);
$receptor_del = utf8_decode($abdDatRec["receptor_del"]);
$receptor_edo = utf8_decode($abdDatRec["receptor_edo"]);
$receptor_pai = utf8_decode($abdDatRec["receptor_pai"]);
$receptor_cp = utf8_decode($abdDatRec["receptor_cp"]);
$sDomicilio = $receptor_cal;
if($receptor_ne != "")
{
$sDomicilio = $sDomicilio." ".$receptor_ne;
}
if($receptor_ni != "")
{
$sDomicilio = $sDomicilio." ".$receptor_ni;
}
if($receptor_col != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_col;
}
if($receptos_loc != "")
{
$sDomicilio = $sDomicilio.", ".$receptos_loc;
}
if($receptor_del != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_del;
}
if($receptor_edo != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_edo;
}
if($receptor_pai != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_pai;
}
if($receptor_cp != "")
{
$sDomicilio = $sDomicilio." ".$receptor_cp;
}
$sDireRecep = base64_encode(utf8_encode($sDomicilio));
}
// Calculamos el Monto Total de los Pagos relacionados
$TotalRetencionesIVA = $TotalRetencionesISR = $TotalRetencionesIEPS = 0.00;
$TotalTrasladosBaseIVA16 = $TotalTrasladosImpuestoIVA16 = 0.00;
$TotalTrasladosBaseIVA8 = $TotalTrasladosImpuestoIVA8 = 0.00;
$TotalTrasladosBaseIVA0 = $TotalTrasladosImpuestoIVA0 = 0.00;
$TotalTrasladosBaseIVAExento = $MontoTotalPagos = 0.00;
foreach ($abdDatDoc as $doc) {
$MonedaDR = $doc["MonedaDR"];
$TipoCambioDR = $doc["TipoCambioDR"];
// Cálculo del importe de pago con precisión de 6 decimales
if ($MonedaP == "MXN") {
$importePago = round($MonedaDR != $MonedaP ? $doc["ImpPagado"] * $TipoCambioDR : $doc["ImpPagado"], 6);
//echo $importePago;
//exit;
} else {
$importePago = round($MonedaDR != $MonedaP ? $doc["ImpPagado"] * $TipoCambioP : $doc["ImpPagado"], 6);
}
$MontoTotalPagos += round($importePago, 6);
// Verificación de impuestos
if ($doc["ObjetoImpDR"] == "02") {
// Retenciones
if ($doc["RDR_ImpuestoDR"] == "001") $TotalRetencionesISR += $doc["RDR_ImporteDR"];
if ($doc["RDR_ImpuestoDR"] == "002") $TotalRetencionesIVA += $doc["RDR_ImporteDR"];
// Traslados
if ($doc["TDR_ImpuestoDR"] == "002") {
switch ($doc["TDR_TasaOCuotaDR"]) {
case 0.16:
$TotalTrasladosBaseIVA16 += $doc["TDR_BaseDR"];
$TotalTrasladosImpuestoIVA16 += $doc["TDR_ImporteDR"];
break;
case 0.08:
$TotalTrasladosBaseIVA8 += $doc["TDR_BaseDR"];
$TotalTrasladosImpuestoIVA8 += $doc["TDR_ImporteDR"];
break;
case 0.00:
$TotalTrasladosBaseIVA0 += $doc["TDR_BaseDR"];
$TotalTrasladosImpuestoIVA0 += $doc["TDR_ImporteDR"];
break;
}
}
}
}
// Ajustes según la moneda de pago y el tipo de cambio
if ($MonedaP != "MXN" && $TipoCambioP > 1.000000) {
if ($MonedaDR != "MXN") {
$factor = $TipoCambioP;
} else {
$factor = 1 / $TipoCambioP;
}
// Aplicamos redondeo con factor de conversión
$TotalRetencionesISR = round($TotalRetencionesISR * $factor, 2);
$TotalRetencionesIVA = round($TotalRetencionesIVA * $factor, 2);
$TotalTrasladosBaseIVA16 = round($TotalTrasladosBaseIVA16 * $factor, 2);
$TotalTrasladosImpuestoIVA16 = round($TotalTrasladosImpuestoIVA16 * $factor, 2);
$TotalTrasladosBaseIVA8 = round($TotalTrasladosBaseIVA8 * $factor, 2);
$TotalTrasladosImpuestoIVA8 = round($TotalTrasladosImpuestoIVA8 * $factor, 2);
$TotalTrasladosBaseIVA0 = round($TotalTrasladosBaseIVA0 * $factor, 2);
$TotalTrasladosImpuestoIVA0 = round($TotalTrasladosImpuestoIVA0 * $factor, 2);
$MontoTotalPagos = round($MontoTotalPagos * $factor, 6);
}
// Ajuste final cuando MonedaP es MXN y MonedaDR no lo es
if ($MonedaP == "MXN" && $MonedaDR != "MXN") {
$factor = 1 / $TipoCambioDR;
$TotalRetencionesISR = round($TotalRetencionesISR * $factor, 2);
$TotalRetencionesIVA = round($TotalRetencionesIVA * $factor, 2);
$TotalTrasladosBaseIVA16 = round($TotalTrasladosBaseIVA16 * $factor, 2);
$TotalTrasladosImpuestoIVA16 = round($TotalTrasladosImpuestoIVA16 * $factor, 2);
$TotalTrasladosBaseIVA8 = round($TotalTrasladosBaseIVA8 * $factor, 2);
$TotalTrasladosImpuestoIVA8 = round($TotalTrasladosImpuestoIVA8 * $factor, 2);
$TotalTrasladosBaseIVA0 = round($TotalTrasladosBaseIVA0 * $factor, 2);
$TotalTrasladosImpuestoIVA0 = round($TotalTrasladosImpuestoIVA0 * $factor, 2);
}
//Corrección específica de decimales en los montos de pago para los complementos pagados en MXN y documentos originales de USD
if($MonedaP == $MonedaDR){
// Corrección del calculo de monto de pago
$MontoTotalPagos = $Monto;
}else{
// Corrección del calculo de monto de pago
$MontoTotalPagos = $Monto * $TipoCambioP;
}
### 10. CREACIÓN Y ALMACENAMIENTO DEL ARCHIVO .XML (CFDI) ANTES DE SER TIMBRADO ###################
#== 10.1 Creación de la variable de tipo DOM, aquí se conforma el XML a timbrar posteriormente.
$xml = new DOMdocument('1.0', 'UTF-8');
"300", "message" => "ERROR - [wsInvoiceSF] Parametros incompletos para el Servicio Web, faltan el Propoietario de la Aplicación");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bRecId == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan el ID del CFDI a actualizar");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatPAC == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos del PAC");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatGen == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsInvoiceSF] Parametros incompletos para el Servicio Web, faltan los Datos Generales");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatEmi == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos del Emisor");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatRec == "" or $bDatArt == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos del Receptor");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if($bDatArt == "")
{
$j_array = array('code' => "300", "message" => "ERROR - [wsComPagoSF_VP_v33] Parametros incompletos para el Servicio Web, faltan los Datos de los Articulos");
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
### 0. EXTRACCION DE PARAMETROS PARA EL CFDI ######################################################
#== Primero, extraemos el JSON del string en base 64
$bdDatPAC = base64_decode($bDatPAC);
$bdDatGen = base64_decode($bDatGen);
$bdDatEmi = base64_decode($bDatEmi);
$bdDatRec = base64_decode($bDatRec);
$bdDatArt = base64_decode($bDatArt);
if($bDatRel <> "")
{
$bdDatRel = base64_decode($bDatRel);
}
if ($tipoTest == 1){
#== Desplegado de los parametros en formato JSON
echo $bdDatPAC;
echo '
';
echo '
';
echo $bdDatGen;
echo '
';
echo '
';
echo $bdDatEmi;
echo '
';
echo '
';
echo $bdDatRec;
echo '
';
echo '
';
echo $bdDatArt;
echo '
';
echo '
';
echo $bdDatDoc;
echo '
';
echo '
';
}
#== Segundo, decodificamos el JSON a un arreglo
$abdDatPAC = json_decode($bdDatPAC,true);
$abdDatGen = json_decode($bdDatGen,true);
$abdDatEmi = json_decode($bdDatEmi,true);
$abdDatRec = json_decode($bdDatRec,true);
$abdDatArt = json_decode($bdDatArt,true);
$abdDatDoc = json_decode($bdDatDoc,true);
if($bDatRel <> "")
{
$abdDatRel = json_decode($bdDatRel,true);
}
#== Datos y Variables para OAuth Token
$coa_ClientId = $abdDatGen["C_OAuth_client_id"];
$coa_ClientSecret = $abdDatGen["C_OAuth_client_secret"];
$coa_RefreshToken = $abdDatGen["C_OAuth_refresh_token"];
$coa_GrantType = $abdDatGen["C_OAuth_grant_type"];
$coa_RedirectUri = $abdDatGen["C_OAuth_redirect_uri"];
$coa_AuthUrl = "https://accounts.zoho.com/oauth/v2/token";
#----------------------------------------------------------------
# JFA: 2021-06-12
# Obtenemos el access_token
#----------------------------------------------------------------
$access_token = oauth($appOwner, 'ZCreator', $coa_RefreshToken, $coa_ClientId, $coa_ClientSecret, $coa_RedirectUri, $coa_GrantType, $coa_AuthUrl);
#== Conexión a Zoho Creator para el detalle del CFDI
// Added by FFR para el manejo de Complementos de Pago con 1 o multiples documentos relacionados
$request_url = 'https://creator.zoho.com/api/v2/'.$appOwner.'/'.$applnkname.'/report/cfdi_cp_query/'.$bRecId;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Zoho-oauthtoken ' . $access_token));
$r = curl_exec($ch);
$array = json_decode($r);
$bdDatDoc = $array->data->jsonDoctosRel;
$abdDatDoc = json_decode($bdDatDoc,true);
$dirBase = realpath("../");
### CÓDIGO FUENTE, FACTURACIÓN ELECTRÓNICA CFDI VERSIÓN 3.2 ACORDE A LOS REQUIRIMIENTOS DEL SAT, ANEXO 20.
### 1. CONFIGURACIÓN INICIAL ######################################################
# 1.1 Configuración de zona horaria
date_default_timezone_set('America/Mexico_City'); //
if($tipoTest > 0){
# 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. DEFINICIÓN DE CONSTANTES ###################################################
$SendaPEMS = "archs_pem/";
$SendaCFDI = "archs_cfdi/";
$SendaGRAFS = "archs_graf/";
$SendaXSD = "archs_xsd/";
// 2.1 Datos de acceso del usuario (proporcionados por el PAC).
if($abdDatPAC["tipoTim"] == 1){
## Timbrado en producción
$urlPAC = "https://solucionfactible.com/ws/services/Timbrado?wsdl";
}
else
{
## Timbrado en pruebas
$urlPAC = "https://testing.solucionfactible.com/ws/services/Timbrado?wsdl";
}
$username = $abdDatPAC["username"];
$password = $abdDatPAC["password"];
if($tipoTest > 0){
$username = "testing@solucionfactible.com";
$password = "timbrado.SF.16672";
$urlPAC = "https://testing.solucionfactible.com/ws/services/Timbrado?wsdl";
}
$valorNod = '';
$metodoDePago = "";
if ($tipoTest > 0){
### 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 'URL: '.$urlPAC."
";
echo '
';
}
### 3. DEFINICIÓN DE VARIABLES INICIALES ##########################################
$noCertificado = $abdDatGen["Certificado_SAT"];
$file_cer = $abdDatGen["Archivo_CER"];
$file_key = $abdDatGen["Archivo_KEY"];
$organi_id_ZB = $abdDatGen["organization_id_ZB"];
$authtoken_ZB = $abdDatGen["authtoken_ZB"];
$authtoken_ZC = $abdDatGen["authtoken_ZC"];
//echo $access_token;
### 4. DESTINATARIOS DE E-MAILS, PERSONAS A QUIENES LES LLEGARÁ DE MANERA ADJUNTA LA FACTURA ELECTRÓNICA EN ARCHIVOS .XML Y .PDF
$CadenaEmails = $abdDatGen["CadenaEmails"];
$CadenaEmails = "ffaccinetto@aptus-legal.com";
### 5. DATOS GENERALES DE LA FACTURA ##############################################
$fact_serie = $abdDatGen["comprobante_serie"];
$fact_folio = $abdDatGen["comprobante_folio"];
if ($bFolioN <> ""){
$fact_folio = $bFolioN;
}
$NoFac = $fact_serie.$fact_folio;
$fact_tipcompr = $abdDatGen["comprobante_tipo"];
$fact_exportacion = $abdDatGen["comprobante_exportacion"];
$subTotal = $abdDatGen["subTotal"];
$total = $abdDatGen["Total"];
$fecha_fact = $abdDatGen["comprobante_fecha"];
$condicionesDePago = $abdDatGen["condicionesDePago"];
$LugarExpedicion = utf8_decode($abdDatGen["LugarExpedicion"]);
$moneda = $abdDatGen["moneda"];
$invoiceNumber = utf8_decode($abdDatGen["invoiceNumber"]);
$invoiceID = $abdDatGen["invoiceID"];
$paymentID = $abdDatGen["paymentID"];
$TipoRelacion = $abdDatGen["TipoRelacion"];
### 5.1 DATOS GENERALES DEL PAGO ##############################################
$FechaPago = $abdDatGen["FechaPago"];
$FormaDePagoP = $abdDatGen["FormaDePagoP"];
$MonedaP = $abdDatGen["MonedaP"];
$Monto = number_format($abdDatGen["Monto"],2,'.','');
$TipoCambioP = number_format($abdDatGen["TipoCambioP"],6,'.','');
$NumOperacion = utf8_decode($abdDatGen["NumOperacion"]);
$RfcEmisorCtaOrd = utf8_decode($abdDatGen["RfcEmisorCtaOrd"]);
$NomBancoOrdExt = utf8_decode($abdDatGen["NomBancoOrdExt"]);
$CtaOrdenante = utf8_decode($abdDatGen["CtaOrdenante"]);
$RfcEmisorCtaBen = utf8_decode($abdDatGen["RfcEmisorCtaBen"]);
$CtaBeneficiario = utf8_decode($abdDatGen["CtaBeneficiario"]);
$TipoCadPago = utf8_decode($abdDatGen["TipoCadPago"]);
$CertPago = $abdDatGen["CertPago"];
$CadPago = $abdDatGen["CadPago"];
$SelloPago = $abdDatGen["SelloPago"];
if ($tipoTest > 0){
### 6. 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 '
';
}
### 7. ARRAYS QUE CONTIENEN LOS ARTICULOS QUE FORMAN PARTE DE LA VENTA ############
### 8. DATOS GENERALES DEL EMISOR #################################################
$emisor_rs = utf8_decode($abdDatEmi["emisor_rs"]);
$emisor_rfc = utf8_decode($abdDatEmi["emisor_rfc"]);
$emisor_regfis = utf8_decode($abdDatEmi["emisor_regfis"]);
### 9. DATOS GENERALES DEL RECEPTOR (CLIENTE) #####################################
$RFC_Recep = utf8_decode($abdDatRec["RFC_Recep"]);
if (strlen($RFC_Recep)==12){$RFC_Recep = " ".$RFC_Recep; }else{$RFC_Recep = $RFC_Recep;}
$receptor_rfc = $RFC_Recep;
$receptor_rs = utf8_decode($abdDatRec["receptor_rs"]);
$receptor_uso = utf8_decode($abdDatGen["usoCFDI"]);
$receptor_regfis = utf8_decode($abdDatRec["receptor_regfis"]);
$receptor_cp = utf8_decode($abdDatRec["receptor_cp"]);
if($TipPDFGen == 1)
{
$receptor_cal = utf8_decode($abdDatRec["receptor_cal"]);
$receptor_ne = utf8_decode($abdDatRec["receptor_ne"]);
$receptor_ni = utf8_decode($abdDatRec["receptor_ni"]);
$receptor_col = utf8_decode($abdDatRec["receptor_col"]);
$receptos_loc = utf8_decode($abdDatRec["receptor_loc"]);
$receptor_del = utf8_decode($abdDatRec["receptor_del"]);
$receptor_edo = utf8_decode($abdDatRec["receptor_edo"]);
$receptor_pai = utf8_decode($abdDatRec["receptor_pai"]);
$receptor_cp = utf8_decode($abdDatRec["receptor_cp"]);
$sDomicilio = $receptor_cal;
if($receptor_ne != "")
{
$sDomicilio = $sDomicilio." ".$receptor_ne;
}
if($receptor_ni != "")
{
$sDomicilio = $sDomicilio." ".$receptor_ni;
}
if($receptor_col != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_col;
}
if($receptos_loc != "")
{
$sDomicilio = $sDomicilio.", ".$receptos_loc;
}
if($receptor_del != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_del;
}
if($receptor_edo != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_edo;
}
if($receptor_pai != "")
{
$sDomicilio = $sDomicilio.", ".$receptor_pai;
}
if($receptor_cp != "")
{
$sDomicilio = $sDomicilio." ".$receptor_cp;
}
$sDireRecep = base64_encode(utf8_encode($sDomicilio));
}
// Calculamos el Monto Total de los Pagos relacionados
$TotalRetencionesIVA = $TotalRetencionesISR = $TotalRetencionesIEPS = 0.00;
$TotalTrasladosBaseIVA16 = $TotalTrasladosImpuestoIVA16 = 0.00;
$TotalTrasladosBaseIVA8 = $TotalTrasladosImpuestoIVA8 = 0.00;
$TotalTrasladosBaseIVA0 = $TotalTrasladosImpuestoIVA0 = 0.00;
$TotalTrasladosBaseIVAExento = $MontoTotalPagos = 0.00;
foreach ($abdDatDoc as $doc) {
$monDoc = $doc["MonedaDR"];
$tipCamDoc = $doc["TipoCambioDR"];
// Determinar factor de conversión a la moneda de pago ($MonedaP, $TipoCambioP ya definidos)
if ($monDoc === $MonedaP) {
$factor = 1;
} elseif ($monDoc === "MXN" && $MonedaP !== "MXN") {
// de MXN a extranjera
$factor = 1 / $TipoCambioP;
} elseif ($monDoc !== "MXN" && $MonedaP === "MXN") {
// de extranjera a MXN
$factor = $tipCamDoc;
} else {
// ambas extranjeras y distintas: doc→MXN→pago
$factor = $tipCamDoc / $TipoCambioP;
}
// 1) Importe de pago
$imp = $doc["ImpPagado"];
$importePago = round($imp * $factor, 6);
$MontoTotalPagos += $importePago;
// 2) Impuestos (convertir cada importe con mismo factor, luego redondear a 2 decimales)
if ($doc["ObjetoImpDR"] === "02") {
// Retenciones
$r = $doc["RDR_ImporteDR"] * $factor;
if ($doc["RDR_ImpuestoDR"] === "001") {
$TotalRetencionesISR += round($r, 2);
}
if ($doc["RDR_ImpuestoDR"] === "002") {
$TotalRetencionesIVA += round($r, 2);
}
// Traslados IVA
if ($doc["TDR_ImpuestoDR"] === "002") {
$base = round($doc["TDR_BaseDR"] * $factor, 2);
$impTras = round($doc["TDR_ImporteDR"] * $factor, 2);
switch ($doc["TDR_TasaOCuotaDR"]) {
case 0.16:
$TotalTrasladosBaseIVA16 += $base;
$TotalTrasladosImpuestoIVA16 += $impTras;
break;
case 0.08:
$TotalTrasladosBaseIVA8 += $base;
$TotalTrasladosImpuestoIVA8 += $impTras;
break;
case 0.00:
$TotalTrasladosBaseIVA0 += $base;
$TotalTrasladosImpuestoIVA0 += $impTras;
break;
}
}
}
}
// Ajustes según la moneda de pago y el tipo de cambio
if ($MonedaP != "MXN" && $TipoCambioP > 1.000000) {
if ($MonedaDR != "MXN") {
$factor = $TipoCambioP;
} else {
$factor = 1 / $TipoCambioP;
}
// Aplicamos redondeo con factor de conversión
$TotalRetencionesISR = round($TotalRetencionesISR * $factor, 2);
$TotalRetencionesIVA = round($TotalRetencionesIVA * $factor, 2);
$TotalTrasladosBaseIVA16 = round($TotalTrasladosBaseIVA16 * $factor, 2);
$TotalTrasladosImpuestoIVA16 = round($TotalTrasladosImpuestoIVA16 * $factor, 2);
$TotalTrasladosBaseIVA8 = round($TotalTrasladosBaseIVA8 * $factor, 2);
$TotalTrasladosImpuestoIVA8 = round($TotalTrasladosImpuestoIVA8 * $factor, 2);
$TotalTrasladosBaseIVA0 = round($TotalTrasladosBaseIVA0 * $factor, 2);
$TotalTrasladosImpuestoIVA0 = round($TotalTrasladosImpuestoIVA0 * $factor, 2);
$MontoTotalPagos = round($MontoTotalPagos * $factor, 6);
}
// Ajuste final cuando MonedaP es MXN y MonedaDR no lo es
if ($MonedaP == "MXN" && $MonedaDR != "MXN") {
$factor = 1 / $TipoCambioDR;
$TotalRetencionesISR = round($TotalRetencionesISR * $factor, 2);
$TotalRetencionesIVA = round($TotalRetencionesIVA * $factor, 2);
$TotalTrasladosBaseIVA16 = round($TotalTrasladosBaseIVA16 * $factor, 2);
$TotalTrasladosImpuestoIVA16 = round($TotalTrasladosImpuestoIVA16 * $factor, 2);
$TotalTrasladosBaseIVA8 = round($TotalTrasladosBaseIVA8 * $factor, 2);
$TotalTrasladosImpuestoIVA8 = round($TotalTrasladosImpuestoIVA8 * $factor, 2);
$TotalTrasladosBaseIVA0 = round($TotalTrasladosBaseIVA0 * $factor, 2);
$TotalTrasladosImpuestoIVA0 = round($TotalTrasladosImpuestoIVA0 * $factor, 2);
}
### 10. CREACIÓN Y ALMACENAMIENTO DEL ARCHIVO .XML (CFDI) ANTES DE SER TIMBRADO ###################
#== 10.1 Creación de la variable de tipo DOM, aquí se conforma el XML a timbrar posteriormente.
$xml = new DOMdocument('1.0', 'UTF-8');
$root = $xml->createElement("cfdi:Comprobante");
$root = $xml->appendChild($root);
$cadena_original='||';
$noatt= array();
#== 10.2 Se crea e inserta el primer nodo donde se declaran los namespaces ======
cargaAtt($root, array("xsi:schemaLocation"=>"http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd",
"xmlns:cfdi"=>"http://www.sat.gob.mx/cfd/4",
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
"xmlns:pago20" => "http://www.sat.gob.mx/Pagos20"
)
);
#== 10.3 Rutina de integración de nodos =========================================
if ($appOwner == "arochiylindner.aptus")
{
cargaAtt($root, array(
"Version"=>"4.0",
"Serie"=>$fact_serie,
"Folio"=>$fact_folio,
"Fecha"=>$fecha_fact,
"NoCertificado"=>$noCertificado,
"SubTotal"=>$subTotal,
"Moneda"=>$moneda,
"Total"=>$total,
"TipoDeComprobante"=>$fact_tipcompr,
"Exportacion"=>$fact_exportacion,
"LugarExpedicion"=>$LugarExpedicion,
"CondicionesDePago"=>$condicionesDePago,
)
);
}
else
{
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,
"Moneda"=>$moneda,
"Total"=>$total,
"TipoDeComprobante"=>$fact_tipcompr,
"Exportacion"=>$fact_exportacion,
"LugarExpedicion"=>$LugarExpedicion,
"CondicionesDePago"=>$condicionesDePago,
)
);
}
// Adicionado por FFR en Abril 08, 2019
// Para el manejo de los CFDI Relacionados
if($bDatRel <> "")
{
$cfdiRelacionados = $xml->createElement("cfdi:CfdiRelacionados");
$cfdiRelacionados = $root->appendChild($cfdiRelacionados);
cargaAtt($cfdiRelacionados, array("TipoRelacion"=>utf8_decode($TipoRelacion)));
for ($i=0; $i < count($abdDatRel); $i++)
{
$cfdiRelacionado = $xml->createElement("cfdi:CfdiRelacionado");
$cfdiRelacionado = $cfdiRelacionados->appendChild($cfdiRelacionado);
cargaAtt($cfdiRelacionado, array("UUID"=>utf8_decode($abdDatRel[$i]["UUID"])));
}
}
$emisor = $xml->createElement("cfdi:Emisor");
$emisor = $root->appendChild($emisor);
cargaAtt($emisor, array("Rfc"=>$emisor_rfc,
"Nombre"=>$emisor_rs,
"RegimenFiscal"=>$emisor_regfis
)
);
$receptor = $xml->createElement("cfdi:Receptor");
$receptor = $root->appendChild($receptor);
cargaAtt($receptor, array("Rfc"=>$receptor_rfc,
"Nombre"=>$receptor_rs,
"DomicilioFiscalReceptor"=>$receptor_cp,
"RegimenFiscalReceptor"=>$receptor_regfis,
"UsoCFDI"=>$receptor_uso
)
);
$conceptos = $xml->createElement("cfdi:Conceptos");
$conceptos = $root->appendChild($conceptos);
#== 10.4 Ciclo "for", recopilación de datos de artículos e integración de sus respectivos nodos =
for ($i=0; $icreateElement("cfdi:Concepto");
$concepto = $conceptos->appendChild($concepto);
cargaAtt($concepto, array(
"ClaveProdServ"=>utf8_decode($abdDatArt[$i]["claveProd"]),
"Cantidad"=>$abdDatArt[$i]["cantidad"],
"ClaveUnidad"=>utf8_decode($abdDatArt[$i]["unidad"]),
"Descripcion"=>utf8_decode($abdDatArt[$i]["descripcion"]),
"ValorUnitario"=>$abdDatArt[$i]["valorUnitario"],
"Importe"=>$abdDatArt[$i]["importe"],
"ObjetoImp"=>utf8_decode($abdDatArt[$i]["ObjetoImp"])
)
);
}
$complemento = $xml->createElement("cfdi:Complemento");
$complemento = $root->appendChild($complemento);
$Pagos = $xml->createElement("pago20:Pagos");
$Pagos = $complemento->appendChild($Pagos);
cargaAtt($Pagos, array("xmlns:pago20"=>"http://www.sat.gob.mx/Pagos20",
"Version"=>"2.0"
)
);
$totales = $xml->createElement("pago20:Totales");
$total = $Pagos->appendChild($totales);
$lSoloTotal = true;
if($TotalRetencionesIVA > 0.00)
{
$lSoloTotal = false;
cargaAtt($total, array(
"TotalRetencionesIVA"=>number_format($TotalRetencionesIVA,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
if($TotalRetencionesISR > 0.00 && $TotalTrasladosBaseIVA16 == 0.00)
{
$lSoloTotal = false;
cargaAtt($total, array(
"TotalRetencionesISR"=>number_format($TotalRetencionesISR,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
if($TotalRetencionesIEPS > 0.00)
{
$lSoloTotal = false;
cargaAtt($total, array(
"TotalRetencionesIEPS"=>number_format($TotalRetencionesIEPS,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
if($TotalTrasladosBaseIVA16 > 0.00)
{
$lSoloTotal = false;
if($TotalRetencionesISR > 0.00)
{
cargaAtt($total, array(
"TotalRetencionesISR"=>number_format($TotalRetencionesISR,2,'.',''),
"TotalTrasladosBaseIVA16"=>number_format($TotalTrasladosBaseIVA16,2,'.',''),
"TotalTrasladosImpuestoIVA16"=>number_format($TotalTrasladosImpuestoIVA16,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
else
{
cargaAtt($total, array(
"TotalTrasladosBaseIVA16"=>number_format($TotalTrasladosBaseIVA16,2,'.',''),
"TotalTrasladosImpuestoIVA16"=>number_format($TotalTrasladosImpuestoIVA16,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
}
if($TotalTrasladosBaseIVA8 > 0.00)
{
$lSoloTotal = false;
cargaAtt($total, array(
"TotalTrasladosBaseIVA8"=>number_format($TotalTrasladosBaseIVA8,2,'.',''),
"TotalTrasladosImpuestoIVA8"=>number_format($TotalTrasladosImpuestoIVA8,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
if($TotalTrasladosBaseIVA0 > 0.00)
{
$lSoloTotal = false;
cargaAtt($total, array(
"TotalTrasladosBaseIVA0"=>number_format($TotalTrasladosBaseIVA0,2,'.',''),
"TotalTrasladosImpuestoIVA0"=>number_format($TotalTrasladosImpuestoIVA0,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
if($TotalTrasladosBaseIVAExento > 0.00)
{
$lSoloTotal = false;
cargaAtt($total, array(
"TotalTrasladosBaseIVAExento"=>number_format($TotalTrasladosBaseIVAExento,2,'.',''),
"MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')
)
);
}
if($lSoloTotal == true)
{
$lSoloTotal = false;
cargaAtt($total, array("MontoTotalPagos"=>number_format($MontoTotalPagos,2,'.','')));
}
$pago = $xml->createElement("pago20:Pago");
$pago = $Pagos->appendChild($pago);
if ($MonedaP == "MXN")
{
cargaAtt($pago, array(
"FechaPago"=>$FechaPago,
"FormaDePagoP"=>$FormaDePagoP,
"MonedaP"=>$MonedaP,
"TipoCambioP"=>1,
"Monto"=>number_format($Monto,2,'.',''),
"NumOperacion"=>$NumOperacion,
"RfcEmisorCtaOrd"=>$RfcEmisorCtaOrd,
"NomBancoOrdExt"=>$NomBancoOrdExt,
"CtaOrdenante"=>$CtaOrdenante,
"RfcEmisorCtaBen"=>$RfcEmisorCtaBen,
"CtaBeneficiario"=>$CtaBeneficiario,
"TipoCadPago"=>$TipoCadPago,
"CertPago"=>$CertPago,
"CadPago"=>$CadPago,
"SelloPago"=>$SelloPago,
"xmlns:pago20"=>"http://www.sat.gob.mx/Pagos20"
)
);
}
else
{
cargaAtt($pago, array(
"FechaPago"=>$FechaPago,
"FormaDePagoP"=>$FormaDePagoP,
"MonedaP"=>$MonedaP,
"TipoCambioP"=>number_format($TipoCambioP,6,'.',''),
"Monto"=>number_format($Monto,2,'.',''),
"NumOperacion"=>$NumOperacion,
"RfcEmisorCtaOrd"=>$RfcEmisorCtaOrd,
"NomBancoOrdExt"=>$NomBancoOrdExt,
"CtaOrdenante"=>$CtaOrdenante,
"RfcEmisorCtaBen"=>$RfcEmisorCtaBen,
"CtaBeneficiario"=>$CtaBeneficiario,
"TipoCadPago"=>$TipoCadPago,
"CertPago"=>$CertPago,
"CadPago"=>$CadPago,
"SelloPago"=>$SelloPago,
"xmlns:pago20"=>"http://www.sat.gob.mx/Pagos20"
)
);
}
$impuestosP = false;
$RDR_ImpuestoDR = "";
$RDR_ImporteDR = 0.00;
$TDR_BaseDR = 0.00;
$TDR_ImpuestoDR = "";
$TDR_TipoFactorDR = "";
$TDR_TasaOCuotaDR = 0.00;
$TDR_ImporteDR = 0.00;
#== Ciclo "for", recopilación de datos de documento e integración de sus respectivos nodos =
$lImpuestosDR = false;
for ($i=0; $icreateElement("pago20:DoctoRelacionado");
$doctoRel = $pago->appendChild($doctoRel);
if($abdDatDoc[$i]["MonedaDR"] == $MonedaP)
{
cargaAtt($doctoRel, array(
"IdDocumento"=>utf8_decode($abdDatDoc[$i]["IdDocumento"]),
"Serie"=>$abdDatDoc[$i]["Serie"],
"Folio"=>$abdDatDoc[$i]["Folio"],
"MonedaDR"=>utf8_decode($abdDatDoc[$i]["MonedaDR"]),
//este valor lo cambié porque si los valores de la moneda son iguales la equivalencia debe de ser 1 pero se tiene que verificar
"EquivalenciaDR"=>$abdDatDoc[$i]["TipoCambioDR"],
// "EquivalenciaDR"=>1,
"NumParcialidad"=>$abdDatDoc[$i]["NumParcialidad"],
"ImpSaldoAnt"=>number_format($abdDatDoc[$i]["ImpSaldoAnt"],2,'.',''),
"ImpPagado"=>number_format($abdDatDoc[$i]["ImpPagado"],2,'.',''),
"ImpSaldoInsoluto"=>number_format($abdDatDoc[$i]["ImpSaldoInsoluto"],2,'.',''),
"ObjetoImpDR"=>$abdDatDoc[$i]["ObjetoImpDR"]
)
);
}
else
{
cargaAtt($doctoRel, array(
"IdDocumento"=>utf8_decode($abdDatDoc[$i]["IdDocumento"]),
"Serie"=>$abdDatDoc[$i]["Serie"],
"Folio"=>$abdDatDoc[$i]["Folio"],
"MonedaDR"=>utf8_decode($abdDatDoc[$i]["MonedaDR"]),
"EquivalenciaDR"=>$abdDatDoc[$i]["TipoCambioDR"],
"NumParcialidad"=>$abdDatDoc[$i]["NumParcialidad"],
"ImpSaldoAnt"=>number_format($abdDatDoc[$i]["ImpSaldoAnt"],2,'.',''),
"ImpPagado"=>number_format($abdDatDoc[$i]["ImpPagado"],2,'.',''),
"ImpSaldoInsoluto"=>number_format($abdDatDoc[$i]["ImpSaldoInsoluto"],2,'.',''),
"ObjetoImpDR"=>$abdDatDoc[$i]["ObjetoImpDR"]
)
);
}
// Verificamos si aplica desglose de impuestos o no
if($abdDatDoc[$i]["ObjetoImpDR"] == "02")
{
$impuestosP = true;
$impuestosDR = $xml->createElement("pago20:ImpuestosDR");
$impuestosDR = $doctoRel->appendChild($impuestosDR);
if($abdDatDoc[$i]["RDR_ImpuestoDR"] == "001")
{
$retencionesDR = $xml->createElement("pago20:RetencionesDR");
$retencionesDR = $impuestosDR->appendChild($retencionesDR);
$retencionDR = $xml->createElement("pago20:RetencionDR");
$retencionDR = $retencionesDR->appendChild($retencionDR);
$RDR_ImpuestoDR = $abdDatDoc[$i]["RDR_ImpuestoDR"];
$RDR_ImporteDR = $RDR_ImporteDR + $abdDatDoc[$i]["RDR_ImporteDR"];
cargaAtt($retencionDR, array(
"BaseDR"=>number_format($abdDatDoc[$i]["RDR_BaseDR"],2,'.',''),
"ImpuestoDR"=>$abdDatDoc[$i]["RDR_ImpuestoDR"],
"TipoFactorDR"=>$abdDatDoc[$i]["RDR_TipoFactorDR"],
"TasaOCuotaDR"=>number_format($abdDatDoc[$i]["RDR_TasaOCuotaDR"],6,'.',''),
"ImporteDR"=>number_format($abdDatDoc[$i]["RDR_ImporteDR"],2,'.','')
)
);
}
if($abdDatDoc[$i]["TDR_ImpuestoDR"] == "002")
{
$trasladosDR = $xml->createElement("pago20:TrasladosDR");
$trasladosDR = $impuestosDR->appendChild($trasladosDR);
$trasaldoDR = $xml->createElement("pago20:TrasladoDR");
$trasaldoDR = $trasladosDR->appendChild($trasaldoDR);
$TDR_BaseDR = $TDR_BaseDR + $abdDatDoc[$i]["TDR_BaseDR"];
$TDR_ImpuestoDR = $abdDatDoc[$i]["TDR_ImpuestoDR"];
$TDR_TipoFactorDR = $abdDatDoc[$i]["TDR_TipoFactorDR"];
$TDR_TasaOCuotaDR = $abdDatDoc[$i]["TDR_TasaOCuotaDR"];
$TDR_ImporteDR = $TDR_ImporteDR + $abdDatDoc[$i]["TDR_ImporteDR"];
cargaAtt($trasaldoDR, array(
"BaseDR"=>number_format($abdDatDoc[$i]["TDR_BaseDR"],2,'.',''),
"ImpuestoDR"=>$abdDatDoc[$i]["TDR_ImpuestoDR"],
"TipoFactorDR"=>$abdDatDoc[$i]["TDR_TipoFactorDR"],
"TasaOCuotaDR"=>number_format($abdDatDoc[$i]["TDR_TasaOCuotaDR"],6,'.',''),
"ImporteDR"=>number_format($abdDatDoc[$i]["TDR_ImporteDR"],2,'.','')
)
);
}
}
}
// Resumen de Impuestos en caso de Aplicar.
if($impuestosP == true)
{
$impuestosP = $xml->createElement("pago20:ImpuestosP");
$impuestosP = $pago->appendChild($impuestosP);
if($RDR_ImpuestoDR == "001")
{
if ($MonedaP == "MXN" && $MonedaDR != "MXN")
{
$RDR_ImporteDR = round($RDR_ImporteDR * (1/$TipoCambioDR), 2, PHP_ROUND_HALF_UP);
}
$retencionesP = $xml->createElement("pago20:RetencionesP");
$retencionesP = $impuestosP->appendChild($retencionesP);
$retencionP = $xml->createElement("pago20:RetencionP");
$retencionP = $retencionesP->appendChild($retencionP);
cargaAtt($retencionP, array(
"ImpuestoP"=>$RDR_ImpuestoDR,
"ImporteP"=>number_format($RDR_ImporteDR,2,'.','')
)
);
}
if($TDR_ImpuestoDR == "002")
{
if ($MonedaP == "MXN" && $MonedaDR != "MXN")
{
$TDR_BaseDR = round($TDR_BaseDR * (1/$TipoCambioDR), 2, PHP_ROUND_HALF_UP);
$TDR_ImporteDR = round($TDR_ImporteDR * (1/$TipoCambioDR), 2, PHP_ROUND_HALF_UP);
}
if ($MonedaP != "MXN" && $MonedaDR == "MXN")
{
$TDR_BaseDR = round($TDR_BaseDR / $TipoCambioDR, 6, PHP_ROUND_HALF_UP);
$TDR_ImporteDR = round($TDR_ImporteDR / $TipoCambioDR, 6, PHP_ROUND_HALF_UP);
}
$trasladosP = $xml->createElement("pago20:TrasladosP");
$trasladosP = $impuestosP->appendChild($trasladosP);
$trasladoP = $xml->createElement("pago20:TrasladoP");
$trasladoP = $trasladosP->appendChild($trasladoP);
cargaAtt($trasladoP, array(
"BaseP"=>number_format($TDR_BaseDR,6,'.',''),
"ImpuestoP"=>$TDR_ImpuestoDR,
"TipoFactorP"=>$TDR_TipoFactorDR,
"TasaOCuotaP"=>number_format($TDR_TasaOCuotaDR,6,'.',''),
"ImporteP"=>number_format($TDR_ImporteDR,6,'.','')
)
);
}
}
#== 10.7 Termina de conformarse la "Cadena original" con doble ||
$cadena_original .= "|";
if ($tipoTest > 0){
#=== Muestra la cadena original (opcional a mostrar) =======================
echo '';
echo 'CADENA ORIGINAL';
echo '
';
echo '';
echo $cadena_original;
echo '
';
}
#=== Muestra la cadena original (opcional a mostrar) =======================
#== 10.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);
#== 10.9 Se convierte la cadena digital a Base 64 ===========================
$sello = base64_encode($crypttext);
if ($tipoTest > 0){
#=== Muestra el sello (opcional a mostrar) =================================
echo '';
echo 'SELLO';
echo '
';
echo '';
echo $sello;
echo '
';
}
#== 10.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 0){
#=== Muestra el certificado del sello digital (opcional a mostrar) =========
echo '';
echo 'CERTIFICADO DEL SELLO DIGITAL';
echo '
';
echo '';
echo $certificado;
echo '
';
}
#== 10.11 Se continua con la integración de nodos ===========================
$root->setAttribute("Sello",$sello);
$root->setAttribute("Certificado",$certificado); # Certificado.
#== Fin de la integración de nodos =========================================
#=== 10.12 Se guarda el archivo .XML antes de ser timbrado =======================
$NomArchCFDI = $SendaCFDI."PreCFDI-33_".$NoFac.".xml";
$NomArchPDF1 = $SendaCFDI."VP_CFDI_".$fact_serie.str_pad($fact_folio, 6, "0", STR_PAD_LEFT)."_".$invoiceNumber.".pdf";
$NomArchXML = "PreCFDI-33_".$NoFac.".xml";
$NomArchPDF = "CFDI_".$fact_serie.str_pad($fact_folio, 6, "0", STR_PAD_LEFT)."_CP.pdf";
$cfdi = $xml->saveXML();
$xml->formatOutput = true;
$xml->save($NomArchCFDI); // Guarda el archivo .XML (sin timbrar) en el directorio predeterminado.
unset($xml);
#=== 10.13 Se dan permisos de escritura al archivo .xml. =========================
chmod($NomArchCFDI, 0777);
### 11. PROCESO DE TIMBRADO ########################################################
if ($tipoTest > 0){
#=== Se muestra el .XML antes de ser timbrado (opcional a mostrar)==========
echo '';
echo 'FACTURA .XML A TIMBRAR';
echo '
';
echo '';
echo htmlspecialchars($cfdi);
echo '
';
}
#== 11.1 Se crea una variable de tipo DOM y se le carga el CFDI =================================
$xml2 = new DOMDocument();
$xml2->loadXML($cfdi);
#== 11.2 Proceso de validación de la variable de tipo DOM (estructura del CFDI a timbrar) contra el esquema cfdv32.xsd ==========================
$fname = $SendaCFDI."PreCFDI-33_".$NoFac.".xml";
if(!file_exists($fname)){
die(PHP_EOL . "File not found" . PHP_EOL . PHP_EOL);
}
$handle = fopen($fname, "r");
$sData = '';
#== 11.3 Convirtiendo el contenido del CFDI a BASE 64 ======================
while(!feof($handle))
$sData .= fread($handle, filesize($fname));
fclose($handle);
//print_r($sData);
$b64 = base64_encode($sData);
$response = '';
if($abdDatPAC["tipoTim"] == 1){
## Timbrado en producción
$urlLocation = 'https://solucionfactible.com/ws/services/Timbrado';
}
else
{
## Timbrado en pruebas
$urlLocation = 'https://testing.solucionfactible.com/ws/services/Timbrado';
}
#== 11.5 Se lleva a cabo el timbrado del XML ============================
try {
$client = new SoapClient($urlPAC);
$client->__setLocation($urlLocation);
$params = array('usuario' => $username, 'password' => $password, 'cfdiBase64'=>$b64, 'zip'=>False);
$response = $client->__soapCall('timbrarBase64', array('parameters' => $params));
} catch (SoapFault $fault) {
$j_array = array('code' => "400", "message" => $fault->faultcode."-".$fault->faultstring);
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
$ret = $response->return;
if($ret->status != 200) {
$j_array = array('code' => "500", "message" => "ERROR EN EL PROCESO DE TIMBRADO. ".$ret->status." - ".$ret->mensaje);
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
#=== 11.7 Muestra los resultados del timbrado del CFDI =========================
$RespServ = $ret->resultados->cfdiTimbrado;
if($RespServ == NULL){
$j_array = array('code' => "600", "message" => "ERROR EN EL PROCESO DE TIMBRADO. status: ".$ret->status.", mensaje: ".$ret->mensaje.". ==> Resultado Timbrado: "." status: ".$ret->resultados->status.", mensaje: ".$ret->resultados->mensaje);
$Resultado = json_encode($j_array);
echo $Resultado;
return;
}
if ($tipoTest > 0){
#== 12.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($RespServ);
echo '
';
}
## 12. PROCESOS POSTERIORES AL TIMBRADO ########################################
#== 12.1 Se asigna la respuesta del servidor a una variable de tipo DOM ====
$VarXML = new DOMDocument();
$VarXML->loadXML($RespServ);
#== 12.2 Se graba la respuesta del servidor a un archivo .xml
$VarXML->save($SendaCFDI."RespServ_".$NoFac.".xml");
chmod($SendaCFDI."RespServ_".$NoFac.".xml", 0777);
$NomArchXML = "CFDI_".$fact_serie.str_pad($fact_folio, 6, "0", STR_PAD_LEFT)."_CP.xml";
$NomArchPDF = "CFDI_".$fact_serie.str_pad($fact_folio, 6, "0", STR_PAD_LEFT)."_CP.pdf";
$xmlt = new DOMDocument();
$xmlt->loadXML($RespServ);
$xmlt->save($SendaCFDI.$NomArchXML);
chmod($SendaCFDI.$NomArchXML, 0777);
#== 12.7 Procesos para extraer datos del Timbre Fiscal del CFDI =========
$docXML = new DOMDocument();
//$docXML->load($SendaCFDI."Fact_CFDI_".$NoFac.".xml");
$docXML->load($SendaCFDI.$NomArchXML);
$comprobante = $docXML->getElementsByTagName("TimbreFiscalDigital");
#== 12.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');
$tim_RfcPac = $timFis->getAttribute('RfcProvCertif');
}
#== 12.9 Se crea el archivo .PNG con codigo bidimensional =================================
$filename = "archs_graf/Img_".$tim_uuid.".png";
### 13. CREACION DE PDF Y ENVIO DE CORREO CON XML Y PDF ###########################
# 13.1 Creación del Archivo PDF
//$url = 'http://64.235.39.50/aptusCFDIRF/wsComPagoPDF_VP_v33.php?NomArchXML='.$NomArchXML.'&NomArchPDF='.$NomArchPDF;
if($TipPDFGen == 1)
{
$url = 'https://aptuslegal.app/aptusCFDIRF/'.$FormatoPDF.'.php?NomArchXML='.$NomArchXML.'&NomArchPDF='.$NomArchPDF.'&pDirRecep='.$sDireRecep;
}
else
{
$url = 'https://aptuslegal.app/aptusCFDIRF/'.$FormatoPDF.'.php?NomArchXML='.$NomArchXML.'&NomArchPDF='.$NomArchPDF;
}
$objCurl = curl_init();
curl_setopt($objCurl, CURLOPT_URL, $url);
curl_setopt($objCurl, CURLOPT_HEADER, 0);
curl_setopt($objCurl, CURLOPT_RETURNTRANSFER, true);
curl_exec($objCurl);
curl_close($objCurl);
# 13.3 Envio del Archivos a Invoice de Zoho Creator
# Primero el PDF
$file_name_with_full_path = '/var/www/html/aptusCFDIRF/archs_cfdi/'.$NomArchPDF;
//$request_url = 'https://creator.zoho.com/api/xml/fileupload/scope=creatorapi';
# Actualización a API V2 y OAuth JFA y FFR 2021-06-18
$request_url = 'https://creator.zoho.com/api/v2/'.$appOwner.'/'.$applnkname.'/report/CFDI_Pago_v33_Borradores/'.$bRecId.'/File_CFDI_PDF/upload';
if (function_exists('curl_file_create')) { // php 5.6+
$cFile = curl_file_create($file_name_with_full_path);
}
else
{
$cFile = '@' . realpath($file_name_with_full_path);
}
$post = array(
'file'=> $cFile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
#JFA: Cambiamos el método de Autenticación a OAuth
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Zoho-oauthtoken ' . $access_token));
$r = curl_exec($ch);
curl_close ($ch);
# Segundo el XML
$file_name_with_full_path = '/var/www/html/aptusCFDIRF/archs_cfdi/'.$NomArchXML;
# Actualización a API V2 y OAuth JFA y FFR 2021-06-18
$request_url = 'https://creator.zoho.com/api/v2/'.$appOwner.'/'.$applnkname.'/report/CFDI_Pago_v33_Borradores/'.$bRecId.'/File_CFDI_XML/upload';
if (function_exists('curl_file_create')) { // php 5.6+
$cFile = curl_file_create($file_name_with_full_path);
}
else
{
$cFile = '@' . realpath($file_name_with_full_path);
}
$post = array(
'file'=> $cFile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
#JFA: Cambiamos el método de Autenticación a OAuth
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Zoho-oauthtoken ' . $access_token));
$r = curl_exec($ch);
curl_close ($ch);
if ($paymentID != "")
{
# 13.4 Envio del Archivos a Invoice de Zoho Books
# Primero actualizamos el access_token de Books
#== Datos y Variables para OAuth Token
$boa_ClientId = $abdDatGen["B_OAuth_client_id"];
$boa_ClientSecret = $abdDatGen["B_OAuth_client_secret"];
$boa_RefreshToken = $abdDatGen["B_OAuth_refresh_token"];
$boa_GrantType = $abdDatGen["B_OAuth_grant_type"];
$boa_RedirectUri = $abdDatGen["B_OAuth_redirect_uri"];
$boa_AuthUrl = "https://accounts.zoho.com/oauth/v2/token";
#----------------------------------------------------------------
# JFA: 2021-06-12
# Obtenemos el access_token
#----------------------------------------------------------------
// $Params = array(
// "refresh_token" => $boa_RefreshToken,
// "client_id" => $boa_ClientId,
// "client_secret" => $boa_ClientSecret,
// "redirect_uri" => $boa_RedirectUri,
// "grant_type" => $boa_GrantType
// );
// $curl = curl_init();
// curl_setopt($curl, CURLOPT_URL, $boa_AuthUrl);
// curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
// curl_setopt($curl, CURLOPT_POSTFIELDS, $Params);
// curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
// $response = curl_exec($curl);
// $array = json_decode($response);
// $boa_access_token = $array->access_token;
$boa_access_token = oauth($appOwner, 'ZBooks', $boa_RefreshToken, $boa_ClientId, $boa_ClientSecret, $boa_RedirectUri, $boa_GrantType, $boa_AuthUrl);
//echo $access_token;
# Primero el PDF
$file_name_with_full_path = '/var/www/html/aptusCFDIRF/archs_cfdi/'.$NomArchPDF;
$request_url = 'https://www.zohoapis.com/books/v3/customerpayments/'.$paymentID.'/attachment';
if (function_exists('curl_file_create')) { // php 5.6+
$cFile = curl_file_create($file_name_with_full_path);
}
else
{
$cFile = '@' . realpath($file_name_with_full_path);
}
$post = array(
// 'authtoken' => $authtoken_ZB,
'organization_id' => $organi_id_ZB,
'can_send_in_mail' => 'true',
'attachment'=> $cFile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
#JFA: Cambiamos el método de Autenticación a OAuth
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Zoho-oauthtoken ' . $boa_access_token));
$r = curl_exec($ch);
curl_close ($ch);
$ra = json_decode($r);
$resultPDF = $ra->code.' - '.$ra->message;
# Segundo el XML
$file_name_with_full_path = '/var/www/html/aptusCFDIRF/archs_cfdi/'.$NomArchXML;
$request_url = 'https://www.zohoapis.com/books/v3/customerpayments/'.$paymentID.'/attachment';
if (function_exists('curl_file_create')) { // php 5.6+
$cFile = curl_file_create($file_name_with_full_path);
}
else
{
$cFile = '@' . realpath($file_name_with_full_path);
}
$post = array(
// 'authtoken' => $authtoken_ZB,
'organization_id' => $organi_id_ZB,
'can_send_in_mail' => 'true',
'attachment'=> $cFile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
#JFA: Cambiamos el método de Autenticación a OAuth
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Zoho-oauthtoken ' . $boa_access_token));
$r = curl_exec($ch);
curl_close ($ch);
$ra = json_decode($r);
$resultXML = $ra->code.' - '.$ra->message;
}
#== Se elimina los archivos de trabajo
unlink($SendaCFDI."PreCFDI-33_".$NoFac.".xml");
unlink($SendaCFDI."RespServ_".$NoFac.".xml");
unlink($filename);
$j_array = array('code' => "200", 'message' => "Proceso de creacion de CFDI fue exitoso", 'version_timbre' => $version_timbre,
'cert_SAT' => $cert_SAT, 'tim_fecha' => $tim_fecha, 'tim_uuid' => $tim_uuid, 'tim_RfcPac' => $tim_RfcPac,
'sello_SAT' => $sello_SAT, 'sello_CFD' => $sello_CFD);
$Resultado = json_encode($j_array);
echo $Resultado;
return;
### 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, 'xmlns:pago10'=>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ónes que da formato al "Importe total" como lo requiere el SAT para ser integrado al código QR.
function ProcesImpTot($ImpTot){
$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;
}