Nueva pregunta

Pregunta:

Fecha: 07-01-2019 09:51:12 (En Español)

Problema con clase para Factura AFIP (no veo el error)[No resuelta]

Tengo el siguiente codigo en PHP y me da error en la construccion del objeto, entonces no puedo obtener el CAE por que hay algun error, pero no me lo dice:

<?php
/*
Ejemplo en codigo php para conectarse y obtener cae mediante uso de web service Afip en modo homologacion (testing).
Este programa se entrega ABSOLUTAMENTE SIN GARANTIA.
El siguiente codigo fuente es una adaptacion de ejemplos encontrados en la web.
2015 Pablo <pablin.php@gmail.com>
*/
class WSFEV1 {
	const CUIT 	= 20357161178;                 		# CUIT del emisor de las facturas. Solo numeros sin comillas.

	const TA 	= "c://xampp/htdocs/gestionweb/includes/php/TAFE.xml";        				# Archivo con el Token y Sign
	//https://wswhomo.afip.gov.ar/wsfev1/service.asmx // Funciones
	//https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL // para obtener WSDL
	const WSDL = "views/modules/facta/wsfev1.wsdl";                   	# The WSDL corresponding to WSFEV1	
	const LOG_XMLS = true;                     		# For debugging purposes
	const WSFEURL = "https://wswhomo.afip.gov.ar/wsfev1/service.asmx"; // homologacion wsfev1 (testing)
	//const WSFEURL = "?????????/wsfev1/service.asmx"; // produccion  

	/*
	* path real del directorio principal terminado en /
	*/
	//private $path = '/www/afipfev1/'; //caso linux
	private $path = 'c:/xampp/htdocs/gestionweb/'; //caso windows (no importa que las barras esten como en linux)
	
	/*
	* manejo de errores
	*/
	public $error = '';
	public $ObsCode = '';
	public $ObsMsg = '';
	public $Code = '';
	public $Msg = '';
	/**
	* Cliente SOAP
	*/
	private $client;
  
	/*
	* objeto que va a contener el xml de TA
	*/
	private $TA;
  
	/*
	* Constructor
	*/
	public function __construct()
	{
    
    // seteos en php
    ini_set("soap.wsdl_cache_enabled", "0");    
    
    // validar archivos necesarios
    if (!file_exists(WSDL)) $this->error .= " Failed to open ".self::WSDL;
    
    if(!empty($this->error)) {
		throw new Exception('WSFE class. Faltan archivos necesarios para el funcionamiento');
    }        
	
    $this->client = new SoapClient($this->path.self::WSDL, array( 
				'soap_version' => SOAP_1_2,
				'location'     => self::WSFEURL,
				'exceptions'   => 0,
				'trace'        => 1)
    ); 
	}
  
	/*
	* Chequea los errores en la operacion, si encuentra algun error falta lanza una exepcion
	* si encuentra un error no fatal, loguea lo que paso en $this->error
	*/
	private function _checkErrors($results, $method)
	{
    if (self::LOG_XMLS) {
		file_put_contents("request-".$method.".xml",$this->client->__getLastRequest());
		file_put_contents("response-".$method.".xml",$this->client->__getLastResponse());
    }
    
    if (is_soap_fault($results)) {
		throw new Exception('WSFE class. FaultString: ' . $results->faultcode.' '.$results->faultstring);
    }
    
    if ($method == 'FEDummy') {return;}
    
    $XXX=$method.'Result';
	if ($results->$XXX->Errors->Err->Code != 0) {
		$this->error = "Method=$method errcode=".$results->$XXX->Errors->Err->Code." errmsg=".$results->$XXX->Errors->Err->Msg;
    }
    	
	
	//asigna error a variable
	if ($method == 'FECAESolicitar') {
		if ($results->$XXX->FeDetResp->FECAEDetResponse->Observaciones->Obs->Code){	
			$this->ObsCode = $results->$XXX->FeDetResp->FECAEDetResponse->Observaciones->Obs->Code;
			$this->ObsMsg = $results->$XXX->FeDetResp->FECAEDetResponse->Observaciones->Obs->Msg;
		}
		
		//if ($results->$XXX->FeDetResp->FECAEDetResponse->Observaciones->Obs[0]->Code){	
		//	$this->ObsCode = $results->$XXX->FeDetResp->FECAEDetResponse->Observaciones->Obs[0]->Code;
		//	$this->ObsMsg = $results->$XXX->FeDetResp->FECAEDetResponse->Observaciones->Obs[0]->Msg;
		//}		
	}
	$this->Code = $results->$XXX->Errors->Err->Code;
    $this->Msg = $results->$XXX->Errors->Err->Msg;	
	//fin asigna error a variable
		
	return $results->$XXX->Errors->Err->Code != 0 ? true : false;
	}

