Conexion PHP y SAP

Yo de Php muy poco, pero … leíste esto?


¿Capaz ahí salga como conectan?

Saludos a tod@s en el foro!

Amigo @Alvan1 te recomiendo que en lugar de utilizar la libreria php-saprfc, desarrolles un webservice en java utilizando SAP Java Connector 3.0 (JCo3) para la interface con R/3. Este conector JCo3 es provisto y recomendado por la mismisima SAP AG. Este esquema de conectividad que te planteo esta mas que probado, yo particularmente lo he implementado en n aplicativos que estan en productivo actualmente.

En su momento, hace 2 años aproximadamente, se trato de utilizar el conector php-saprfc-1.4.1 en un proyecto y fue desechado casi de inmediato por los problemas de configuracion e inestabilidad de conexión que presentaba, investigamos mas a fondo y nos dimos cuenta que la ultima actualizacion de la libreria habia sido en el año 2011, una libreria con 3 años sin actualizaciones es practicamente un proyecto que se dejo abandonado.

Ahora que @SidV coloco el link en git de la libreria es que me doy cuenta que al parecer retomaron el proyecto. Me voy a tomar como tarea probarla nuevamente a ver que tal.

Prueba la solución que te propuse, te garantizo que funciona bien. Ademas por tratarse de un webservice, vas a crear una solución mas abierta, basada en estandares y reutilizable desde cualquier plataforma.

Hasta te puedes ganar un punto extra por su implementación :thumbsup:

3 Me gusta

Hola @Alvan1 yo realice la conexión de PHP con SAP, te comento lo que necesitas es lo siguiente:
Nota: toma encuenta si tu server es a 32 o 64

  1. El archivo Librfc

  2. php_saprfc_php5.6_ts.dll en tu caso por la version de tu PHP.

  3. Abrir el archivo php.ini (que se encuentra en c:\xampp\php\php.ini)y agregar el dll dentro del archivo donde se encuentran las “extension= …” ejemplo:
    extension=php_saprfc_php5.6_ts.dll

  4. Debes de crear una funcion RFC en sap, con tus tablas o estructuras correspondientes.

  5. Crear una “Funcion en PHP” donde hagas la conexión a SAP (tomando en cuenta el envio de parametros a tu función y elementos entrantes a la misma).

  6. El archivo que generes PHP se apoya de “otro” PHP el cual contiene librerias para la conexión.

En mi caso, lo implementé en una INTRANET usando XAMPP, cualquier duda o comentario hazlo saber o comunicate conmigo.

Saludos y suerte.

3 Me gusta

Este sería el código del archivo PHP donde llamarias a la funcion RFC de SAP …en mi caso:

<html>
<body>
<h1>CONEXIÓN SAP_PHP</h1>
<?PHP

    // aqui en esta parte incluyes el archivo donde tendras las librerias que pondré más aabajo
    require_once("saprfc.php");
 
    // Create saprfc-instance
    $sap = new saprfc(array(
            "logindata"=>array(
            "ASHOST"=>"10.10.10.10"		// application server
            ,"SYSNR"=>"Numero de sistema"	/ system number
            ,"CLIENT"=>"Cliente"			// client
            ,"USER"=>"USUARIO DE ACCESO A SAP"			// user
            ,"PASSWD"=>"Password"		// password
            )
            ,"show_errors"=>false			// let class printout errors
            ,"debug"=>false)) ; 				// detailed debugging information
 
    // Call-Function
    $result=$sap->callFunction("NOMBRE_DE_TU_FUNCION",
            array(	array("IMPORT","EL_NOMBRE_DEL_IMPORT_DE_TU_FUNCION","*"),
            array("TABLE","TABLE_DE_TU_FUNCION",array())
            ));
 
    // Si se realizo el llamado a la funcion correctamente
    if ($sap->getStatus() == SAPRFC_OK) 
    {
        // Entonces imprimes tus resultados....
        ?><table>
            <tr>
            <td>Nombre</td>
            <td>Numero De Usuario</td>
            </tr>

     <?PHP
 
        foreach ($result["USER_DISPLAY_TAB"] as $user) 
        	{
            echo "<tr>
            	  <td>", $user["SAPNAM"],"</td><td>",$user["USRNO"],"</td> //Elementos o Campos de tu estructura o tabla
            	  </tr>";
        	}
 
        ?></table><?PHP
    } 
		    else 
		    	{
		        // Si no se realizo la conexión a la funcion RFC
		        $sap->printStatus();
		        // Imprimes el mensaje de error
		        // 		$sap->getStatusText() or $sap->getStatusTextLong()
		    	}
 
    // Logoff/Cerrar SAP RFC
    $sap->logoff();
?>
</body>
</html>

Y este seria tu archivo saprfc.php donde contendrías las librerias…y lo incluirás en el codigo anterior que te pase…

<?PHP


// For easy checking of BAPI-type values
if (!defined("SAPRFC_OK")) define("SAPRFC_OK",0);
if (!defined("SAPRFC_ERROR")) define("SAPRFC_ERROR",1);
if (!defined("SAPRFC_APPL_ERROR")) define ("SAPRFC_APPL_ERROR",2);


class saprfc {

	var $logindata;
	var $rfc_conn;
	var $func_id;
	var $show_status_flag;
	var $check_bapi_errors;
	var $status;
	var $status_infos;
	var $debug;
	var $call_function_result;

	function saprfc($config=array()) {
		$this->rfc_conn=false;
		$this->func_id=false;
		$this->show_status_flag=isset($config["show_errors"]) ? $config["show_errors"] : true;
		$this->check_bapi_errors=isset($config["check_bapi_errors"]) ? $config["check_bapi_errors"] : false;
		$this->status="";
		$this->status_infos="";
		$this->debug=isset($config["debug"]) ? $config["debug"] : false;
		$this->logindata=isset($config["logindata"])?$config["logindata"]:array();
		$this->call_function_result=false; // Result of the last executed sapaccess-call_function()
	}
	
	function setLoginData($logindata) {
		$this->logindata=$logindata;
	}

	// TODO: currently only login with logindata allowed
	// that means you have to set logindata for the class on creation
	// maybe we can use setcookie ("SAPRFC_LOGON", urlencode(serialize($this->logindata)),time()+7200);	
	function login() {
	   	if (!$this->rfc_conn)
	   	{
		   	$this->rfc_conn=@saprfc_open($this->logindata);
			if (!$this->rfc_conn) {
				return $this->setStatus(SAPRFC_ERROR,"saprfc::login()\nOpen RFC connection with saprfc_open() failed with error:\n".@saprfc_error());
			}
		}
		return SAPRFC_OK;
	}

	// Close RFC_Connection	
	function logoff() {
	   	if ($this->rfc_conn)
	   	{
			@saprfc_close($this->rfc_conn);
		}
	}

	// set Status and optionally show Errors
	function setStatus($status,$status_infos) {
		$this->status=$status;
		$this->status_infos=$status_infos;
		if ($this->show_status_flag &&
			$this->status!=SAPRFC_OK ) {
			$this->printStatus();
		}
		return $this->status;
	}		
	
	// Checks if last Call succeded
	function getStatus() {
		return $this->status;
	}
	
	// Returns actual Status/Error
	function getStatusText() {
		$statustext="";
		switch ($this->status) {
			case SAPRFC_OK:
				$statustext=$this->status_infos;
				break;
			case SAPRFC_APPL_ERROR:
				$statustext=$this->status_infos["TYPE"]." ".$this->status_infos["ID"]."-".$this->status_infos["NUMBER"].": ".$this->status_infos["MESSAGE"];
				break;
			case SAPRFC_ERROR:
				$statustext=$this->status_infos;
				break;
		}
		return $statustext;
	}

