Kisebb-nagyobb kihagyás után ismét itt vagyok (vagy talán vagyunk). Egy munka során felmerült problémát, és a hozzá tartozó megoldásomat szeretném most megosztani. Arról már korábban volt szó, hogy hogyan használhatjuk a PHP 5 beépített SOAP osztályát, ha SOAP klienst vagy szervert szeretnénk üzemeltetni. Azonban mi van akkor, ha nem áll rendelkezésre PHP 5? Persze, ott a PEAR, de mivel nekem egyrészről nem volt szükségem a SOAP kliens által nyújtott minden szolgáltatásra és egyébként is inkább előnyben részesítem a saját kódot, ezért elő is bányásztam már porosodó cURL tudásomat, mivel a cURL kiterjesztés nagyban megkönnyíti a HTTP kérések küldését és a válaszok fogadását valamint a PHP 4-es verziójában is elérhető.

A feladat tehát, hogy az MNB SOAP alapú webszolgáltatását használva lekérjük az éppen aktuális árfolyamokat a PHP egy 4.4 feletti verziója segítségével. Az MNB-nél elég programozó-barátak ilyen téren, a http://www.mnb.hu/arfolyamok.asmx címen tulajdonképpen mindent megtudhatunk a szolgáltatás működéséről, kezdve attól, hogy milyen formátumú XML-t várnak tőlünk, addig, hogy milyen formátumút fogunk mi azért cserébe kapni. Természetesen a dolog nem ennyire szép, mivel csak a szabványos SOAP kérés-válasz van leírva, hogy az adatokat magukat milyen formátumban kapjuk, az nincs. Részletkérdés, úgyis látni fogjuk... :)

Mint az a fentebb említett címen kitűnően látható, három függvény áll a rendelkezésünkre, ebből mi csak a középsőt fogjuk használni, mivel az adja vissza az aktuális árfolyamokat. Ha vagyunk olyan bátrak és rá is kattintunk, láthatjuk a kérés és válasz szabványos formáját. Kezdjük is el a kódolást:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.mnb.hu/arfolyamok.asmx");
curl_setopt($ch, CURLOPT_HEADER, 0);

Létrehozunk egy cURL kapcsolatot, majd megadjuk neki az URL-t, megmondjuk, hogy nem kérünk header-eket, a könnyebb feldolgozhatóság érdekében. A példa XML header-jében látszik, hogy POST-olnunk kell az adatokat a rendszernek, ezért a következő beállításra is szükségünk lesz:

curl_setopt($ch, CURLOPT_POST, true);

Ennek viszont megvan az a hátránya, hogy az alapértelmezett Content-Type application/x-www-form-urlencoded lesz, a szolgáltatás viszont text/xml-t vár el tőlünk (és ezt nem is felejti el megjegyezni egy hiba formájában ha mégis az előbbivel küldjük neki az adatokat). Így ezt át kell állítanunk, valamint egy saját header-re is szükségünk van (SOAPAction):

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-Type: text/xml; charset=utf-8',
	'SOAPAction: "http://www.mnb.hu/webservices/GetCurrentExchangeRates"'
));

Nincs más hátra, mint a megfelelő curl_setopt segítségével a POST adatot hozzácsapni a kérés végére:

curl_setopt($ch, CURLOPT_POSTFIELDS, "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">
	<soap:Body>
		<GetCurrentExchangeRates xmlns=\"http://www.mnb.hu/webservices/\"/>
	</soap:Body>
</soap:Envelope>");

Már csak egy utolsó beállítás, hogy ne rögtön kiírja az eredményt, hanem visszaadja, majd végrehajtjuk a lekérést és lezárjuk a kapcsolatot:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$soap_response = curl_exec($ch);
curl_close($ch);

Meg is volnánk. Bár tény, hogy a SOAP osztályt használva fele ennyi kóddal megúsztuk volna és abban már az eredmény kinyerése a SOAP válaszból is meglett volna, de ez legalább működik PHP 4-es környezetben is. Klimatizált szerverszobában gazdag további nyarat Mindenkinek.