	/**
	* Abre el archivo de TA xml,
	* si hay algun problema devuelve false
	*/
	public function openTA()
	{
	$this->TA = simplexml_load_file(self::TA);

	return $this->TA == false ? false : true;
	}
  
	/*
	* Retorna el ultimo número autorizado.
	*/ 
	public function FECompUltimoAutorizado($ptovta, $tipo_cbte)
	{
	$results = $this->client->FECompUltimoAutorizado(
		array('Auth'=>array('Token' => $this->TA->credentials->token,
							'Sign' => $this->TA->credentials->sign,
							'Cuit' => self::CUIT),
			'PtoVta' => $ptovta,
			'CbteTipo' => $tipo_cbte));
			
    $e = $this->_checkErrors($results, 'FECompUltimoAutorizado');
	
    return $e == false ? $results->FECompUltimoAutorizadoResult->CbteNro : false;
	} //end function FECompUltimoAutorizado
  
	/*
	* Retorna el ultimo comprobante autorizado para el tipo de comprobante /cuit / punto de venta ingresado.
	*/ 
	public function recuperaLastCMP ($ptovta, $tipo_cbte)
	{
	$results = $this->client->FERecuperaLastCMPRequest(
		array('argAuth' =>  array('Token' => $this->TA->credentials->token,
								'Sign' => $this->TA->credentials->sign,
								'cuit' => self::CUIT),
			'argTCMP' => array('PtoVta' => $ptovta,
								'TipoCbte' => $tipo_cbte)));
	$e = $this->_checkErrors($results, 'FERecuperaLastCMPRequest');
	
	return $e == false ? $results->FERecuperaLastCMPRequestResult->cbte_nro : false;
	} //end function recuperaLastCMP

	
	/*
	* Solicitud CAE y fecha de vencimiento 
	*/	
	public function FECAESolicitar($cbte, $ptovta, $regfe, $regfetrib, $regfeiva)
	{
	$params = array( 
		'Auth' => 
		array( 'Token' => $this->TA->credentials->token,
				'Sign' => $this->TA->credentials->sign,
				'Cuit' => self::CUIT ), 
		'FeCAEReq' => 
		array( 'FeCabReq' => 
			array( 'CantReg' => 1,
					'PtoVta' => $ptovta,
					'CbteTipo' => $regfe['CbteTipo'] ),
		'FeDetReq' => 
		array( 'FECAEDetRequest' => 
			array( 'Concepto' => $regfe['Concepto'],
					'DocTipo' => $regfe['DocTipo'],
					'DocNro' => $regfe['DocNro'],
					'CbteDesde' => $cbte,
					'CbteHasta' => $cbte,
					'CbteFch' => $regfe['CbteFch'],
					'ImpNeto' => $regfe['ImpNeto'],
					'ImpTotConc' => $regfe['ImpTotConc'], 
					'ImpIVA' => $regfe['ImpIVA'],
					'ImpTrib' => $regfe['ImpTrib'],
					'ImpOpEx' => $regfe['ImpOpEx'],
					'ImpTotal' => $regfe['ImpTotal'], 
					'FchServDesde' => $regfe['FchServDesde'], //null
					'FchServHasta' => $regfe['FchServHasta'], //null
					'FchVtoPago' => $regfe['FchVtoPago'], //null
					'MonId' => $regfe['MonId'], //PES 
					'MonCotiz' => $regfe['MonCotiz'], //1 
					'Tributos' => 
						array( 'Tributo' => 
							array ( 'Id' =>  $regfetrib['Id'], 
									'Desc' => $regfetrib['Desc'],
									'BaseImp' => $regfetrib['BaseImp'], 
									'Alic' => $regfetrib['Alic'], 
									'Importe' => $regfetrib['Importe'] ),
							), 
					'Iva' => 
						array ( 'AlicIva' => 
							array ( 'Id' => $regfeiva['Id'], 
									'BaseImp' => $regfeiva['BaseImp'], 
									'Importe' => $regfeiva['Importe'] ),
							), 
					), 
			), 
		), 
	);
	
	$results = $this->client->FECAESolicitar($params);

    $e = $this->_checkErrors($results, 'FECAESolicitar');
	
	//asigno respuesta 
	$resp_cae = $results->FECAESolicitarResult->FeDetResp->FECAEDetResponse->CAE;
	$resp_caefvto = $results->FECAESolicitarResult->FeDetResp->FECAEDetResponse->CAEFchVto;

	return $e == false ? Array( 'cae' => $resp_cae, 'fecha_vencimiento' => $resp_caefvto ): false;
	} //end function FECAESolicitar
	
} // class