	// Returns actual Status/Error
	function getStatusTextLong() {
		$statustext="";
		switch ($this->status) {
			case SAPRFC_OK:
				$statustext.="<br><font size=4 color=green><pre>";
				$statustext.="No errors detected.";
				$statustext.="</font><br><font size=3 color=green><pre>";
				$statustext.="<br><b>".$this->getStatusText()."</b>";
				$statustext.="</pre></font>";
				break;
			case SAPRFC_APPL_ERROR:
				$statustext.="<br><font size=4 color=red><pre>";
				$statustext.="Application-Errors found during BAPI-Calls:";
				$statustext.="</font><br><font size=3 color=red><pre>";
				$statustext.="<br><b>".$this->getStatusText()."</b>";
				$statustext.="</pre></font>";
				break;
			case SAPRFC_ERROR:
				$statustext.="<br><font size=4 color=red><pre>";
				$statustext.="Errors found during saprfc-Calls:";
				$statustext.="</font><br><font size=3 color=red><pre>";
				$statustext.="<br><b>".$this->getStatusText()."</b>";
				$statustext.="</pre></font>";
				break;
		}
		return $statustext;
	}

	function printStatus() {
		echo $this->getStatusTextLong();
	}		
	
	// Call RFC-Function in SAP		
	function callFunction($func_name="",$parameters) {
		/* typical call:
			$result=$saprfc->call_function("RFC_SYSTEM_INFO",
									array(	array("EXPORT","SYSTEM","MBS")
											array("IMPORT","CODEPAGE")
											array("IMPORT","DBNAME")
											array("TABLE","APPLLIST",array())
									)
								);
		*/
		
		// Initialize Variables
		$result_data=array();
		$this->call_function_result=false;
						
		// Check SAPRFC-Installation
		if (! extension_loaded ("saprfc")) {
			return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction()\n SAPRFC-Extension.dll not loaded.");
		}
		
		// Validate given data
		if (empty($func_name)) {
			return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction():\n No Function-Name given");
		}
		
		// Move Parameters to local Arrays
		$func_params_import=array();		
		$func_params_tables=array();
		$func_params_export=array();
		foreach ($parameters as $key => $param) {
			$type=$param[0];
			$name=$param[1];
			$value=isset($param[2])?$param[2]:"";
			switch ($type) {
				case "IMPORT":
					$func_params_import[$name]=$value;
					break;
				case "EXPORT":
					$func_params_export[$name]="";
					break;
				case "TABLE":
					$func_params_tables[$name]=$value;
					if (!is_array($value)) {
						return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction()\n Wrong Parameter-Value for Table-Parameter ".$name.". We expected an Array.");
					}
					break;
				default:
					return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction()\n Wrong Parameter-Type '".$type."'. Must be IMPORT, EXPORT or TABLE.");
			}
		}
		
		// Do Login (only done in method login(), if necessary)	
		if ($this->login()==SAPRFC_ERROR) {
			return $this->getStatus();
		}
		
		// Discover Function in SAP
		$this->func_id=@saprfc_function_discover($this->rfc_conn,$func_name);
		if (!$this->func_id) {
			return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction()\n Function module '".$func_name."' seems not to exist. function saprfc_function_discover() failed.");
		}

		// Set Import-Parameters		
		foreach ($func_params_import as $name => $value) {
			$rc=@saprfc_import($this->func_id,$name,$value);
			if (empty($rc)) {
				return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction('".$func_name."')\n Import-Parameter=".$name. " could not be set. (Does it exist?)");
			}
		}
		// Set Table-Parameters	(importing-values)
		foreach ($func_params_tables as $name => $value) {
			$rc=@saprfc_table_init($this->func_id,$name);
			if (empty($rc)) {
				return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction('".$func_name."')\n Table-Parameter=".$name. " could not be set. (Does it exist?)");
			}
			foreach ($value as $key => $data) {
				@saprfc_table_append($this->func_id,$name,$data);
			}
		}

		// Execute Function
		$result = @saprfc_call_and_receive ($this->func_id);
		if ($result != SAPRFC_OK)
		{
			if ($result == SAPRFC_EXCEPTION ) {
				return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction('".$func_name."')\n saprfc_call_and_receive(): Exception raised: ".@saprfc_exception($this->func_id));
			} else {
				return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction('".$func_name."')\n saprfc_call_and_receive(): Call error: ".@saprfc_error($this->func_id));
			}
		}
	   
		// Get Exporting-Parameters
		foreach ($func_params_export as $name =>$value) {
			$rc=@saprfc_export($this->func_id,$name);
//			if (empty($rc)) { // llaegner removed (Reason: when export returns the -good- value "0", then empty also evaluates to true (thanks Alexander Gouriev)
			if (!isset($rc)) {
				return $this->setStatus(SAPRFC_ERROR,"saprfc::callFunction('".$func_name."')\n Export-Parameter=".$name. " could not be set (Does it exist?)".@saprfc_error($this->func_id));
			} else {
				$result_data[$name]=$rc;
			}
		}

		// Get Table-Parameters
		foreach ($func_params_tables as $name => $content) {
			// Ausgabe-Tabelle initialisieren
			$result_data[$name]=array(); 
			$rows=@saprfc_table_rows($this->func_id,$name);
			for ($i=1; $i<=$rows; $i++)
			{
				$result_data[$name][$i]=@saprfc_table_read ($this->func_id,$name,$i);
			}
		}

		// Save function-call result for later analysis
		$this->call_function_result=$result_data;
		
		// Echo Debug-Information, if flagged
		if ($this->debug)
			@saprfc_function_debug_info($this->func_id);
			
		// Falls es ein BAPI-Aufruf ist, Fehler raussuchen
		if ($this->check_bapi_errors) {
			$bapi_return=@saprfc_export($this->func_id,"RETURN");
			if (isset($bapi_return) && 
					is_array($bapi_return) && 
					isset($bapi_return["MESSAGE"]) && 
					$bapi_return["NUMBER"] != 0) {
					
				// FINISH FUNCTION-CALL
				$this->setStatus(SAPRFC_APPL_ERROR,$bapi_return);
				return $result_data;	
			}
		}
		// Close Function-Execution and free results removed because it sometimes stops completly executing PHP!!
		//@saprfc_function_free($this->func_id);
		
		// FINISH FUNCTION-CALL
		$this->setStatus(SAPRFC_OK,"call function '".$func_name."' successfull.");
		return $result_data;	
	}
	
}

?>
2 Me gusta

Si van a compartir muchas lineas de código, me parece mejor que usen https://gist.github.com/
Donde podrían hasta “folkear-se” entre ustedes :slight_smile: y pegan aquí directamente la URL del GIST, y queda compartida en el tema :thumbsup:


Volviendo al tema.
No les sirve esto?

2 Me gusta

Gracias…haré uso de ello¡¡¡ saludos

Una disculpa de antemano por haberme ausentado de este tópico fue por razones laborales, les comento aun sigo sin poder realizar dicha conexión :frowning: pero el fin me dare la tarea de crear una maquina virtual para ahí montarle lo necesario en SO Linux con estas características kernel 2.6.25.18-0.2-pae i686.

Ya que al parecer todo esta mas orientada a hacerlo dentro de ese sistema. Agradecerles a todos por sus comentarios.

Gracias @marciano por lo que comentas, aquí el tema es que el sistema vive sea creo y ya está implementado en PHP y ahora lo que quieren hacer es darle ese plus con la interconexión a SAP, seria volver a reprogramar todo a JAVA EE y montar los JCO que como bien dices es lo mas idóneo y por WS pues que te digo así lo trabajamos en su momento en su momento en el INFONAVIT pero este cliente es nuevo y se aferró a hacer todo desde PHP y ahora si que al cliente lo que pida, pero de todos modos muchas gracias.

