WebServices, SOAP
En el manual del desenvolupador hi ha un apartat que fa una introducció de com podem accedir al Sugar CRM a través dels Web Services.
SugarCRM proporciona una API de Web Services a través de la implementació del protocol SOAP que fa NuSOAP PHP. SOAP significa Simple Object Access Protocol. S'utilitza per fer Crides a Procediments Remots (RPC, Remote Procedure Calls) a través del protocol HTTP mitjançant missatges XML.
La API de SugarSoap està construïda utilitzant la llibreria NuSOAP que s'inclou en les tres versions de Sugar CRM. Es pot veure l'API a:
http://localhost/sugarcrm/soap.php
El fitxer SugarSoap WSDL (Web Services Description Language) es troba a:
http://localhost/sugarcrm/soap.php?wsdl
Gràcies als diversos toolkits disponibles, és fàcil fer efectiu l'ús dels SOAP Web Services des d'una varietat de llenguatges de programació, en particular amb Sugar i la seva ampla llista de serveis basats en SOAP que ofereix.
Per als següents exemples s'utilitza PHP juntament amb el toolkit NuSOAP. Evidentment ens podrem connectar al SugarCRM via SOAP i escriure les nostres pròpies aplicacions en Java, C++ o qualsevol altre llenguatge de programació amb capacitat SOAP.
Nota: el primer que hem de fer és assegurar-nos que el fitxer de variables config.php funciona correctament: http://localhost/sugarcrm/config.php
En la carpeta examples hi ha exemples de connexió:
El primer que passa quan executem SoapTest.php és un error:
http://localhost/sugarcrm/examples/SoapTest.php error: Not a valid entry point
Això es soluciona ficant define('sugarEntry', TRUE); a dalt de tot:
Your code is fine actually. When you include 'nusoap/nusoap.php' toward the top of your file, it's using the copy of nuSOAP found in Sugar (which has protections built in for entry points). You can either add this line to the top of your PHP file: PHP Code: define('sugarEntry', TRUE);
i ara ja funciona.
Un exemple mínim per connectar-se als Web Services de Sugar CRM:
fitxer echoprova.php
<?php define('sugarEntry', TRUE); require_once('../include/nusoap/nusoap.php'); $client = new nusoapclient('http://localhost/sugarcrm/soap.php'); $auth_array = array( 'user_auth' => array( 'user_name' => 'admin', 'password' => md5('****'), ) ); $login_results = $client->call('login',$auth_array); $session_id = $login_results['id']; $user_guid = $client->call('get_user_id',$session_id); printf("\n".$auth_array['user_auth']['user_name'].' has a GUID of ' . $user_guid . "\n\n"); ?>
Bàsicament ens connectem amb el login i pwd (substituir pel password correcte), fa un call i visualitzem el GUID del login amb què ens hem connectat.
L'exemple SoapTestPortal.php i SoapTestPortal2.php són més complets, però no funcionen perquè es necessita Sugar Portal i la versió Enterprise o Professional de Sugar
Contingut
Exemple2. Inserir un lead
inserir_lead.php (ha funcionat)
<?php define('sugarEntry', TRUE); //Use the NuSOAP files require_once('../include/nusoap/nusoap.php'); $soapclient = new nusoapclient('http://localhost/sugarcrm/soap.php?wsdl',true); $user_auth = array( 'user_auth' => array( 'user_name' => 'admin', 'password' => md5('****'), 'version' => '0.1' ), 'application_name' => 'soapleadcapture'); $result_array = $soapclient->call('login',$user_auth); $session_id = $result_array['id']; $user_guid = $soapclient->call('get_user_id',$session_id); // Up until now, we have not introduced anything new // The following lines will use the set_entry SOAP call to add // a Lead from a mixture of POST variables and hard coded // values, then assign to the authenticated Sugar user... /* $set_entry_params = array( 'session' => $session_id, 'module_name' => 'Leads', 'name_value_list'=>array( array('name'=>'first_name','value'=>$_POST['first_name']), array('name'=>'last_name','value'=>$_POST['last_name']), array('name'=>'status', 'value'=>'New'), array('name'=>'phone_work', 'value'=>$_POST['phone']), array('name'=>'phone_fax', 'value'=>$_POST['fax']), array('name'=>'account_name','value'=>$_POST['companyname']), array('name'=>'lead_source','value'=>'Web Site'), array('name'=>'description','value'=>$_POST['prod_desc']), array('name'=>'assigned_user_id', 'value'=>$user_guid))); */ $set_entry_params = array( 'session' => $session_id, 'module_name' => 'Leads', 'name_value_list'=>array( array('name'=>'first_name','value'=>'Pere'), array('name'=>'last_name','value'=>'Pruna'), array('name'=>'status', 'value'=>'New'), array('name'=>'phone_work', 'value'=>'659.00.61.56'), array('name'=>'phone_fax', 'value'=>'93.456.56.56'), array('name'=>'account_name','value'=>'Balmes SCCP'), array('name'=>'lead_source','value'=>'www.balmessccp.org'), array('name'=>'description','value'=>'la descripció del possible client'), array('name'=>'assigned_user_id', 'value'=>$user_guid))); $result = $soapclient->call('set_entry',$set_entry_params); // this redirects to a page specified in the previous page... //header("Location: " . $_POST['redirect']); ?>
On veig la llista de tots els camps que es poden omplir per a un lead? Doncs a /sugarcrm/modules/leads/metadata/detailedviewdefs.php.
Aquí puc veure que per exemple hi ha un camp que és el do_not_call, i per tant puc afegir la línia
array('name'=>'do_not_call','value'=>True),
Recordar que a http://mysugar/soap.php hi ha la documentació bàsica sobre els mètodes exposats de les funcions SOAP.
Exemple3. Login with error checking
És una funció que valida un login i password de SugarCRM. Podria servir per validar l'entrada a una aplicació web amb els logins i passwords de Sugar.
<? function wsLogin($userName, $Password) { echo "including"; require_once('../include/nusoap/nusoap.php'); $Connectionstring = 'http://localhost/sugarcrm/soap.php?wsdl'; $wsdl="http://localhost/sugarcrm/soap.php?wsdl"; $sugar_client = new soapclient($wsdl, true); echo "get the client "; $proxy = $sugar_client->getProxy(); echo "proxy "; $ret = $proxy->test('OK'); echo "test is: $ret"; echo "password conded is: ". md5($Password) . ""; $user_auth = array( 'user_name' => $userName, 'password' => md5($Password), 'version' => "1", ); $login_results= $proxy->login($user_auth, "pipo"); if($login_results['error']['name']=="No Error") { return $session_id = $login_results['id']; } else { return $login_results['error']['name']; } } ?>
Llistar casos
Després de barallar-me bastant, he aconseguit llistar els casos que hi ha ficats al SugarCRM, amb la possibilitat de filtrar i d'ordenar. El mètode response és important per depurar doncs dóna molta informació d'on estan els errors.
<?php define('sugarEntry', TRUE); require_once('../include/nusoap/nusoap.php'); $client = new nusoapclient('http://localhost/sugarcrm/soap.php?wsdl',true); $pass = md5('****'); echo "Login Result: "; echo $client->call('create_session', array('user_name'=>'admin', 'password'=>$pass)); echo "<br />"; $auth_array = array( 'user_auth' => array( 'user_name' => 'admin', 'password' => md5('****'), ) ); $login_results = $client->call('login',$auth_array); $session_id = $login_results['id']; printf("Session ID: ". $session_id . "<br />"); $module_name='Cases'; $query='cases.name like "%warning%"'; $order_by='cases.id'; $offset=0; $select_fields=array( 'id', 'case_number', 'name', 'status', ); $max_results=5; $deleted=0; $search_list=$client->call('get_entry_list',array($session_id,$module_name,$query,$order_by,$offset,$select_fields,$max_results,$deleted)); echo "numero de resultats ".$search_list['result_count']."<br />"; echo "el mètode response va molt bé per editar errors. Per exemple, si faig referència a un camp que no existeix en el order by<br />"; echo $client->response; echo "<br /><br />"; function nameValuePairToSimpleArray($array){ $my_array=array(); while(list($name,$value)=each($array)){ $my_array[$value['name']]=$value['value']; } return $my_array; } echo "Search result is <pre>"; if($search_list['result_count']>0){ foreach($search_list['entry_list'] as $record){ $array= nameValuePairToSimpleArray($record['name_value_list']); echo $array['id'] . " :: " . $array['case_number'] . " - " . $array['name'] . " - " . $array['status'] . "<br>"; } } else { echo "No cases found"; echo "<br />"; } // End the session echo "Closing Session: "; echo $client->call('end_session', array('user_name'=>'admin')); echo "<br />"; //kill the client unset($client); ?>
Llistar contactes (classe PHP)
Ara faig el mateix que l'anterior exercici però definint una classe PHP.
La classe SugarSoap la defineixo en el fitxer SugarSoap.php:
<?php define('sugarEntry', TRUE); require_once('../include/nusoap/nusoap.php'); class SugarSoap{ var $soapclient; var $proxy; var $sess; function SugarSoap(){ $soap_url='http://localhost/sugarcrm/soap.php?wsdl'; $soapclient = new nusoapclient($soap_url,true); $this->proxy = $soapclient->getProxy(); $this->login(); } function login(){ $auth_array = array( 'user_auth' => array( 'user_name' => 'admin', 'password' => md5('****'), ) ); $result = $this->proxy->call('login',$auth_array); $this->sess= $result['error']['number']==0 ? $result['id'] : null; return $this->sess; } function getContacts($query='',$maxnum=0,$orderby=' contacts.last_name asc'){ $contact_array = array( $this->sess, 'Contacts', $query, $orderby, 0, array( 'id', 'first_name', 'last_name', 'account_name', 'account_id', 'email1', 'phone_work', ), $maxnum, false ); $result = $this->proxy->call('get_entry_list',$contact_array); echo "el mètode response va molt bé per editar errors. Per exemple, si faig referència a un camp que no existeix en el order by<br />"; echo $this->proxy->response."<br /><br />"; return $result; } function nameValuePairToSimpleArray($array){ $my_array=array(); while(list($name,$value)=each($array)){ $my_array[$value['name']]=$value['value']; } return $my_array; } } ?>
i el fitxer llistar_contactes.php és el que crida a la classe:
<?php require_once "SugarSoap.php"; $soap=new SugarSoap(); // we automatically log in $result=$soap->getContacts(" contacts.phone_work<>'' ",5," contacts.last_name desc"); if($result['result_count']>0){ foreach($result['entry_list'] as $record){ $array= $soap->nameValuePairToSimpleArray($record['name_value_list']); echo $array['first_name'] . " " . $array['last_name'] . " - " . $array['email1']. " - " . $array['phone_work']. "<br>"; } } else { echo "No contacts found"; } ?>
Compte perquè si en el filtre fico
contacts.email1<>
falla, i això és perquè no existeix el camp mail1 en la taula contacts. El tractament dels mails és una mica més complexe, és una relació 1:M i els mails estan en la taula email_addr_bean_rel i el camp primary_address. La consulta que s'envia és
SELECT count(*) c FROM contacts LEFT JOIN users ON contacts.assigned_user_id=users.id LEFT JOIN accounts_contacts ON contacts.id=accounts_contacts.contact_id and accounts_contacts.deleted = 0 LEFT JOIN accounts ON accounts_contacts.account_id=accounts.id AND accounts.deleted=0 LEFT JOIN email_addr_bean_rel eabl ON eabl.bean_id = contacts.id AND eabl.bean_module = 'Contacts' and eabl.primary_address = 1 and eabl.deleted=0 LEFT JOIN email_addresses ea ON (ea.id = eabl.email_address_id) where ( contacts.email1<>'' ) AND contacts.deleted=0
i falla perquè
MySQL error 1054: Unknown column 'contacts.email1' in 'where clause'
Analitzant la clàusula SQL veig que he de ficar la línia
eabl.primary_address<>
i ara sí que puc filtar els contactes que tenen email1<>
Al MySQL, per veure les taules i la descripció de les taules és:
mysql> show tables; mysql> SHOW FIELDS FROM `contacts`; mysql> SHOW FIELDS FROM `email_addr_bean_rel`;