?>


El caso es que obtengo este error:
2019-01-716:42:55string(18) "2019-01-0722:50:23"
Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 85

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 85

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 85

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 102

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 102

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 102

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 103

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 103

Notice: Trying to get property 'Msg' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 103

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 106

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 106

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 106

FECompUltimoAutorizado: 30

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 85

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 85

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 85

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 92

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 102

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 102

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 102

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 103

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 103

Notice: Trying to get property 'Msg' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 103

Notice: Undefined property: stdClass::$Errors in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 106

Notice: Trying to get property 'Err' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 106

Notice: Trying to get property 'Code' of non-object in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 106

Error al obtener CAE
Code:
Msg:
Obs:
Msg:

Error al obtener CAE

Nro: 31
Cae:
Fecha Vto:


Osea hasta el ultimo comprobante llega, lo obtiene pero quisiera saber porque no muestra el codigo de error.
Podria ser el tipo y numero de comprobante? quiero hacer factura c a consumidor final, seri 11 y 1?
Etiquetas: PHP Votos: 1 - Respuestas: 3 - Vistas: 10 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 08-01-2019 03:43:55 Bueno, encontre que el error aparece en el archivo response xml de la solicitud. y obtengo:

    en el xml tengo este error:
    <Observaciones><Obs><Code>10071</Code><Msg>Para comprobantes tipo C el objeto IVA no debe informarse.</Msg></Obs>
    pero no se como dejar vacio el importe de iva.


    Pero si negreo la linea, osea saco la variable del array obtengo:

    Fatal error: SOAP-ERROR: Encoding: object has no 'ImpIVA' property in C:\xampp\htdocs\gestionweb\views\modules\facta\wsfev1.class.php on line 207.
      Votos: 0 - Link respuesta
     
  • Fecha: 08-01-2019 12:48:20 Hola Giuliano,
    Tienes un problema con la manera en que manejas tus respuestas.

    En general tienes varias lineas de codigo que son llamadas a la propiedad de un objeto dentro de otro objeto que a su vez esta dentro de otro objeto y asi sucesivamente. Por ejemplo la linea que proporcionaste al inicio (85 y 102):

    $results->$XXX->Errors->Err->Code


    El problema es que si tu codigo corrio bien, sin errores, entonces la propiedad Errors sera un arreglo vacio. Entonces tu codigo esta mal porque estas asumiendo que Errors tiene una propiedad Err y eso es incorrecto. Lo que realmente debes hacer es validar que Errors este vacio.

    Esto a su vez implica que tienes que cambiar tu clase pues definiste la propiedad error como cadena de caracteres pero estaras recibiendo varios errores y tu logica para reportarlos no es correcta.

    Todo esta en el WSDL:

    <s:complexType name="ArrayOfErr">
        <s:sequence>
            <s:element minOccurs="0" maxOccurs="unbounded" name="Err" nillable="true" type="tns:Err"/>
        </s:sequence>
    </s:complexType>
    


    Te sugiero que hagas una clase por cada elemento del WSDL y utilices la opcion classMap de SOAP. Eso te facilitara muchisimo la interaccion con el servicio.

    Tu codigo tiene muchisimas deficiencias pero como prueba de concepto esta bien.

    Te recomiendo le apliques PSR y actualices la sintaxis a PHP 7.1 para que sea mas legible. Si puedes tambien ayudaria tener los bloques de documentacion completos.

    Saludos!
      Votos: 0 - Link respuesta
     
  • Fecha: 10-01-2019 00:54:54 Es que lo que tengo que hacer basicamente es leer el archivo XML que tiene el response como vos decis. Voy a buscar alguna manera de hacerlo y comento. Gracias   Votos: 0 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión