Webové služby v PHP: XML-RPC a SOAP

Školení, která pořádám

Článek vyšel v rámci PHP okénka na serveru Root.cz.

Koncept webových služeb umožňuje protokolem HTTP volat funkce na vzdáleném serveru, předávat jim parametry a pracovat s vrácenými výsledky. Je přitom úplně jedno, v jakém programovacím jazyce je webová služba napsaná i z jakého jazyka ji voláme. Rozdíly se smývají ve formátu výměny dat, kterým je obvykle XML. Jakýkoliv program schopný pracovat s XML daty tedy může být klientem i serverem webových služeb.

Webové služby lze použít všude tam, kde potřebujeme partnerům předávat nějaká data nebo tato data naopak získávat. Může jít o seznam produktů, aktuální počasí, výsledky vyhledávání, …

Jako protokol pro práci s webovými službami se nejčastěji používá buď jednodušší XML-RPC nebo komplexnější SOAP. K webové službě v protokolu SOAP lze navíc připojit tzv. WSDL dokument, který popisuje veškerou funkčnost webové služby a ze kterého tedy můžeme zjistit, jaké funkce s jakými parametry a jakou návratovou hodnotou lze přes tuto webovou službu volat.

Požadavky a odpovědi můžeme zpracovávat stejně jako jakékoliv XML, PHP navíc pro oba nejběžnější druhy služeb nabízí extenze, které nás od přenosového formátu zcela odstíní: XML-RPC a SOAP (v PHP 4 lze použít knihovnu NuSOAP). V tomto článku si ukážeme, jak lze vytvářet požadavky v obou protokolech. Poměrně jednoduše lze na požadavky i odpovídat (vytvořit server), tomu se tento článek ale nevěnuje.

XML-RPC

Extenze XML-RPC pracuje na nižší úrovni a poskytuje pouze základní funkce zakódování požadavku a jeho dekódování. O samotné zavolání se musíme postarat sami:

<?php
/** Položení XML-RPC požadavku
* @param string URL webové služby
* @param string funkce, která se má zavolat
* @param array parametry, které se mají funkci předat
* @param array zvláštní typy "base64" nebo "datetime"
* @param string kódování odpovědi, výchozí je utf-8
* @return mixed data vrácená funkcí
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function xmlrpc($url, $method, $params, $types = array(), $encoding = 'utf-8') {
    foreach ($types as $key => $val) {
        xmlrpc_set_type($params[$key], $val);
    }
    $context = stream_context_create(array('http' => array(
        'method' => "POST",
        'header' => "Content-Type: text/xml",
        'content' => xmlrpc_encode_request($method, $params, array('encoding' => $encoding))
    )));
    return xmlrpc_decode(file_get_contents($url, false, $context), $encoding);
}

// ukázka použití
echo xmlrpc("http://phpxmlrpc.sourceforge.net/server.php", "examples.getStateName", array(1)) . "\n";
?>

Funkce předpokládá zapnutou direktivu allow_url_fopen, která dovoluje pracovat se vzdálenými soubory. Pokud je tento požadavek splněn, dá se s XML-RPC pomocí této funkce velice jednoduše pracovat, jinak je potřeba funkci přepsat buď na extenzi cURL nebo na funkci fsockopen.

SOAP

Extenze SOAP umožňuje pracovat na vyšší úrovni a po zaregistrování webové služby už můžeme přímo volat její funkce. Práci s touto extenzí si ukážeme na službě Live Search, která nabízí vyhledávání přes protokol SOAP. Pro použití této služby se musíme zaregistrovat, čímž získáme klíč umožňující položení až 25 000 dotazů denně. Díky připravenému WSDL dokumentu můžeme službu začít ihned používat.

Nejprve zjistíme, jaké funkce můžeme používat. To lze zjistit buď z dokumentace nebo přímo z WSDL dokumentu:

<?php
$soap = new SoapClient('http://soap.search.msn.com/webservices.asmx?wsdl');
print_r($soap->__getFunctions()); // array('SearchResponse Search(Search $parameters)')
?>

Dozvíme se, že existuje jediná funkce Search s parametrem typu Search a návratovou hodnotou typu SearchResponse. Co jednotlivé typy znamenají, můžeme zjistit zavoláním funkce SoapClient::__getTypes. Dozvíme se, že typ Search je struktura s jediným prvkem Request typu SearchRequest. SearchRequest je zase struktura s prvky jako AppID (náš klíč), Query (dotaz, který pokládáme), CultureInfo (informace o jazyku a místu vyhledávání, hodnota cs-CZ ale bohužel zatím není podporována) nebo Requests (oblast, kterou chceme prohledávat). V PHP se struktury předávají buď jako objekty s odpovídajícími vlastnostmi nebo jednoduše jako asociativní pole:

<?php
define("LIVE_APP_ID", "zaregistrovaný identifikátor aplikace");
$limit = 10;
$site = "php.vrana.cz";
$query = $_GET["query"];

$soap = new SoapClient('http://soap.search.msn.com/webservices.asmx?wsdl');
$SourceRequest = array(
    "Source" => "Web",
    "Offset" => intval($_GET["offset"]),
    "Count" => $limit,
    "ResultFields" => "All",
);
$Search = array(
    "AppID" => LIVE_APP_ID,
    "Query" => "site:$site $query",
    "CultureInfo" => "en-US",
    "SafeSearch" => "Off",
    "Flags" => "None",
    "Requests" => array("SourceRequest" => $SourceRequest),
);
$SearchResponse = $soap->Search(array("Request" => $Search));
?>

Použití výsledků vyhledávání záleží na naší fantazii – můžeme ho použít pro prohledávání na vlastních stránkách (přidáním operátoru site: přímo do dotazu) nebo třeba pro pravidelné zjišťování pozice našich stránek na vybrané dotazy (to se dá udělat i přímým rozebráním stránky s výsledky, použití webové služby je ale spolehlivější a hlavně v souladu s licencí).

Funkce Search vrátí hlubokou strukturu s výsledky pro jednotlivé zdroje vyhledávání (kromě webu lze prohledávat i reklamy, obrázky, telefonní seznam, opravy překlepů, …). My prohledáváme pouze web, takže s výsledkem můžeme přímo pracovat:

<?php
$SourceResponse = $SearchResponse->Response->Responses->SourceResponse;
if (!$SourceResponse->Results->Result) {
    echo "<p>Nic nebylo nalezeno.</p>\n";
} else {
    echo "<dl>\n";
    foreach ($SourceResponse->Results->Result as $Result) {
        echo '<dt><a href="' . htmlspecialchars($Result->Url) . '">';
        echo htmlspecialchars($Result->Title) . "</a></dt><dd>";
        echo htmlspecialchars($Result->Description) . "</dd>\n";
    }
    echo "</dl>\n";
}
if ($SourceResponse->Total > $_GET["offset"] + $limit) {
    echo "<p><a href='?query=" . urlencode($query) . "&amp;offset=" . ($_GET["offset"] + $limit);
    echo "'>Další</a> z celkem $SourceResponse->Total.</p>\n";
}
?>

Nalezené výsledky zobrazíme v seznamu a pokud jich je hodně, tak zobrazíme odkaz na další stránku.

Závěr

Díky existujícím extenzím se v PHP s webovými službami pracuje velice pohodlně – jsme zcela odstíněni od přenosového formátu a jednoduše voláme funkce a zpracováváme výsledky podobně, jako to děláme s lokálními knihovnami.

Jakub Vrána, Seznámení s oblastí, 10.8.2007, diskuse: 37 (nové: 0)

Diskuse

ikona Ji31:

Jee, díky. Zrovna mám něco dělat v SOAP, takže se mi tento článek perfektně hodil.

Díky

Miloš:

Jako základ pro Soap je článek stručný a poučný. Mám ale problém, když chci soapClient použít v tzv.nonWSDL režimu tj. bez užití wsdl souboru. Můžete mne navést na nějaký chodivý příklad nebo je PHP5 chyba? (Soudě podle množství lidí, kterým to nejde.)

MS

ikona Jakub Vrána OpenID:

Úplně jednochý příklad mi funguje:

soap_server.php:
<?php
function a_plus_b($a, $b) {
    return $a + $b;
}

$server = new SoapServer(null, array('uri' => "http://test-uri/"));
$server->addFunction('a_plus_b');
$server->handle();
?>

soap_client.php:
<?php
$client
= new SoapClient(null, array('location' => "http://localhost/php5/soap_server.php", 'uri' => "http://test-uri/"));
echo
$client->a_plus_b(3, 2);
?>

ikona Kcko:

Tento příklad v dnešní době nefunguje (PHP 5.6, 7.0), vlastně jsem na to narazil náhodou, protože mi nefungují žádné non WSDL režimy. Zjistil jsem, co to způsobuje (https://stackoverflow.com/questions/13285716/…-xml-document)

Vlastnost always_populate_raw_post_data , která se odkomentuje a je to funkční. Nicméně je to workaround, protože je to již deprecated.

Asi na tohle nikdo nezareaguje, ale tak třeba kdyby náhodou, věděl by někdo co s tím, aby to fungovalo i bez tohoto nastavení?

Zdeněk:

Dobrý den,
jak zadefinuji aby kdyz posilam dotaz na soap server pres SoapUI aby $a byla a $b byla b. Protoze serveru je jedno co tam poslu. Bere promenne postupne takze kdyz zadam:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:a_plus_b>
        <b>10</b>
        <a>20</a>
        </tem:a_plus_b>
   </soapenv:Body>
</soapenv:Envelope>
Tak vysledek je 10+20, ale ja chci aby byl 20+10 (stejne to vyjde oboje 30, ale myslim kdyz doplnuji neco u ceho to vyznam uz ma)

Dekuji

ikona Jakub Vrána OpenID:

Asi bych zkusil poslat nejdřív <a> a potom <b>.

LubaM:

Jaky, ze je ten link na registraci Live Search? Odkazovany nefunguje a ani po dlouhem hledani se mne na jejich IMO neprehlednych strankach nepodarilo najit alternativni, u nehoz bych si byl jist, ze se jedna o registraci k vyse zminovane sluzbe.

ikona Jakub Vrána OpenID:

Odkaz mi taky nefunguje a nový jsem taky nenašel. Zeptal jsem se tedy v Microsoftu a uvidíme.

ikona Jakub Vrána OpenID:

Je to těžko uvěřitelné, ale stránka funguje jen tehdy, když je jako výchozí jazyk nastavena angličtina (Accept-Language: en).

LubaM:

Diky za vyreseni problemu, tohle by mne nenapadlo. Opravdu tezko uveritelne.

Radek:

Ja mam problem, muzete mi poradit?
Mam vytvoreneneho SOAP klienta, ktery posila requesty na SOAP server ktery bezi pod asp.net
Pozadavek provozovatele SOAP serveru je aby reqeusty pouzivali kodovani win-1250. Me teda vsechno jede ve win-1250 - vlastni stranky i db a i kdyz ulozim to co mi vrati __getLastRequest do souboru, tak je to v poradku citelne v kodovani win-1250.

No ale provozovatel tvrdi, ze jemu to prichazi ve spatnem kodovani a poslane udaje jsou necitelne. Muzete poradit jak kodovani zmenit, pripadne jak spolehlive vyzkouset v jakem kodovani se request (retezce v requestu) posilaji?

Diky

ikona Jakub Vrána OpenID:

V parametru $options konstruktoru SoapClient lze zadat encoding, což je interní kódování dat, ale požadavky se vždy odesílají v UTF-8.

mark516651:

z dlouhodobého hlediska jiště není rozumé dát si windows-1250 kódování na vývěsní štít, vizitku a používat jej vždy a všude, od toho je tu právě unicode.

newman:

Zdravím,
jak byste řešili zabezpečení při autentizaci uživatele skrze SOAP server? V situaci, kdy byste chtěli např. jeden uživatelský účet pro více serverů? Přijde mi (zjednodušeně řečeno), že např. prostá funkce vracející info o úspěšnosti přihlašovacích údajů je řešení vysloveně vyzývající k nasazení nějakého robota a testování kombinací jmeno/heslo než by se to podařilo trefit. Napadá vás nějaký způsob jak by se taková věc dala bezpečněji vyřešit?

Fibi:

Tady bych měl dotaz na problém se kterým jsem se setkal u exportu do seznamu pomocí XML-RCP.
Problém nastane pokud mám kód :

xmlrpc_encode_request('volana.metoda',
array(
   array('1' => 'hodnota jednicky')
);
A chci aby bylo zakodovano do struct, nikoliv do array.
Jediné co jsem zatím vymyslel je že k jedničce přiřadím definovaný kus textu a ten z už hotového XML dotazu odstraním a až následně dále zpracovávám, ale to mi nepřijde příliš logický postup :-(
Nezná někdo elegantnější řešení ?

Martin:

Zdravím, přiklad tady uvedený mi nefunguje nezměnilo se něco na microsoftu? Nebo dělám něco špatně.Díky M.

TM:

Dobrý den,
začínám si hrát s XML-RPC a narazil jsem hned na začátku. Pokud použiji funkci:

<?php
xmlrpc
('https://www.estatix.cz/firma/rpc2.php', 'login',$params);
?>

tak se dozvím:

Warning: file_get_contents(https://www.estatix.cz/firma/rpc2.php) [function.file-get-contents]: failed to open stream: Invalid argument in C:\Program Files\Easy... -: ukazuje na řádek kde je použita funkce file_get_contents.

Netuším proč na tom padá - pokud si dám do prohlížeče samotné url tak mi server odpoví že akceptuje pouze POST - takže ten žije... můžete mě postrčit co mám špatně?

matak:

použij curl, máš zakázané pomocí file_get_contents načítat externí adresy

Radek:

Dobrý den, ten přiklad pro soap plati i pro NuSoap?

Ciba:

Dobry den,
pri pouziti baliku nusoap v PHP 5 je nutne si jej poupravit! Nastava zde kolize s nove implementovanou metodou SoapServer, ktera v PHP4 nebyla a v baliku nusoap se jmenuje stejne.
Vytvareni klienta je temer stejne, rozdil je v implementaci serveru. Vyzdvyhl bych zde rad perfektni vlastnost nusoapu -> generovani uzivatelske dokumentace zaroven s WSDL.

David:

Dobrý den,
mám vymyšlený projekt, který by měl fungovat jako webová služba, protože některé věci nemůžu nechat programovat nikho cizího, musím to udělat sám a tak bych potřeboval pár informací: 1)Jestli  je SOAP protokol aktuální a má cenu ho využívat, vpodstatě nejdená li se o slepou vývojovou větev jako např. XML-RPC a 2)bych potřeboval poradit nějakou dobrou knihu zabývající se problematikou vebových služeb nejlépe ve spojen s php.

Děkuji za odpovědi David

ikona Jakub Vrána OpenID:

1. SOAP se stále běžně používá. 2. Knihu neznám.

jvic:

Doporučuji knihu Programujte mashup aplikace v PHP, kde se řeší XML-RPC, SOAP i REST. :)

hps:

Dobry den

chcel by som vas poprosit o radu

pouzival som SOAP sluzbu na overovanie IC DPH
pouzival som nasledujuci kod
<?php
$skratka
=$_REQUEST['s'];
$cislo=$_REQUEST['no'];
if ((
$cislo<>"")AND($skratka<>"")):
#$client = new SoapClient('http://ec.europa.eu/taxation_customs/vies/api/checkVatPort?wsdl');
$client = new SoapClient('http://ec.europa.eu/taxation_customs/vies/services/checkVatService?wsdl');

$params = array('countryCode' => $skratka, 'vatNumber' => $cislo);
$r = $client->checkVat($params);
  if (($r->valid)==1):

$out="ano
"
.$r->name."
"
.$r->address;
$out=iconv("utf-8", "windows-1250",$out);
$trans = array("
"
=> "\n");
echo
strtr ($out,$trans);
  else:
  echo "nie";
  endif;
else:
echo
"error nezadal si parametre";
endif;
?>

vsetko fungovalo bez problemov ale nedavno zmenili wsdl pre sluzbu na http://ec.europa.eu/taxation_customs/vies/services/checkVatService?wsdl
Teraz neviem prist na to ako upravit kod aby znova fungoval
zmena odkazu na wsdl subor nestaci.

Peťa:

Zkouším ... a funguje. Jen jsem zkopíroval a zadal vstupy, bez dalších úprav.

Overtonesinger:

Úžasné! Bez úprav mi funguje i v roce 2016! Děkuji mnohokráte za krásný příklad použití SOAP přes http. Ví někdo, náhodou, jak se připojit na webService přes HTTPS? (ZoET ... Zákon o EET, ten server jede na https!).

Radek Cvek:

Pokud chcete v xmlrpc používat diakritiku zaměňte v Jakubově funkci řádek
<?php
 
'content' => xmlrpc_encode_request($method, $params, array('encoding' => $encoding))
?>
za
<?php
'content' => xmlrpc_encode_request($method, $params, array('escaping' => 'markup', 'encoding' => $encoding))
?>
vyzkoušejte sami:
<?php
  header
('Content-type: text/html; charset=utf-8',true);
  echo xmlrpc_encode_request($method, 'František Novák', array('encoding' => 'utf-8')).'<br />';
  echo xmlrpc_encode_request($method, 'František Novák', array('escaping' => 'markup', 'encoding' => 'utf-8'));
?>

Daniel:

Pokud volám přímo

<?php $soap->Search(array("Request" => $Search)); ?>

tak to hlásí notice. Viz podobný problém na http://stackoverflow.com/questions/12420866/…-soap-client

Palino:

mate niekto skusenosti s WSDL 2.0. SoapClient ju nativne nepodporuje a neviem najst nijake rozumne riesenie, alebo nahradu. Budem vdacny za kazdu radu. dik

Racky:

Ahoj. Vzhledem k nefunkčnosti MSN bych navrhl zveřejnit, co by se mělo zobrazit po zavolání $soap->__getTypes(). V návodu to není uvedeno a nedokážu tak odvodit, jak pochopit výpis této metody v jiných případech. Můj příklad je tento:

<?php
$soap
= new SoapClient('http://epodpora.mfcr.cz/media/CRPDPH_v1.0.wsdl');
$soap->__getFunctions():

// StatusNespolehlivyPlatceResponse getStatusNespolehlivyPlatce(StatusNespolehlivyPlatceRequest $parameters)

$soap->__getTypes():

// struct StatusNespolehlivyPlatceRequest { DICType dic; }
// string DICType

// Snažím se volat toto, ale hlásí to fatal error "Couldn't connect to host in index.php":

$res = $client->getStatusNespolehlivyPlatce(array('DIČ'))
// nebo
$res = $client->__soapCall('getStatusNespolehlivyPlatce', array('DIČ'));

?>

Mikaël DELSOL:

Try http://www.wsdltophp.com ;)

Michal:

Dobrý den, mám následující kód:

<?
$soapURL
= "https://domena/sestava.wsdl";
$soapParameters = Array('username' => "******", 'password' => "*******") ;
$soapFunction = "sestavaData";
$soapFunctionParameters = Array(
   
"parametr" => Array("kod" =>"ALL_DATA","hodnota"=>"1"),
   
"kod" => "TS",
   
"export" => "1"
);

$soapClient = new SoapClient($soapURL, $soapParameters);

$soapResult = $soapClient->__soapCall($soapFunction, $soapFunctionParameters) ;
?>
ale vypisuje mi to:
Fatal error: Uncaught SoapFault exception: [SOAP-ENV:Client] No WS-Security header found in /u01/docs/www/html/soap1/index.php:67 Stack trace: #0 /u01/docs/www/html/soap1/index.php(67): SoapClient->__soapCall('sestavaData', Array) #1 {main} thrown in /u01/docs/www/html/soap1/index.php on line 6

dále mám dotaz k autentifikaci, zda to takto může být nebo je potřeba místo "username" uvádět "login"? Zkoušel jsem i hledat to secutiry WS a našel jsem tuto třídu:

<?
class WSSoapClient extends SoapClient {

    private
$username;
    private
$password;

    private function
wssecurity_header() {

       
$timestamp = gmdate('Y-m-d\TH:i:s\Z');
       
$nonce = mt_rand();
       
$passdigest = base64_encode( pack('H*', sha1(pack('H*', $nonce). pack('a*',$timestamp). pack('a*',$this->password))));

       
$auth = '
        <wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="https://okbasetst/okbase/ws/sestavaEndpoint.wsdl">
        <wsse:UsernameToken>
            <wsse:Username>'
.$this->username.'</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-…#PasswordDigest">'
.$passdigest.'</wsse:Password>
            <wsse:Nonce>'
.base64_encode(pack('H*', $nonce)).'</wsse:Nonce>
            <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-…-utility-1.0.xsd">'
.$timestamp.'</wsu:Created>
           </wsse:UsernameToken>
        </wsse:Security>
        '
;

       
/* XSD_ANYXML (or 147) is the code to add xml directly into a SoapVar.
         * Using other codes such as SOAP_ENC, it's really difficult to set the
         * correct namespace for the variables, so the axis server rejects the
         * xml.
         */
       
$authvalues = new SoapVar($auth,XSD_ANYXML);
       
$header = new SoapHeader("https://okbasetst/okbase/ws/sestavaEndpoint.wsdl", "Security", $authvalues, true);

        return
$header;
    }

   
/* It's necessary to call it if you want to set a different user and
     * password
     */
   
public function __setUsernameToken($username, $password) {
       
$this->username = $username;
       
$this->password = $password;
    }

   
/* Overwrites the original method adding the security header. As you can
     * see, if you want to add more headers, the method needs to be modifyed
     */
   
public function __soapCall($function_name, $arguments, $options=null, $input_headers=null, $output_headers=null) {

       
$result = parent::__soapCall($function_name, $arguments, $options, $this->wssecurity_header());

        return
$result;
    }
}
?>

ale pokud ji použiji tak mi to píše neznámé jméno nebo heslo.

Yuni:

Pane Vráno jste frajer, stračně jste mi pomohl díky :)

Lister:

Ahoj,

nemam zadny problem, ale spis jen vaham nad pouzitim extenze XML-RPC v php, protoze je u ni upozorneni, ze je experimentalni. Nasadit to na produkci mi neprijde zrovna idealni. Je experimentalni uz nekolik let a stale stejna nebo se vyviji?

Diky

Lawondyss:

Skvělý článek, pomohl mi nastartovat komunikaci s dopravcem přes jeho API. Teď jsem však narazil na to, že jedna z funkcí vyžaduje strukturu, které nejsem schopen docílit.
Jako vzor jsem dostal tohle XML:

<?xml version="1.0" encoding="windows-1250"?>
<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>
    <ImportPackagesExt xmlns="PPLIEGate">
      <FirCode>ppltest</FirCode>
      <Packages>
        <Items>
          <anyType xsi:type="Package">
            <PackageID>40080145103</PackageID>
            <ZipCode>16300</ZipCode>
            <Country>CZ</Country>
            <ErrorCode>0</ErrorCode>
            <ErrorMessage></ErrorMessage>
          </anyType>
          <anyType xsi:type="Package">
            <PackageID>40010529207</PackageID>
            <ZipCode>15500</ZipCode>
            <Country>CZ</Country>
            <ErrorCode>0</ErrorCode>
            <ErrorMessage></ErrorMessage>
          </anyType>
        </Items>
      </Packages>
    </ImportPackagesExt>
  </soap:Body>
</soap:Envelope>

Takže jsem si udělal skript, který by měl danou strukturu vytvořit. Pochopil jsem, že musím použít i třídu SoapVar.

<?php
$packs
= [
    [
       
'PackageID' => '40080145103',
       
'ZipCode' => '16300',
       
'Country' => 'CZ',
       
'ErrorCode' => 0,
       
'ErrorMessage' => '',
    ],
    [
       
'PackageID' => '40010529207',
       
'ZipCode' => '15500',
       
'Country' => 'CZ',
       
'ErrorCode' => 0,
       
'ErrorMessage' => '',
    ],
];

$items = [];
foreach (
$packs as $pack) {
   
$items[] = new SoapVar($pack, SOAP_ENC_ARRAY, XSD_ANYTYPE, null, 'Package');
}

$packages = [
   
'FirCode' => $firCode,
   
'Packages' => [
       
'Items' => $items,
       
'ErrorCode' => 0,
    ],
   
'DepID' => '00',
];
$response = $soap->ImportPackagesExt($packages);
?>

Ale dostávám jen výjimku SoapFaul, která říká:
Server was unable to process request. ---> Unable to cast object of type 'System.Xml.XmlNode[]' to type 'Package'.

Pomůže mi někdo to dát dohromady?

Lawondyss:

Tak už jsem na to přišel. Proměnná $items se také musí předat jako instance třídy SoapVar.

<?php
$packages
= [
   
'FirCode' => $firCode,
   
'Packages' => [
       
'Items' => new SoapVar($items, SOAP_ENC_ARRAY),
       
'ErrorCode' => 0,
    ],
   
'DepID' => '00',
];
?>

Miro:

Zdravím,

mám problém s pripojením na web-service. Zoznam funkcií na základe __getFunctions() získam v pohode, ale keď chcem zavolať službu, tak dostanem naspäť chybovú hlášku "Error Fetching http headers". Problém je, že neviem ako nastaviť hlavičku (SoapHeaders). Mám síce meno a heslo, ale neviem ako ho mám použiť. Všade sa píše o tele, ale o obsahu hlavičky je ťažké sa niečo dočítať. Ako má vyzerať obsah hlavičky asi nie je súčasť wsdl špecifikácie, lebo som tam žiadnu takú informáciu nenašiel (napr. ako sa má volať parameter obsahujúci meno a heslo, čo vlastne má byť v druhom parametri toho SoapHeaders a pod.. ) Dá sa to nejako zistiť, alebo to musí explicitne povedať strana poskytujúca web-service mimo wsdl špecifikáciu? Pozn: druhej strane to robila nejaká dodávateľská firma, ktorá sa ponúkla, že mi to za pár tisíc eur naimplementuje, lebo to nie je nič zložité. Inak ma odkázala sa tú wsdl špecifikáciu, kde je vraj všetko.

Na niečo podobné sa tu pýtal aj Michal v minulom januári, ale žiadna odpoveď tam nie je. Vedel by mi niekto poradiť? Vopred ďakujem.

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.