@iespino gracias por tus comentarios en la VM que cree me apegare a usar el XAMPP, nadamas tengo una duda en que S.O. montaste el XAMPP ?

E igualmente @Shadowdancer y @SidV como siempre respondiendo, sus guías me va a ayudar a terminar esta encrucijada que al final tiene que salir si o si

Muchas muchas gracias.
Saludos.

3 Me gusta

Y has investigado si SAP comparte Web-Services para consumirlos?. Yo no se mucho del tema pero aqui donde laboro lo poco que conozco es que SAP lo único que entrega son archivos de texto, supongo usando ABAP para alimentar otros sistemas…

El sistema operativo donde monte el XAMPP fue Windows Server 2008

@Alvan1 Lograste resolver este problema?

No estimado con la librería nunca se pudo, lo que se hizo puros consumos de wsdl para la extracción de información. Pero pues solo así se pudo

3 Me gusta

Lo que pasa es que yo lo logré hacer en 2 servidores con windows server 2008, y estoy tratando de implementar en un windows server 2016 y es en el que me da ese error, no se si sea el lenguaje. Ya cambie el SAP Logon, y tampoco. :slight_smile: Alguien del grupo @abapers sabe sobre el tema?

Buen día, tengo varios semanas tratando de instalar el php_saprfc_php5.6_ts en windows 2008 x64 y no se puede, alguien pudo con esto?, seguí todos los pasos y nada

te sale algún mensaje de error? tienes que buscar el dll correcto para tu versión de apache. que versión tienes?

Version de Apache/2.4.26 (Win32) OpenSSL/1.0.2l PHP/5.6.31

Puedes intentar con el php_saprfc_PHP5.6_x86_ts.dll para ver si te funciona, o que error te manda? crea un archivo php:

<?php
phpinfo();
?>

Para verificar que este activo el dll de saprfc.

@Alvan1 esto hice yo hace algunos meses, lo estoy usando full

Hoy por razones de compatibilidad con otros sistemas tuve que deupgradear a Xampp 5.6 e hice lo mismo y funcionó perfecto. Esto aplica a HANA, pero también se puede hacer parecido con SQL Server.

Saludos,
David

1 me gusta

Buen día.

Reactivando nuevamente el tema de la conexión con PHP y SAP, Les comento que estoy tratando de conectar php7 con SAP, y me encontré una guía paso a paso la cual he seguido sin obtener éxito, continuo con mis pruebas, si alguien logra hacerlo funcionar favor de compartir.

Les comento que tengo SAP LOGO 720

1. XAMPP Versión 7.2.4-0
2. PHP Version 7.2.4
3. Apache/2.4.33 (Win32)

h_tps://gkralik.github.io/php7-sapnwrfc/installation.html

Bueno acá tu tema es:

  • ¿Que tipo de BD usa SAP LOGO? De ser SQL no deberías tener problema más que la configuración de tu ODBC
    Para esto:
    h_tps://docs.microsoft.com/en-us/sql/connect/php/loading-the-php-sql-driver?view=sql-server-2017
    h_tps://social.msdn.microsoft.com/Forums/es-ES/4ca96d4c-c706-4380-8929-7154b1889420/error-al-configurar-php-7-para-conexion-con-sql-server-2008?forum=sqlserveres

Después cheque el Manual que hice y veas tu configuración de php.ini es super importante que puedas configurar bien la extensión del odbc o del pdo_odbc

Estoy preparando un pequeño tutorial para lograr conexiones PHP con SQL Server…

Saludos,
David

PD: Yo no pude usar ese manual porque no tengo acceso al Centro de Software de SAP.

Otro buen Manual:

h_tp://www.ingdiaz.org/conectarse-microsoft-sql-server-desde-php-7-drivers-php-sql-server/