Lekcje komputerowe

Piszemy aplikację klient-serwer SOAP w języku PHP. Czy Microsoft wypada z gry?

(PHP 5 >= 5.0.1)

SoapClient::SoapClient — Konstruktor SoapClient

Parametry

wsdl

URI pliku WSDL plik lub ZERO jeśli pracujesz w nie-WSDL tryb.

Podczas programowania buforowanie WSDL może zostać wyłączone poprzez użycie opcji mydło.wsdl_cache_ttl php.ini, w przeciwnym razie zmiany dokonane w pliku WSDL nie będą miały efektu do czasu mydło.wsdl_cache_ttl straciła ważność.

opcje

Szereg opcji. Jeśli pracujesz w trybie WSDL, ten parametr jest opcjonalny. Jeśli pracujesz w trybie innym niż WSDL, plik Lokalizacja I u należy ustawić opcje, gdzie Lokalizacja to adres URL serwera SOAP, do którego należy wysłać żądanie, oraz u jest docelową przestrzenią nazw usługi SOAP.

The styl I używać opcje działają tylko w trybie innym niż WSDL. W trybie WSDL pochodzą one z pliku WSDL.

The wersja_mydła Opcja określa, czy używać klienta SOAP 1.1 (domyślnie), czy SOAP 1.2.

W przypadku uwierzytelniania HTTP plik Zaloguj sie I hasło opcji można użyć do dostarczenia poświadczeń. Aby nawiązać połączenie HTTP za pośrednictwem serwera proxy, należy użyć opcji proxy_host, Port proxy, proxy_login I hasło_proxy są również dostępne. Do użytku z uwierzytelnianiem za pomocą certyfikatu klienta HTTPS certyfikat_lokalny I hasło opcje. Uwierzytelnienie może zostać dostarczone w pliku uwierzytelnianie opcja. Metoda uwierzytelniania może być dowolna SOAP_AUTHENTICATION_BASIC(domyślnie) lub SOAP_AUTHENTICATION_DIGEST.

The kompresja opcja umożliwia zastosowanie kompresji żądań i odpowiedzi HTTP SOAP.

The kodowanie opcja definiuje wewnętrzne kodowanie znaków. Ta opcja nie zmienia kodowania żądań SOAP (zawsze jest to utf-8), ale konwertuje na nie ciągi znaków.

The namierzać opcja umożliwia śledzenie żądań, dzięki czemu można cofnąć błędy. Domyślnie jest to FAŁSZ

The mapa klas tej opcji można użyć do mapowania niektórych typów WSDL na klasy PHP. Ta opcja musi być tablicą zawierającą typy WSDL jako klucze i nazwy klas PHP jako wartości.

Ustawianie wartości logicznej namierzać opcja umożliwia użycie metod SoapClient->__getLastRequest , SoapClient->__getLastRequestHeaders , SoapClient->__getLastResponse i SoapClient->__getLastResponseHeaders .

The wyjątki opcja jest wartością logiczną określającą, czy błędy mydła zgłaszają wyjątki typu SoapFault.

The czas połączenia minął opcja określa limit czasu w sekundach dla połączenia z usługą SOAP. Ta opcja nie definiuje limitu czasu dla usług z wolnymi odpowiedziami. Aby ograniczyć czas oczekiwania na zakończenie połączeń, dostępne jest ustawienie default_socket_timeout.

The mapa maszynowa opcja jest tablicą odwzorowań typów. Mapowanie typów to tablica z kluczami Wpisz imię, typ_ns(URI przestrzeni nazw), z_xml(wywołanie zwrotne akceptujące jeden parametr ciągu) i do_xml(wywołanie zwrotne akceptujące jeden parametr obiektu).

The pamięć podręczna_wsdl opcja jest jedną z WSDL_CACHE_NONE, WSDL_CACHE_DISK, WSDL_CACHE_MEMORY Lub WSDL_CACHE_BOTH.

The agent użytkownika opcja określa ciąg znaków, w którym ma zostać użyty Agent użytkownika nagłówek.

The kontekst_strumienia opcja to kontekst.

The cechy opcja jest maską bitową SOAP_SINGLE_ELEMENT_ARRAYS, SOAP_USE_XSI_ARRAY_TYPE, SOAP_WAIT_ONE_WAY_CALLS.

The utrzymać przy życiu opcja jest wartością logiczną określającą, czy wysłać Połączenie: Keep-Alive nagłówek lub Połączenie: zamknij .

Dziennik zmian

Wersja Opis
5.4.0 Nowy utrzymać przy życiu opcja.

Przykłady

Przykład 1 SoapClient::SoapClient() przykład

$klient = nowy SoapClient("jakieś.wsdl");

$client = nowy SoapClient („some.wsdl” , array(„soap_version” => SOAP_1_2 ));

$client = nowy SoapClient („some.wsdl” , array(”login” => „jakaś_nazwa” ,
"hasło" => "jakie_hasło" ));

$client = nowy SoapClient („some.wsdl” , array(”proxy_host” => „localhost” ,
"proxy_port" => 8080 ));

$client = nowy SoapClient („some.wsdl” , array(”proxy_host” => „localhost” ,
"port_proxy" => 8080,
"proxy_login" => "jakaś nazwa" ,
"proxy_password" => "jakieś hasło" ));

$client = nowy SoapClient („some.wsdl” , array(„local_cert” => „cert_key.pem” ));

$client = nowy SoapClient (null, array("location" =>
"uri" => "http://test-uri/" ));

$client = nowy SoapClient (null , array("location" => "http://localhost/soap.php" ,
"uri" => "http://test-uri/" ,
"styl" => DOKUMENT SOAP,
„użyj” => SOAP_LITERAL ));

$klient = nowy SoapClient("jakieś.wsdl" ,
array("kompresja" => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP ));

$serwer = nowy SoapClient („some.wsdl” , array („encoding” => „ISO-8859-1” ));

klasa MyBook(
publiczny $tytuł ;
publiczny $autor ;
}

$server = nowy SoapClient („books.wsdl” , array(”classmap” => array(”book” => „MyBook” )));

?>

Chrisa Gunawardeny

Aby monitorować wywołania SOAP przychodzące i wychodzące z serwera uniksowego:

Sudo tcpdump -nn -vv -A -s 0 -i eth0 dst lub src Host xxx.xxx.xxx.xxx i port 80

I zawsze używaj „cache_wsdl” => WSDL_CACHE_NONE

svenr w organizacji selfhtml dot org

Opcja „classmap” jest w rzeczywistości mapowaniem typu „ComplexType” używanego w SOAP na klasy PHP.

Nie myl nazw znaczników XML zwróconych w ramach żądania z tymi typami złożonymi. SOAP pozwala im się różnić.

Miałem coś takiego:
...


FooBar

TagName nie jest kluczem, który chcesz umieścić w swojej mapie klas, musisz znać nazwę typu złożonego, do którego odnosi się ten TagName. Informacje te znajdują się w zasobie WSDL.

paulovitorbal w Gmailu dot com

W przypadku korzystania z certyfikatów w parametrze „local_cert” należy podać zawartość pliku, a nie nazwę pliku.

Nowy klient mydła("http://localhost/index.php?wsdl ", array("local_cert"=>file_get_contents("./key.pem"),"passphrase"=>"hasło"));

W PHP możesz mieć zdefiniowane właściwości prywatne w klasach, których używasz w mapie klas. Jeśli więc utworzysz w swojej klasie prywatną właściwość $foo, a element SOAP ma element podrzędny , zawartość $foo zostanie ustawiona na zawartość . W ten sposób możesz kontrolować dostęp do właściwości swoich klas.

(Uwaga: to nie działa w HPHP Facebooka).

willem dot stuursma w hyves dot nl

Jeśli chcesz używać klas w innej przestrzeni nazw w swojej mapie klas, po prostu użyj ukośnika odwrotnego w nazwie klasy docelowej.

Przykład:
$classmap = array("result" => "Mojaprzestrzeń_nazw\\Result" );
?>

Musisz dwukrotnie określić ukośnik odwrotny, ponieważ jest to znak ucieczki w łańcuchach.

simonlang i gmx kropka rozdz

Przykład klienta mydła z uwierzytelnianiem HTTP przez serwer proxy:

nowy klient Soap(
"usługa.wsdl" ,
szyk(
// Rzeczy do rozwoju.
"ślad" => 1 ,
„wyjątki” => prawda,
"cache_wsdl" => WSDL_CACHE_NONE ,
"funkcje" => SOAP_SINGLE_ELEMENT_ARRAYS ,

// Poświadczenia uwierzytelniania dla żądania SOAP.
"login" => "nazwa użytkownika" ,
"hasło" => "hasło" ,

// Adres URL serwera proxy.
"proxy_host" => "example.com" , // Nie dodawaj tutaj schematu (http lub https). To nie zadziała.
"proxy_port" => 44300,

// Poświadczenia uwierzytelniania dla serwera proxy.
"proxy_login" => NULL,
"proxy_password" => NULL,
);
?>
Podanie adresu URL pliku WSDL na serwerze zdalnym (który również jest chroniony uwierzytelnianiem HTTP) nie zadziałało.Pobrałem plik WSDL i zapisałem go na serwerze lokalnym.

Asafa Mellera

W pełni działająca konfiguracja mydła php .net:
notatki
1. web.config na serwerze .net musi działać z podstawowym powiązaniem http.
2. parametry do funkcji mydła należy przekazać jako:
array("nazwa_parametru"=>"wartość_parmu1",
"nazwa_parmu2"=>"wartość_parmu2"...)

header("Typ zawartości: tekst/zwykły");

Próbować(
$opcje = tablica(
"soap_version" => SOAP_1_1 ,
„wyjątki” => prawda,
"ślad" => 1 ,
"cache_wsdl" => WSDL_CACHE_NONE
);
$klient = nowy Klient Soap( „http://www.example.com/end_point.wsdl”, $opcje);

) catch (Wyjątek $e ) (
Echo "

Wyjątek Błąd!

" ;
echo $e -> getMessage();
}

Echo "uruchamia HelloWorld:" ;

Próbować(
$odpowiedź = $klient -> HelloWorld();

}
catch (wyjątek $e)
{
echo "Wychwycony wyjątek: ", $e -> getMessage(), "\n" ;
}

Print_r($odpowiedź);
?>
powodzenia!
Asafa.

faebu i faebu kropka rozdz

Mam te same problemy, gdy próbuję załadować pole WDSL chronione przez podstawowe uwierzytelnianie http, ponieważ parametry login i hasło są używane tylko w żądaniu, ale nie podczas odczytu pliku wdsl. Po prostu stosuję następujące obejście, pobierając plik xml do niechronionej lokalizacji na moim serwerze. Proszę zauważyć, że nie obsługuje to żadnego rodzaju buforowania.

klasa SoapAuthClient rozszerza SoapClient (
/**
* Ponieważ pakiet PHP SOAP nie obsługuje podstawowego uwierzytelniania
* ta klasa pobiera plik WDSL przy użyciu pakietu cURL i
* tworzy lokalną kopię pliku wdsl na twoim serwerze.
*Upewnij się, że podałeś następujący dodatkowy parametr w pliku
* $opcje Tablica:
* wdsl_local_copy => prawda
*/

Private $cache_dir = "/home/example/htdocs/cache/" ;
prywatny $cache_url = „http://www.example.com/cache/”;

Funkcja SoapAuthClient ($wdsl, $options) (
if (isset($options [ "wdsl_local_copy" ]) &&
$opcje [ "wdsl_local_copy" ] == prawda &&
isset($options [ "login" ]) &&
isset($opcje [ "hasło" ])) (

$plik = md5(uniqid()). ".xml" ;

If (($fp = fopen ($this -> cache_dir . $plik , "w")) == false ) (
rzuć nowy wyjątek ( „Nie można utworzyć lokalnego pliku WDSL („. $to -> katalog_pamięci podręcznej. $plik. „)” );
}

$ch = curl_init();
$kredyt = ($opcje["login"]. ":" . $opcje["hasło" ]);
curl_setopt($ch, CURLOPT_URL, $wdsl);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt ($ch, CURLOPT_USERPWD, $credit);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt ($ch, CURLOPT_FILE, $fp);
if (($xml = curl_exec ($ch )) === false ) (
//curl_close($ch);
fclose($fp);
unlink ($this -> cache_dir . $file );

Zgłoś nowy wyjątek (curl_error($ch));
}

Curl_close($ch);
fclose($fp);
$wdsl = $this -> cache_url . $plik ;
}

Unset($options [ "wdsl_local_copy" ]);
unset($options [ "wdsl_force_local_copy" ]);

Echo $wdsl ;
rodzic :: __construct ($wdsl, $options);

Odłącz ($this -> cache_dir . $file );
}
}
?>

tatupheba w Gmailu dot com

Cześć ludzie!

Wskazówka dla programistów:

Programując jakiś serwer mydła, ustaw dyrektywę „soap.wsdl_cache_enabled” w pliku php.ini na 0:

Soap.wsdl_cache_enabled=0

W przeciwnym razie wyświetli się kilka dziwnych błędów informujących, że plik wsdl jest nieprawidłowy lub go brakuje.

Dzięki temu unikniesz mnóstwa niepotrzebnego bólu.

titan w phpdevshell dot org

Należy zauważyć, że jeśli otrzymasz błąd zwrotny: „Odniesienie do obiektu nie jest ustawione na instancję obiektu.”. Może to być spowodowane czymś tak prostym, jak przekazanie nieprawidłowych parametrów. Kiedy spojrzysz na ten XML:



strunowy
dataGodzina
dataGodzina

Twój kod powinien wyglądać mniej więcej tak:

próbować (
$opcje = tablica(
"soap_version" => SOAP_1_2 ,
„wyjątki” => prawda,
"ślad" => 1 ,
"cache_wsdl" => WSDL_CACHE_NONE
);
$klient = nowy Klient Soap( „http://example.com/doc.asmx?WSDL”, $opcje);
// Zwróć uwagę, gdzie w pliku XML znajdują się znaczniki „Get” i „Request”.
$results = $klient -> Pobierz (array("request" =>array("CustomerId" => "1234" )));
) catch (Wyjątek $e ) (
Echo "

Wyjątek Błąd!

" ;
echo $e -> getMessage();
}

$results = $klient -> Pobierz (array("request" =>array("CustomerId" => "842115" )));
?>

Jeśli plik WSDL zawiera parametr typu base64Binary, nie powinieneś używać funkcji base64_encode() podczas przekazywania zmiennych mydlanych. Podczas wykonywania żądania biblioteka SOAP automatycznie koduje Twoje dane w formacie Base64, więc w przeciwnym razie będziesz kodować je dwukrotnie.

Fragment WSDL:

$ciąg = „dane_które_chcesz_wysłać___jak_xml_in_soap”;
$mydło_dane = tablica(
"foo" => "pasek" ,
//"content" => base64_encode($string) // nie rób tego
"content" => $string //zrób to
);
$odpowiedź = $klient -> Wyślij ($soap_data );
?>

marcovtout w Hotmail Dot Com

Będąc nowym użytkownikiem SOAP, przez jakiś czas szukałem odpowiedzi, dlaczego moja wiadomość otrzymywała odpowiedź w SoapUI, ale nie w moim kodzie php. Konkretna usługa, do której się odnosiłem, daje komunikat HTTP 202 Accepted w przypadku powodzenia (brak odpowiedzi), ale zwraca komunikat SOAP w przypadku błędów.

Sytuacja:
Używając (uwierzytelnionego) połączenia klienta i pliku WDSL, wywołania SOAP typu „One-Way” nie dają nagłówka odpowiedzi, nawet jeśli oczekuje się odpowiedzi.

Rozwiązanie:
Wywołując konstruktor klienta, ustaw SOAP_WAIT_ONE_WAY_CALLS w $options["features"].

Tim w tdinternet dot com

PHP 5.2.11 nie wydaje się być zbyt wybredny w kwestii poprawności pliku WSDL.

Inni klienci SOAP narzekali na problemy ze schematem i przestrzenią nazw, podczas gdy SoapClient PHP działał całkowicie dobrze. Jednak naprawienie tych problemów dla innych klientów zepsuło SoapClient PHP do tego stopnia, że ​​obiekty przekazywane do metody SOAP stawały się pustymi tablicami na po stronie serwera.

Wyciągnięta lekcja: niektóre elementy miały przedrostek xsd, a inne nie — upewnij się, że Twój WSDL jest poprawny i spójny (używam poprawionego pliku WSDL_Gen.php).

James Dot Ellis w Gmailu Dot Com

Miałem problemy z uzyskaniem odpowiedzi z serwera SOAP Coldfusion, bez żadnych oczywistych problemów w używanym kliencie SoapClient.

W końcu odkryłem, że serwer akceptował tylko żądania SOAP 1.1, a nie 1.2. Nie jestem pewien, czy jest to ustawienie Coldfusion obejmujące cały system, ale jeśli trafisz na tę samą ścianę, spróbuj ustawić opcję SoapClient „soap_version” na stałą SOAP_1_1 (która jest wartością domyślną, ale moja miała domyślną wartość 1.2, ponieważ klient był ponownie używany do innej usługi )

ajcartmell w fonant dot com

Wydaje się, że występuje problem z określeniem pustych ciągów dla opcji proxy_host i proxy_port w najnowszych wersjach PHP (od wersji późniejszej niż 5.2.9 i równej lub wcześniejszej niż 5.2.11).

Podanie pustych wartości string dla proxy_host i proxy_port powoduje błędy typu „nie znaleziono hosta”: podanie NULL lub FALSE działa prawidłowo.

bhargav dot khatana w Gmailu dot com

Ponad tydzień zajęło mi wymyślenie, jak zaimplementować nagłówki WSSE (Web Service Security) w natywnym PHP SOAP. Nie ma zbyt wielu dostępnych zasobów na ten temat, dlatego pomyślałem o dodaniu tego tutaj dla korzyści społeczności.

Krok 1: Utwórz dwie klasy, aby utworzyć strukturę dla nagłówków WSSE

klasa clsWSSEAuth(
prywatny $Nazwa użytkownika ;
prywatne $Hasło ;
funkcja __construct ($nazwa użytkownika, $hasło) (
$this -> Nazwa użytkownika = $nazwa użytkownika;
$to -> Hasło = $hasło;
}
}

Klasa clsWSSEToken (
prywatny $NazwaUżytkownikaToken ;
funkcja __construct ($innerVal)(
$this -> UsernameToken = $innerVal;
}
}
?>
Krok 2: Utwórz zmienne mydlane dla nazwy użytkownika i hasła

$nazwa użytkownika = 1111 ;
$hasło = 1111 ;

//Sprawdź u swojego dostawcy, jakiej przestrzeni nazw zabezpieczeń używa.
$strWSSENS = „http://schemas.xmlsoap.org/ws/2002/07/secext”;

$objSoapVarUser = nowy SoapVar($nazwa użytkownika, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
$objSoapVarPass = nowy SoapVar($hasło, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
?>
Krok 3: Utwórz obiekt dla klasy Auth i przekaż mydło var

$objWSSEAuth = nowy clsWSSEAuth ($objSoapVarUser, $objSoapVarPass);
?>
Krok 4: Utwórz SoapVar z obiektu klasy Auth

$objSoapVarWSSEAuth= nowy SoapVar ($objWSSEAuth, SOAP_ENC_OBJECT, NULL, $strWSSENS, „UsernameToken”, $strWSSENS);
?>
Krok 5: Utwórz obiekt dla klasy Token

$objWSSEToken = nowy clsWSSEToken ($objSoapVarWSSEAuth);
?>
Krok 6: Utwórz SoapVar z obiektu klasy Token

$objSoapVarWSSEToken= nowy SoapVar ($objWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, "UsernameToken", $strWSSENS);
?>
Krok 7: Utwórz SoapVar dla węzła „Bezpieczeństwo”.

$objSoapVarHeaderVal=nowy SoapVar ($objSoapVarWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, "Bezpieczeństwo", $strWSSENS);
?>
Krok 8: Utwórz obiekt nagłówka z mydła zabezpieczającego

Nagłówek $objSoapVarWSSE= nowy SoapHeader ($strWSSENS, „Bezpieczeństwo”, $objSoapVarHeaderVal, true, „http://abce.com”);

//Trzeci parametr tutaj tworzy „mustUnderstand=1
//Parametr Forth generuje „actor="http://abce.com ""
?>
Krok 9: Utwórz obiekt klienta Soap

$objClient = nowy SoapClient ($WSDL, $arrOptions);
?>
Krok 10: Ustaw nagłówki dla obiektu mydlanego klienta

$objClient -> __setSoapHeaders (tablica($objSoapVarWSSEHeader ));
?>
Krok 11: Ostateczne wywołanie metody

$objResponse = $objClient -> __soapCall ($strMethod, $requestPayloadString);
?>

Peter z webacoustics dot com

Odkryłem, że pobieranie WSDL kończy się niepowodzeniem, gdy używane jest podstawowe uwierzytelnianie w kliencie mydlanym. Zaimplementowałem więc następujące obejście, używając wget. Zdaję sobie sprawę, że wget może nie być opcją w niektórych środowiskach, w takim przypadku cURL byłby następną najprostszą rzeczą.

$wsdl = get_wsdl ( „https://example.com/soap/service?wsdl”);
$this -> klient = nowy SoapClient ($wsdl, array("user" => "someuser" , "hasło" => "jakiehasło" ));

Funkcja prywatna get_wsdl ($url) (
globalny $g ;
$url = escapeshellarg($url);
$cache_file = "/tmp/soap.wsdl." . md5($url);

//pobieraj tylko nowy plik WSDL co godzinę
if(! file_exists ($cache_file ) || filectime ($cache_file )< time () - 3600 ) {
$agent = escapeshellarg("--user-agent=($g["useragent"])");
mwexec("wget ​​--quiet --timeout=5 ( $agent ) --no-check-certificate --output-document=($plik_pamięci podręcznej) ($url) ");
if(! plik_istnieje ($plik_pamięci podręcznej )) (
rzuć nowy wyjątek („Nie można załadować WSDL pod adresem ( $url )” );
}
}
powrót
$plik_pamięci podręcznej ;
}
?>

Meltir w Meltir Dot Com

Dla tych, którzy walczą z serwerami proxy uwierzytelnianymi NTLM, oto rozwiązanie, którego używam atm:

/**
* Dziecko SoapClient z obsługą uwierzytelniania proxy ntlm
*
* @autor Meltir
*
*/
klasa NTLM_SoapClient rozszerza SoapClient (

Funkcja publiczna __construct ($wsdl, $options = array()) (
if (empty($options [ "proxy_login" ]) || pusty($options [ "proxy_password" ])) rzuć nowy wyjątek ( „Do uwierzytelnienia NTLM wymagany jest login i hasło!”);
$this -> proxy_login = $opcje [ "proxy_login" ];
$this -> proxy_password = $options [ "proxy_password" ];
$this -> proxy_host = (puste($opcje [ "proxy_host" ]) ? "Lokalny Gospodarz": $opcje[ „host_proxy”]);
$to-> Port proxy= (pusty($opcje[ "Port proxy"]) ? 8080 : $opcje[ "Port proxy"]);
rodzic:: __skonstruować($wsdl, $opcje);
}

/**
* Wywołaj adres URL za pomocą curl z uwierzytelnianiem ntlm
*
* @param ciąg $url
* @param ciąg $dane
* @ciąg zwrotny
* @rzuca SoapFault w przypadku błędu połączenia curl
*/
funkcja chronionazadzwońCurl($url, $dane) {
$uchwyt= curl_init();
curl_setopt($uchwyt, CURLOPT_HEADER, FAŁSZ);
curl_setopt($uchwyt, CURLOPT_URL, $url);
curl_setopt($uchwyt, CURLOPT_FAILONERROR, PRAWDA);
curl_setopt($uchwyt, CURLOPT_HTTPHEADER,Szyk(„Klient PHP SOAP-NTLM”));
curl_setopt($uchwyt, TRANSFER CURLOPT_RETURN, PRAWDA);
curl_setopt($uchwyt, CURLOPT_POSTFIELDS, $dane);
curl_setopt($uchwyt, CURLOPT_PROXYUSERPWD, $to-> proxy_login. ":" . $to-> hasło_proxy);
curl_setopt($uchwyt, CURLOPT_PROXY, $to-> proxy_host. ":" . $to-> Port proxy);
curl_setopt($uchwyt, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
$odpowiedź= curl_exec($uchwyt);
jeśli (puste(
$odpowiedź)) {
wrzucić nowe
Błąd mydła(„Błąd CURL:”. curl_error($uchwyt), curl_errno($uchwyt));
}
curl_close($uchwyt);
powrót
$odpowiedź;
}

Funkcja publiczna __doŻądanie($prośba, $lokalizacja, $akcja, Wersja $, $w jedną stronę= 0 ) {
powrót
$to-> zadzwońCurl($lokalizacja, $prośba);
}

}
?>

Wymaga zwijania i można go przedłużyć, ale działa na moje proste potrzeby.

Eric Dot Caron w Gmailu Dot Com

Myśl wskazana przez Jana w bestbytes i omówiona w błędzie nr 27777, jednym z częstych źródeł komunikatu „Parsing WSDL: Nie udało się znaleźć” " błąd wynika z próby uzyskania dostępu do pliku WSDL chronionego przez uwierzytelnianie HTTP. Przekazanie loginu/hasła w drugim parametrze nie zawsze działa; więc jeśli napotkasz ten komunikat o błędzie i spróbujesz uzyskać dostęp do chronionego pliku WSDL, spróbuj przekazać nazwę użytkownika i hasło w pierwszym parametrze.

Anonimowy

Musiałem zmagać się z dość dziwnym zachowaniem, gdy próbowałem bezskutecznie korzystać ze standardowych usług sieciowych Parlay X. Znalazłem jednak lekarstwo na mój problem.

Problem, z którym się spotkałem, dotyczył błędnego, nieprawidłowego żądania podstawowego uwierzytelnienia HTTP wysłanego do usługi internetowej. Mimo że wysłałem prawidłowe dane uwierzytelniające, wystąpił błąd uwierzytelnienia. Okazuje się, że PHP wysyłał żądania HTTP do innego punktu końcowego, który nie jest udostępniany bezpośrednio przez usługę internetową i ten punkt końcowy nie wymaga uwierzytelnienia.

Moim rozwiązaniem tego problemu było użycie tych prostych linii w przykładzie użycia metody sendSms Paraly-X.

Najpierw utwórz klienta mydła bez żadnych opcji uwierzytelniania HTTP:

$klient= nowyKlient Mydła($wsdl_url);
?>

Powyższe żądanie buforuje plik wsdl w katalogu /tmp. Zaraz po tej konstrukcji tworzymy kolejnego klienta mydła, tym razem z opcjami uwierzytelniania HTTP:

próbować (
$klient= nowyKlient Mydła($wsdl_url, tablica("Zaloguj sie"=> "Gryf",
"hasło"=> "hasło"));
) złapać (
Wyjątek $e) {
drukuj(„Błąd: wyślij SMS: %s\n”, $e-> __do ciągu());
powrót
FAŁSZ;
}
?>

Teraz powinno działać bez problemu. Bez drugiego wywołania PHP wywoła sendSms bez poświadczeń, co zakończy się nieudaną próbą z powodu braku informacji uwierzytelniających. Uważam, że ta procedura jest najprostsza.

Ten proces powinien być wykonywany za każdym razem, gdy wygaśnie buforowany plik wsdl lub po prostu można wydłużyć czas życia buforowanego pliku wsdl z php.ini

Jon Dot Gilbert i Net-entwicklung Dot de

Zauważ, że utworzenie klienta mydła dla nieprawidłowego adresu URL (testujesz, co się dzieje, gdy usługa jest niedostępna, prawda?) zazwyczaj generuje wyjątek, który można przechwycić za pomocą try..catch. Jeśli jednak xdebug jest aktywny, pojawi się błąd krytyczny, którego oczywiście nie można przechwycić.

slooem w Gmailu dot com

Miałem problem z omówieniem użycia mapy klas, którego rozwiązanie zajęło mi sporo czasu. Zakładałem, że typ WSDL, do którego odnosili się dokumenty, był nazwą elementu zwracanego w SOAP, więc tak:

I zastanawiałem się, dlaczego mapowanie
"classmap"=>array("node"=>"MójNode")

Nic nie zrobił.
Dzieje się tak, ponieważ w moim WSDL zdefiniowałem węzeł jako:

Mapa klas, której potrzebowałem, to:
"classmap"=>array("nodeType"=>"Mójwęzeł")

Udało mi się znaleźć nazwy typów za pomocą SoapClient->__getTypes()
Później zdałem sobie sprawę, gdzie mogę zajrzeć do WSDL w poszukiwaniu potrzebnej nazwy typu.

Nie wiem, czy przeoczyłem coś boleśnie oczywistego, ale może to wyjaśni niektóre dokumenty.

Jon

Wystąpiły pewne problemy podczas korzystania z SoapClient łączącego się z serwerem zewnętrznym za pośrednictwem Microsoft ISA (obecnie wersja 2006, ale może to dotyczyć również innych wersji). Podajemy proxy_host, proxy_port, proxy_login i proxy_password, ale serwer ISA zgłasza logowanie w swoim loguje się jako „anonimowy”.

Nasz administrator systemu uważa, że ​​dzieje się tak dlatego, że PHP nie dostarcza informacji NTLN (protokół bezpieczeństwa Windows) w odpowiednim formacie (a to, czy powinno działać z zastrzeżonymi serwerami proxy, to oczywiście inna debata). Próbowaliśmy „nazwa użytkownika”, „DOMENA\nazwa_użytkownika” bez skutku. Rozwiązaniem jest dodanie wyjątku na serwerze ISA dla docelowej nazwy hosta/IP; wówczas można podać wartość null dla loginu_proxy i hasła_proxy, a połączenie powinno wtedy działać zgodnie z oczekiwaniami.

A propos, jeśli masz problemy, upewnij się, że numer portu jest podany jako liczba całkowita. Niektóre wersje PHP nie będą używać proxy z SoapClient, jeśli numer portu zostanie podany w postaci ciągu znaków.

sty w bestbytes dot de

MOŻESZ uzyskać wsdl, jeśli wymagane jest podstawowe uwierzytelnienie:

$logowanie = „bert”;
$hasło= „hasło Berta”;

$klient= nowyKlient Mydła(
„http://”. kod urlenowy($logowanie) . ":" . kod urlenowy($hasło) . „@www.server.com/ścieżka/do/wsdl”,
szyk(
"Zaloguj sie"=> $logowanie,
"hasło"=> $hasło
)
);

?>

informacje na stronie nickssilvestro dot net

Dla każdego, kto ma problemy z ArrayOf_xsd_string i otrzymuje błąd podobny do „Nie zdefiniowano deserializatora dla typu tablicy (http://www.w3.org/2001/XMLSchema)string”
Spróbuj użyć parametru „features” ustawionego na SOAP_USE_XSI_ARRAY_TYPE — dzięki temu zostanie użyty właściwy deserializator.

Np,
$klient= nowyKlient Mydła(„niektóre.wsdl”, tablica("cechy"=> SOAP_USE_XSI_ARRAY_TYPE));
?>

snajper

szukałem dobrego przykładu i nie mogłem znaleźć,
w końcu znalazłem to gdzieś (zapomniałem gdzie), myślę, że to jest to
najlepszy przykład żądania mydła z wieloma parametrami

$params->AWSAccessKeyId = AMAZON_API_KEY;
$params->Request->SearchIndex = "Książki";
$params->Request->Keywords = "php5 oop";

$amazon = nowy SoapClient("http://webservices.amazon.com
/AWSECommerceService/AWSECommerceService.wsdl");
$result = $amazon->itemSearch($params);

alex na reutone przecinek com

Aby połączyć PHP SOAP z MS SOAP (CRM/EXCHANGE/...) stworzyłem kilka klas, korzystając z wyjaśnień poniżej i w innych miejscach.
www.reutone.com/heb/articles.php?instance_id=62&actions=show&id=521

naugtur w Gmailu dot com

Wyjątek SoapFault: wygląda na to, że nie mamy dokumentu XML zostało już wspomniane, że ma to miejsce, gdy serwer wysyła coś wcześniej ... > etykietka.

Dla wszystkich, którzy mają z tym problemy, Ibrak dostępu do kodu serwera:
Oto jak utworzyć serwer proxy, który będzie czyścić odpowiedziDoTy

php
/**
* Proste zajęcia zaczerpnięte z notatki Jamesa Ellisa
*/
klasaKlient proxyrozciąga sięKlient Mydła{
chroniony
Dokument $cache= "" ;
funkcję publiczną
__skonstruować($wsdl, $opcje) {
rodzic:: __skonstruować($wsdl, $opcje);
}

/**
* SetCacheDocument() ustawia zawartość wcześniej buforowanego dokumentu
*/
funkcję publicznąUstaw dokument pamięci podręcznej($dokument) {
$to-> dokument pamięci podręcznej= $dokument;
}

/**
* __doRequest() zastępuje standardową metodę SoapClient w celu obsługi żądania lokalnego
*/
funkcję publiczną__doŻądanie() {
powrót
$to-> dokument pamięci podręcznej;
}
}

//umieść ten kod w swojej funkcji lub gdziekolwiek masz ustawione wszystkie wymagane zmienne

$klient= nowyKlient Mydła($wsdl_url, $ustawienia_tablica);
$pustka= $klient-> $metoda($parametry); //wywołaj tę opcję, aby uzyskać odpowiedź z serwera

$ciąg_odpowiedzi= $klient-> __getLastResponse();

//ta część usuwa rzeczy
$start= strpos($ciąg_odpowiedzi, ");
koniec= strpo($ciąg_odpowiedzi, ">" );
$ciąg_odpowiedzi= substr($ciąg_odpowiedzi, $start, koniec- $start+ 1 );

//Przygotuj serwer proxy
$proxy= nowyKlient proxy($wsdl_url, $ustawienia_tablica);
//i wypełnij go odpowiedzią serwera
$proxy-> Ustaw dokument pamięci podręcznej($ciąg_odpowiedzi);

$and_finally_the_result_is= $proxy-> $metoda($parametry);

drukuj_r($and_finally_the_result_is); //to pozwala zobaczyć, co tam jest

?>

$method to nazwa metody, np. $method="getVersion";
$params - typowe parametry metody mydlanej

Wskazówki dla użytkowników:

    Jeśli znasz plik WSDL, możesz skonfigurować szybkie łącze do formularzy klienta za pomocą
    http://www.?template=/clientform.html&fn=soapform
    &SoapTemplate=brak&SoapWSDL=Twój_WSDL_plik
    Lub
    http://www..html?SoapWSDL=Twój_WSDL_plik

    Serwer buforuje pliki WSDL podczas normalnych operacji, aby poprawić wydajność. Jeśli dokonasz jakichkolwiek zmian w pliku WSDL, wybierz opcję NIE pole wyboru.

Wskazówki dla programistów:

    Używać<dokumentacja> jeśli to możliwe, w pliku WSDL, aby podać instrukcje. Zostanie on wyświetlony w formularzu klienta.

    Użyj typu wyliczeniowego, jeśli element ma stałą liczbę wartości. Będą one wyświetlane jako pola rozwijane.

Kluczowe cechy:

    Obsługa schematu XML z 1999 r. i 2001 r. Narzędzie do konstruowania żądań SOAP wykorzystuje schemat zdefiniowany w pliku WSDL.

    Tablica wsparcia i tablica struktur. Obsługiwane są tylko tablice jednowymiarowe. Niestety, nie ma rzadkich tablic.

    Możliwość serializacji złożonych typów danych i tablic złożonych typów danych, nawet wielopoziomowych struktur osadzonych.

    Obsługa identyfikatorów/HREF zarówno w komunikatach SOAP, jak i definicjach schematów.

    Obsługuje zarówno sekcję 5/7 protokołu SOAP, jak i kodowanie dokumentów/literałów.

Szczegóły techniczne-- Dynamiczne wiązanie usług SOAP

Powiązanie to kontrakt pomiędzy logiką klienta i logiką serwera. W protokole SOAP istnieją dwa typy powiązań: powiązanie obiektów (lub powiązanie SOAP) i powiązanie parametrów. Większość zestawów narzędzi SOAP wykonuje powiązania obiektów statycznych, generując obiekty proxy po stronie klienta. Problem polega na tym, że w przeciwieństwie do tradycyjnego modułu programistycznego, w którym obiekty/interfejsy są stabilne, usługi sieciowe mogą ulec zmianie w dowolnym momencie bez powiadomienia, ponieważ często są własnością osób trzecich lub są przez nie kontrolowane. Inny problem pojawia się, gdy wzrasta liczba dostępnych usług internetowych, a wygenerowany kod źródłowy może szybko stać się koszmarem w utrzymaniu. Wreszcie, gdy usługi internetowe, do których należy uzyskać dostęp, są nieznane, co jest częstsze niż prawdopodobne, wcześniejsze powiązanie staje się niemożliwe lub przynajmniej trudne. Wygenerowanie obiektu proxy dla usługi, która ma zostać zbudowana w przyszłości, jest interesującym projektem badawczym.

Ogólny klient SOAP demonstruje dynamiczne powiązania (lub powiązania w czasie wykonywania) usług i parametrów SOAP. Obiekt generowany jest w momencie wykonania, gdy podany jest plik WSDL, a wartości parametrów są kojarzone z komunikatem SOAP tuż przed dostarczeniem. Technika późnego wiązania (lub opóźnionego wiązania) może znacznie zmniejszyć koszty konserwacji, ponieważ jednego klienta można używać do uzyskiwania dostępu do wielu usług sieciowych.

W LeaseWeb dużo pracujemy z usługami sieciowymi SOAP, aby zintegrować ze sobą nasze wewnętrzne aplikacje. Zwłaszcza podczas tworzenia i testowania naszych aplikacji, ponieważ potrzebujemy umiejętności ćwiczenia z API SOAP.

$ curl -sS http://leaseweb.github.io/php-soap-client/installer | php

Spowoduje to pobranie pliku phar do bieżącego katalogu roboczego i uczyni go wykonywalnym, dzięki czemu będziesz mógł od razu zacząć go używać, wywołując:

$ ./soap_client

Aby zainstalować najnowszą wersję główną, możesz pobrać kod źródłowy bezpośrednio z GitHuba, spakować własny plik .phar i zainstalować go - używając GNU Make.
Aby móc utworzyć plik .phar, musisz mieć zainstalowany kompozytor. Aby dowiedzieć się więcej o kompozytorze, zapoznaj się z jego doskonałą dokumentacją.

# Zainstaluj klienta mydła php $ git clone https://github.com/LeaseWeb/php-soap-client.git $ cd php-soap-client $ Composer.phar install $ make $ Sudo make install

Jeśli podczas działania otrzymujesz wyjątek Nie udało się skompilować phar, musisz ustawić phar.readonly = Off w swoim php.ini. Na komputerze programistycznym jest to w porządku, ale należy pamiętać o ryzyku bezpieczeństwa podczas ustawiania phar.readonly na Off.

Powyższe polecenie make install zainstaluje aplikację mydło_klient w katalogu /usr/local/bin i uczyni ją wykonywalną, dzięki czemu będzie można ją łatwo nazwać w ten sposób:

$ wash_client php-soap-client wersja 2.1.3 Sposób użycia: polecenie Opcje: ... Dostępne polecenia: call Wywołuje zdalną usługę z określoną `metodą` i wysyła odpowiedź na standardowe wyjście. pomoc Wyświetla pomoc dotyczącą listy poleceń. Wyświetla listę poleceń. list-methods. Wyświetla listę dostępnych metod, które można wywołać na pilocie. request Wygeneruj żądanie SOAP w formacie XML dla danej metody i wyprowadź dane na standardowe wyjście. wsdl Pobierz WSDL usługi mydlanej.

Od tego momentu zakładamy, że zainstalowałeś mydło_client.phar w swoim systemie w /usr/local/bin/soap_client i że katalog /urs/local/bin znajduje się w $PATH .

Powiedzmy, że chcielibyśmy zobaczyć, jakie metody są dostępne w zdalnym serwisie http://www.webservicex.net/ConvertTemperature.asmx. Moglibyśmy wydać następujące polecenie:

$ mydło_klient --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" metody list

Który wyświetli następujące informacje:

KonwertujTemp

Jeśli uruchomisz powyższe polecenie z opcją -vvv, otrzymasz bardziej szczegółowe dane wyjściowe.
W tym przypadku jedyną dostępną metodą jest ConvertTemp . Zobaczmy jak wygląda żądanie SOAP XML dla tej metody:

$ mydło_klient --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" żądanie ConvertTemp 0

Jeśli chcesz wysłać żądanie SOAP do metody ConvertTemp w usłudze zdalnej, użyj polecenia call sub:

$ mydło_klient --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" wywołanie --edytor ConvertTemp

Zwróć uwagę na opcję --editor znajdującą się po poleceniu wywołania. Jeśli użyjesz flagi --editor, mydło_klient otworzy edytor określony w zmiennej środowiskowej $EDITOR, dzięki czemu będziesz mógł zmodyfikować plik XML żądania przed jego wysłaniem.

Jeśli wielokrotnie wysyłasz to samo żądanie, możesz zapisać żądanie mydła jako lokalny plik XML i przekazać je do /dev/stdin polecenia wywołania mydła_klienta:

# Pobierz plik xml żądania i zapisz go lokalnie $ mydło_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" request ConvertTemp > my_sample_request.xml # Teraz edytuj my_sample_request.xml # Teraz możesz wywołać Metoda ConvertTemp z tym wstępnie przygotowanym żądaniem $ mydło_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" wywołanie ConvertTemp< my_sample_request.xml

Ponieważ podczas eksplorowania zdalnej usługi internetowej będziesz często powtarzał polecenia Soap_client w krótkim czasie, możesz zaoszczędzić trochę czasu, ustawiając zmienną środowiskową SOAPCLIENT_ENDPOINT zawierającą adres URL pliku WSDL. Gdy ta zmienna środowiskowa jest ustawiona, można pominąć opcję wiersza poleceń --endpoint. Zróbmy to teraz i wywołajmy metodę ConvertTemp:

$ eksport SOAPCLIENT_ENDPOINT="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" $ połączenie klienta z mydłem ConvertTemp< my_sample_request.xml

Chciałem wiedzieć, ile 107,6 stopni Fahrenheita jest wyrażonych w stopniach Celsjusza, więc mój plik my_sample_request.xml zawiera:

$ kot moje_przykładowe_żądanie.xml 107.6 stopień Fahrenheita stopień Celsjusza

$ mydło_klient wywołanie ConvertTemp< my_sample_request.xml stdClass Object ( => 42)

Odpowiedź brzmi 42.

Jeśli wolisz widzieć odpowiedzi w formacie XML, możesz użyć opcji wiersza poleceń --xml:

$ wywołanie klienta_mydła --xml ConvertTemp< my_sample_request.xml 42

Ten samouczek powinien dostarczyć Ci wystarczających informacji, aby rozpocząć eksplorację, testowanie i/lub tworzenie interfejsów API SOAP.
W przyszłym poście na blogu będę kontynuował temat klienta mydła php. Obecnie pracujemy nad pakowaniem archiwum .phar do użytku w Internecie.

Część liryczna.

Wyobraź sobie, że wdrożyłeś lub wdrażasz pewien system, który powinien być dostępny z zewnątrz. Te. istnieje określony serwer, z którym musisz się komunikować. Na przykład serwer WWW.

Serwer ten może wykonywać wiele działań, pracować z bazą danych, wykonywać żądania stron trzecich do innych serwerów, wykonywać pewne obliczenia itp. żyć i ewentualnie rozwijać się według znanego mu scenariusza (czyli według scenariusza deweloperów). Komunikowanie się z takim serwerem nie jest interesujące dla osoby, ponieważ może ona nie być w stanie/chcieć udostępniać pięknych stron ze zdjęciami i inną przyjazną dla użytkownika treścią. Jest napisany i działa tak, aby działał i dostarczał danych na żądanie, bez obawy, że będzie czytelny dla człowieka, klient sam sobie z tym poradzi.

Inne systemy uzyskujące dostęp do tego serwera mogą już według własnego uznania dysponować danymi otrzymanymi z tego serwera - przetwarzać, gromadzić, wydawać swoim klientom itp.

Otóż ​​jedną z opcji komunikacji z takimi serwerami jest SOAP. Protokół wymiany komunikatów XML SOAP.

Część praktyczna.

Usługa internetowa (tak nazywa się to, co udostępnia serwer i z czego korzystają klienci) umożliwia komunikację z serwerem za pomocą przejrzyście ustrukturyzowanych komunikatów. Faktem jest, że serwis internetowy nie przyjmuje żadnych danych. Na każdą wiadomość niezgodną z regulaminem serwis odpowie błędem. Notabene błąd będzie także w formie xml z przejrzystą strukturą (co nie dotyczy tekstu wiadomości).

WSDL (język opisu usług internetowych). Zasady tworzenia komunikatów dla serwisu internetowego są również opisane za pomocą XML i również mają przejrzystą strukturę. Te. Jeśli usługa internetowa zapewnia możliwość wywołania metody, musi umożliwiać klientom poznanie parametrów używanych w tej metodzie. Jeżeli usługa WWW oczekuje jako parametru ciągu znaków dla Metody 1, a ciąg powinien mieć nazwę Param1, wówczas reguły te zostaną określone w opisie usługi WWW.

Jako parametry można przekazywać nie tylko proste typy, ale także obiekty i kolekcje obiektów. Opis obiektu sprowadza się do opisu każdego elementu składowego obiektu. Jeżeli obiekt składa się z kilku pól, to każde pole jest opisane, jego typ, nazwa (jakie są możliwe wartości). Pola mogą być również typu złożonego i tak dalej, aż opis typów zakończy się prostymi - string, boolean, number, date... Jednak niektóre specyficzne typy mogą okazać się proste, ważne jest, aby klienci może zrozumieć, jakie wartości mogą zawierać.

Klientom wystarczy znać adres URL usługi internetowej; plik wsdl będzie zawsze w pobliżu, dzięki czemu można zorientować się w metodach i ich parametrach udostępnianych przez tę usługę internetową.

Jakie są zalety tych wszystkich bajerów:

  • W większości systemów opis metod i typów następuje automatycznie. Te. programista na serwerze musi tylko powiedzieć, że tę metodę można wywołać poprzez usługę internetową, a opis wsdl zostanie wygenerowany automatycznie.
  • Opis, który ma przejrzystą strukturę, jest czytelny dla każdego klienta mydła. Te. niezależnie od usługi internetowej, klient będzie wiedział, jakie dane otrzymuje usługa internetowa. Korzystając z tego opisu Klient może zbudować własną wewnętrzną strukturę klas obiektów, tzw. bind” i. W rezultacie programista korzystający z serwisu WWW musi napisać coś takiego (pseudokod):

    NewUser:=TSoapUser.Create("Vasya","Pupkin","admin"); mydło.AddUser(NowyUżytkownik);

  • Automatyczna walidacja.

    • Walidacja XML. xml musi być dobrze sformułowany. Nieprawidłowy xml - od razu błąd dla klienta, niech to rozwiąże.
    • walidacja schematu. xml musi mieć określoną strukturę. xml nie pasuje do schematu - od razu błąd dla klienta, niech to rozwiąże.
    • Weryfikacja danych przeprowadzana jest przez serwer Sodła, aby typy danych i ograniczenia były zgodne z opisem.
  • Autoryzację i uwierzytelnianie można wdrożyć oddzielną metodą. natywnie. lub korzystając z autoryzacji http.
  • Usługi sieciowe mogą działać zarówno poprzez protokół mydła, jak i poprzez http, czyli poprzez żądania get. Oznacza to, że jeśli parametry są prostymi danymi (bez struktury), możesz po prostu wywołać zwykły get www.site.com/users.asmx/GetUser?Name=Vasia lub post. Jednak nie wszędzie i nie zawsze tak się dzieje.
  • ... zobacz w Wikipedii

Istnieje również wiele wad:

  • Nieracjonalnie duży rozmiar wiadomości. Cóż, tutaj natura xml jest taka, że ​​format jest zbędny, im więcej tagów, tym więcej bezużytecznych informacji. Plus mydło dodaje mu redundancji. W przypadku systemów intranetowych problem ruchu jest mniej dotkliwy niż w przypadku Internetu, dlatego zapotrzebowanie na mydło dla sieci lokalnych jest większe, w szczególności Sharepoint ma usługę sieciową mydła, za pomocą której można się z powodzeniem komunikować (z pewnymi ograniczeniami).
  • Automatyczna zmiana opisu usługi internetowej może zepsuć wszystkich klientów. Cóż, tak jest z każdym systemem, jeśli nie będzie obsługiwana kompatybilność wsteczna ze starymi metodami, wszystko przepadnie…
  • Nie minus, ale wada. Wszystkie wywołania metod muszą być niepodzielne. Na przykład podczas pracy z bazą danych możemy rozpocząć transakcję, wykonać kilka zapytań, a następnie wycofać lub zatwierdzić. W mydle nie ma transakcji. Jedna prośba, jedna odpowiedź i rozmowa zakończona.
  • Radzenie sobie z opisem tego, co jest po stronie serwera (czy wszystko jest opisane poprawnie?) i tego, co jest po stronie klienta (co mi tutaj opisano?) może być dość trudne. Kilka razy miałem do czynienia ze stroną klienta i przekonywałem programistę serwera, że ​​jego dane zostały opisane błędnie, ale on w ogóle nic z tego nie rozumiał, bo automatyczne generowanie a nie powinien, to kwestia oprogramowanie. Błąd oczywiście tkwił w kodzie metody; programista po prostu go nie zauważył.
  • Praktyka pokazuje, że twórcom serwisów internetowych strasznie daleko jest do ludzi korzystających z tych serwisów. W odpowiedzi na dowolne żądanie (ważne z zewnątrz) może pojawić się niezrozumiały błąd „Błąd 5. Wszystko jest źle”. Wszystko zależy od sumienia deweloperów :)
  • Pewnie nadal czegoś nie pamiętam...

Jako przykład można podać otwarty serwis internetowy Belavia:

  • http://86.57.245.235/TimeTable/Service.asmx - punkt wejścia, znajduje się tam również tekstowy opis metod dla zewnętrznych programistów.
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL - wsdl opis metod i typów odbieranych i zwracanych danych.
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList - opis konkretnej metody z przykładem typu żądania xml i odpowiedzi xml.

Możesz ręcznie utworzyć i wysłać żądanie, takie jak:

POST /TimeTable/Service.asmx HTTP/1.1 Host: 86.57.245.235 Typ zawartości: tekst/xml; charset=utf-8 Długość treści: długość Akcja SOAPA: „http://webservices.belavia.by/GetAirportsList” ru

nadejdzie odpowiedź:

HTTP/1.1 200 OK Data: pon., 30 września 2013 r. 00:06:44 GMT Serwer: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-wersja: 4.0.30319 Kontrola pamięci podręcznej: prywatna, maks. -age=0 Typ zawartości: tekst/xml; charset=utf-8 Długość zawartości: 2940

PS Wcześniej otwarto usługę internetową Aeroflot, ale po tym, jak 1C dodało obsługę mydła do 8ku, grupa beta testerów 1C pomyślnie ją zainstalowała. Teraz coś się tam zmieniło (nie znam adresu, możesz poszukać jeśli jesteś zainteresowany).
Zastrzeżenie ZZY. Mówił na poziomie codziennym. Możesz kopać.

Cześć wszystkim!
Tak się złożyło, że ostatnio zacząłem rozwijać usługi internetowe. Ale dzisiaj temat nie jest o mnie, ale o tym, jak możemy napisać własny XML Web Service w oparciu o protokół SOAP 1.2.

Mam nadzieję, że po przeczytaniu tematu będziesz potrafił:

  • napisać własną implementację serwerową aplikacji internetowej;
  • napisać własną kliencką implementację aplikacji internetowej;
  • napisz własny opis usługi internetowej (WSDL);
  • wysyłaj tablice klienckie tego samego typu danych na serwer.

Jak można się domyślić, cała magia zostanie wykonana przy użyciu PHP i wbudowanych klas SoapClient i SoapServer. Nasz królik będzie usługą wysyłania wiadomości SMS.

1 Opis problemu

1.1 Granice

Na początek proponuję zająć się efektem, który osiągniemy na koniec tematu. Zgodnie z zapowiedzią powyżej napiszemy usługę wysyłania wiadomości SMS, a dokładniej będziemy odbierać wiadomości z różnych źródeł za pośrednictwem protokołu SOAP. Następnie zastanowimy się, w jakiej formie docierają na serwer. Proces kolejkowania wiadomości do dalszego dostarczenia do dostawcy niestety z wielu powodów wykracza poza zakres tego wpisu.

1.2 Jakie dane będziemy zmieniać?

Świetnie, ustaliliśmy granice! Kolejnym krokiem, jaki należy podjąć, jest podjęcie decyzji, jakie dane będziemy wymieniać pomiędzy serwerem a klientem. W tym temacie radzę nie dzielić włosa na czworo i od razu odpowiedzieć sobie na główne pytania:

  • Jakie minimum danych należy przesłać na serwer, aby wiadomość SMS została wysłana do abonenta?
  • Jakie minimalne dane muszą zostać przesłane z serwera, aby zaspokoić potrzeby klienta?

Coś mi mówi, że w tym celu należy wysłać:

  • numer telefonu komórkowego i
  • treść wiadomości SMS.

W zasadzie te dwie cechy wystarczą do wysłania, ale od razu wyobrażam sobie przypadek SMS-a z życzeniami urodzinowymi, który przychodzi do Ciebie o 3 lub 4 nad ranem! W tym momencie będę bardzo wdzięczna wszystkim, którzy o mnie nie zapomnieli! Dlatego wyślemy również na serwer i

  • data wysłania wiadomości SMS.

Następną rzeczą, którą chciałbym wysłać na serwer, jest:

  • Typ wiadomości.

Parametr ten nie jest obowiązkowy, ale może nam się bardzo przydać, jeśli chcemy szybko powiedzieć szefowi, ilu naszych klientów „zachwyciliśmy” naszymi nowościami, a także narysować piękne statystyki na ten temat.

A mimo to o czymś zapomniałem! Jeśli zastanowimy się trochę głębiej, warto zauważyć, że klient może wysłać na serwer albo jedną wiadomość SMS, albo kilka z nich na raz. Innymi słowy, jeden pakiet danych może zawierać od jednego do nieskończonej liczby wiadomości.

W rezultacie otrzymujemy, że do wysłania wiadomości SMS potrzebujemy następujących danych:

  • Numer telefonu komórkowego,
  • treść wiadomości SMS,
  • czas wysłania wiadomości SMS do abonenta,
  • typ wiadomości.

Odpowiedzieliśmy na pierwsze pytanie, teraz musimy odpowiedzieć na drugie pytanie. A może pozwolę sobie na małe zamieszanie. Dlatego z serwera wyślemy tylko dane logiczne, których znaczenie ma następujące znaczenie:

  • TRUE – pakiet pomyślnie dotarł do serwera, przeszedł uwierzytelnienie i znalazł się w kolejce do wysłania do dostawcy SMS
  • FAŁSZ – we wszystkich pozostałych przypadkach

Na tym kończy się opis problemu! I na koniec przejdźmy do zabawnej części – zastanówmy się, jaką dziwną bestią jest to SOAP!

2 Co to jest SOAP?

Generalnie początkowo nie planowałem nic pisać o tym czym jest SOAP i chciałem ograniczyć się do linków do strony w3.org z niezbędnymi specyfikacjami, a także linków do Wikipedii. Ale na sam koniec postanowiłem napisać krótką notatkę na temat tego protokołu.

A moją opowieść zacznę od tego, że ten protokół wymiany danych należy do podzbioru protokołów opartych na tzw. paradygmacie RPC (Remote Procedury Call), którego antypodą jest REST (Representational State Transfer). Więcej na ten temat można przeczytać w Wikipedii, linki do artykułów znajdują się na samym końcu tematu. Z tych artykułów musimy zrozumieć, co następuje: „Podejście RPC pozwala na wykorzystanie niewielkiej liczby zasobów sieciowych przy dużej liczbie metod i złożonym protokole. Dzięki podejściu REST liczba metod i złożoność protokołów są ściśle ograniczone, co oznacza, że ​​liczba poszczególnych zasobów może być duża.” Czyli w odniesieniu do nas oznacza to, że na stronie w przypadku podejścia RPC zawsze będzie jedno wejście (link) do usługi i jaką procedurę wywołać, aby przetworzyć przychodzące dane, które przesyłamy wraz z danymi, natomiast z podejściem REST w naszej witrynie znajduje się wiele wejść (linków), z których każdy akceptuje i przetwarza tylko określone dane. Jeśli ktoś czytający wie, jak jeszcze prościej wyjaśnić różnicę w tych podejściach, koniecznie napisz w komentarzach!

Następną rzeczą, którą musimy wiedzieć o SOAP, jest to, że protokół ten wykorzystuje ten sam XML co transport, co z jednej strony jest bardzo dobre, ponieważ W naszym arsenale od razu pojawia się pełna moc stosu technologii opartych na tym języku znaczników, a mianowicie XML-Schema - język opisujący strukturę dokumentu XML (dzięki Wikipedia!), który pozwala na automatyczną walidację danych otrzymanych przez serwer od klientów.

Zatem teraz wiemy, że SOAP jest protokołem używanym do implementacji zdalnych wywołań procedur i wykorzystuje XML jako środek transportu! Jeśli przeczytasz artykuł na Wikipedii, dowiesz się z niego również, że można go używać na dowolnym protokole na poziomie aplikacji, a nie tylko w połączeniu z HTTP (niestety w tym temacie rozważymy tylko SOAP przez HTTP). A wiesz, co mi się w tym wszystkim podoba najbardziej? Jeśli nie będzie domysłów, to podpowiem - SOAP!... Nadal nie ma domysłów?... Czy na pewno czytasz artykuł na Wikipedii?... Ogólnie rzecz biorąc, nie będę cię dalej męczyć. Dlatego przejdę od razu do odpowiedzi: „SOAP (z angielskiego Simple Object Access Protocol – simple protokół dostęp do obiektów; do specyfikacji 1.2)”. Najbardziej niezwykłą rzeczą w tym wierszu jest kursywa! Nie wiem, jakie wnioski z tego wszystkiego wysnułeś, ale widzę co następuje - skoro tego protokołu w żaden sposób nie można nazwać „prostym” (i najwyraźniej nawet w3 się z tym zgadza), to od wersji 1.2 przestał się jakoś odszyfrowywać ! I stało się znane jako SOAP, po prostu SOAP, kropka.

No dobrze, przepraszam, odeszliśmy trochę na bok. Jak pisałem wcześniej, jako transport używany jest XML, a pakiety podróżujące pomiędzy klientem a serwerem nazywane są kopertami SOAP. Jeśli weźmiesz pod uwagę ogólną strukturę koperty, wyda Ci się ona bardzo znajoma, ponieważ... przypomina znaczniki strony HTML. Ma główną sekcję - Osnuć, który zawiera sekcje nagłówek I Ciało, Lub Wada. W Ciało dane są przesyłane i jest to obowiązkowa część koperty, natomiast nagłówek jest opcjonalne. W nagłówek autoryzacja lub jakiekolwiek inne dane, które nie są bezpośrednio związane z danymi wejściowymi procedur usług internetowych, mogą zostać przesłane. O Wada nie ma nic specjalnego do powiedzenia poza tym, że przychodzi do klienta z serwera w przypadku jakichkolwiek błędów.

W tym miejscu kończy się moja recenzja protokołu SOAP (samm kopertom i ich strukturze przyjrzymy się bardziej szczegółowo, gdy nasz klient i serwer w końcu nauczą się je na siebie uruchamiać), a zaczyna nowa - o towarzyszu SOAP o nazwie WSDL(Język opisu usług sieciowych). Tak, tak, właśnie to odstrasza większość z nas od nawet prób implementacji naszego API w tym protokole. W rezultacie zwykle wymyślamy na nowo nasze koło, używając JSON jako środka transportu. Czym więc jest WSDL? WSDL to język opisu usług sieciowych i dostępu do nich, oparty na języku XML (c) Wikipedia. Jeśli ta definicja nie wyjaśnia ci całego świętego znaczenia tej technologii, spróbuję opisać ją własnymi słowami!

WSDL ma na celu umożliwienie naszym klientom normalnej komunikacji z serwerem. W tym celu plik z rozszerzeniem „*.wsdl” zawiera następujące informacje:

  • Jakie przestrzenie nazw zostały użyte?
  • Jakie schematy danych zastosowano?
  • Jakiego rodzaju wiadomości oczekuje serwis WWW od klientów?
  • Jakie dane należą do jakich procedur usług sieciowych,
  • Jakie procedury zawiera serwis internetowy?
  • Jak Klient powinien wywołać procedury serwisu WWW,
  • Na jaki adres należy kierować telefony od klientów?

Jak widać, ten plik to cała usługa internetowa. Podając w kliencie adres pliku WSDL, dowiemy się wszystkiego o każdym serwisie WWW! Dzięki temu nie musimy wiedzieć zupełnie nic o tym, gdzie znajduje się sama usługa internetowa. Wszystko, co musisz wiedzieć, to lokalizacja pliku WSDL! Już niedługo przekonamy się, że SOAP nie jest taki straszny jak to przedstawiają rosyjskie przysłowia.

3 Wprowadzenie do schematu XML

Teraz wiemy dużo o tym, czym jest SOAP, co się w nim kryje i mamy przegląd otaczającego go stosu technologicznego. Ponieważ przede wszystkim SOAP jest metodą interakcji między klientem a serwerem, a język znaczników XML służy jako środek transportu, w tej sekcji zrozumiemy trochę, jak odbywa się automatyczna walidacja danych przy użyciu schematów XML.

Głównym zadaniem diagramu jest opisanie struktury danych, które będziemy przetwarzać. Wszystkie dane w schematach XML są podzielone na prosty(skalarny) i złożony typy (struktur). Typy proste obejmują następujące typy:

  • linia,
  • numer,
  • wartość logiczna,
  • data.

Coś bardzo prostego, co nie ma żadnych rozszerzeń w środku. Ich antypodą są złożone typy złożone. Najprostszym przykładem typu złożonego, jaki przychodzi każdemu na myśl, są obiekty. Na przykład książka. Książka składa się z właściwości: autor, Nazwa, cena, numer ISBN itp. Te właściwości z kolei mogą być typami prostymi lub złożonymi. Zadaniem schematu XML jest opisanie tego.

Sugeruję nie iść daleko i napisać schemat XML dla naszej wiadomości SMS! Poniżej znajduje się opis XML wiadomości SMS:

71239876543 Wiadomość testowa 2013-07-20T12:00:00 12

Nasz diagram typów złożonych będzie wyglądał następująco:

Ten wpis brzmi następująco: Mamy zmienną „ wiadomość" typ " Wiadomość" i istnieje typ złożony zwany " Wiadomość„, który składa się z sekwencyjnego zestawu elementów” telefon" typ strunowy, « tekst" typ strunowy, « data" typ dataGodzina, « typ" typ dziesiętny. Typy te są proste i zostały już zdefiniowane w opisie schematu. Gratulacje! Właśnie napisaliśmy nasz pierwszy schemat XML!

Myślę, że znaczenie elementów „ element" I " Typ złożony„Wszystko stało się dla Ciebie mniej więcej jasne, więc nie będziemy się już na nich skupiać i przejdziemy od razu do elementu kompozytora” sekwencja" Kiedy używamy elementu kompozytora „ sekwencja„Informujemy, że zawarte w nim elementy muszą zawsze znajdować się w kolejności określonej na schemacie i wszystkie są obowiązkowe. Ale nie rozpaczaj! W schematach XML znajdują się jeszcze dwa elementy kompozytora: „ wybór" I " Wszystko" Kompozytor” wybór„zapowiada, że ​​musi znajdować się jeden z wymienionych w nim elementów, a kompozytor” Wszystko» – dowolna kombinacja wymienionych elementów.

Jak pamiętacie, w pierwszej części tematu ustaliliśmy, że w pakiecie można przesyłać od jednej do nieskończonej liczby wiadomości SMS. Dlatego proponuję zrozumieć, w jaki sposób takie dane są deklarowane w schemacie XML. Ogólna struktura pakietu może wyglądać następująco:

71239876543 Wiadomość testowa 1 2013-07-20T12:00:00 12 71239876543 Wiadomość testowa N 2013-07-20T12:00:00 12

Diagram dla tak złożonego typu będzie wyglądał następująco:

Pierwszy blok zawiera znaną deklarację typu złożonego „ Wiadomość" Jeśli zauważyłeś, to w każdym prostym typie zawartym w „ Wiadomość", dodano nowe atrybuty wyjaśniające " minWystępuje" I " maks.Występuje" Jak można się domyślić z nazwy, pierwszy ( minWystępuje) wskazuje, że ta sekwencja musi zawierać co najmniej jeden element typu „ telefon», « tekst», « data" I " typ", natomiast następny ( maks.Występuje) deklaruje nam, że w naszej sekwencji istnieje co najwyżej jeden taki element. Dzięki temu pisząc własne schematy dla dowolnych danych mamy najszerszy wybór w zakresie ich konfiguracji!

Drugi blok diagramu deklaruje element „ lista wiadomości" typ " Lista wiadomości" Jest oczywiste, że " Lista wiadomości" jest typem złożonym, który zawiera co najmniej jeden element " wiadomość”, ale maksymalna liczba takich elementów nie jest ograniczona!

4 Napisz swój WSDL

Czy pamiętasz, że WSDL to nasz serwis internetowy? Mam nadzieję, że pamiętasz! Gdy to napiszemy, będzie na nim działał nasz mały serwis internetowy. Dlatego radzę nie zawracać sobie głowy.

Generalnie aby wszystko u nas działało poprawnie musimy przesłać do klienta plik WSDL z poprawnym typem MIME. W tym celu należy odpowiednio skonfigurować swój serwer WWW, a mianowicie ustawić typ MIME dla plików z rozszerzeniem „*.wsdl” w następującej linii:

Aplikacja/wsdl+xml

Ale w praktyce zwykle wysyłam nagłówek HTTP przez PHP „ tekst/xml»:

Header("Typ zawartości: tekst/xml; charset=utf-8");

i wszystko działało świetnie!

Chcę Cię od razu ostrzec, że nasz prosty serwis internetowy będzie miał dość imponujący opis, więc nie przejmuj się, bo... Większość tekstu to obowiązkowa woda i po jednorazowym napisaniu możesz go stale kopiować z jednego serwisu internetowego do drugiego!

Ponieważ WSDL to XML, musisz napisać o tym bezpośrednio w pierwszej linijce. Główny element pliku powinien zawsze nazywać się „ definicje»:

Zazwyczaj WSDL składa się z 4-5 głównych bloków. Pierwszym blokiem jest definicja usługi internetowej, czyli inaczej punktu wejścia.

Tu jest napisane, że mamy usługę o nazwie - „ Usługa sms" W zasadzie wszystkie nazwy w pliku WSDL możesz zmienić na jakie tylko chcesz, bo nie odgrywają absolutnie żadnej roli.

Następnie ogłaszamy, że w naszym serwisie internetowym „ Usługa sms„istnieje punkt wejścia („port”) zwany „ Port usługi sms" To właśnie do tego punktu wejścia będą wysyłane wszystkie żądania od klientów do serwera. I wskaż w elemencie „ adres» link do pliku obsługi, który będzie akceptował żądania.

Kiedy już zdefiniujemy usługę sieciową i określimy dla niej punkt wejścia, musimy powiązać z nią obsługiwane procedury:

Aby to zrobić, wyświetla listę, które operacje i w jakiej formie zostaną wywołane. Te. dla portu” Port usługi sms„powiązanie jest zdefiniowane pod nazwą” Wiązanie usługi sms", który ma typ wywołania " RPC„, a HTTP jest używany jako protokół transmisji. Dlatego wskazaliśmy tutaj, że wykonamy wywołanie RPC przez HTTP. Następnie opisujemy, które procedury ( operacja) są obsługiwane w serwisie internetowym. Będziemy wspierać tylko jedną procedurę – „ Wyślij SMS" Dzięki tej procedurze nasze wspaniałe wiadomości zostaną wysłane na serwer! Po zadeklarowaniu procedury należy wskazać, w jakiej formie dane będą przekazywane. W tym przypadku wskazuje się, że zastosowane zostaną standardowe koperty SOAP.

Następnie musimy powiązać procedurę z komunikatami:

Aby to zrobić, określamy, że nasze powiązanie jest typu „ Typ portu smsservice" i w elemencie " Typ portu„nazwą tego samego typu wskazujemy powiązanie procedur z komunikatami. I tak wiadomość przychodząca (od klienta do serwera) będzie nazywana „ wyślij żądanie SMS" i wychodzące (z serwera do klienta) " wyślij odpowiedź SMS" Podobnie jak wszystkie nazwy w języku WSDL, nazwy wiadomości przychodzących i wychodzących są dowolne.

Teraz musimy opisać same komunikaty, tj. przychodzące i wychodzące:

Aby to zrobić, dodajemy elementy „ wiadomość„z imionami” wyślij żądanie SMS" I " wyślij odpowiedź SMS„odpowiednio. Wskazujemy w nich, że wejściem powinna być koperta, której struktura odpowiada typowi danych „ Wniosek" Po czym z serwera zwracana jest koperta zawierająca typ danych - „ Odpowiedź».

Teraz pozostaje nam tylko trochę zrobić - dodać opis tych typów do naszego pliku WSDL! A jak myślisz, jak WSDL opisuje dane przychodzące i wychodzące? Myślę, że już wszystko zrozumiałeś dawno temu i powiedziałeś sobie, że używanie schematów XML! I będziesz mieć całkowitą rację!

Możesz nam pogratulować! Nasz pierwszy WSDL został napisany! I jesteśmy o krok bliżej osiągnięcia celu.
Następnie przyjrzymy się, co PHP zapewnia nam do tworzenia własnych aplikacji rozproszonych.

5 Nasz pierwszy serwer SOAP

Wcześniej pisałem, że do stworzenia serwera SOAP w PHP skorzystamy z wbudowanej klasy SoapServer. Aby wszystkie dalsze działania przebiegały tak samo jak u mnie, będziesz musiał trochę zmodyfikować swój PHP. Aby być jeszcze bardziej precyzyjnym, musisz upewnić się, że masz zainstalowane rozszerzenie „php-soap”. O tym, jak zainstalować go na swoim serwerze WWW, najlepiej przeczytać na oficjalnej stronie PHP (zobacz listę odnośników).

Po zainstalowaniu i skonfigurowaniu wszystkiego będziemy musieli utworzyć plik w folderze głównym Twojego hostingu „ smsservice.php» o następującej treści:

setClass("SoapSmsGateWay"); //Uruchamiamy serwer $server->handle();

Mam nadzieję, że nie trzeba wyjaśniać, co jest powyżej linii za pomocą funkcji „ini_set”. Ponieważ tam ustala się, które nagłówki HTTP wyślemy z serwera do klienta i konfiguruje się środowisko. W linii z „ini_set” wyłączamy buforowanie pliku WSDL, aby nasze zmiany w nim natychmiast odniosły skutek na kliencie.

Teraz wchodzimy na serwer! Jak widać, cały serwer SOAP zajmuje tylko trzy linie! W pierwszej linii tworzymy nową instancję obiektu SoapServer i przekazujemy do jego konstruktora adres naszego opisu WSDL usługi WWW. Teraz już wiemy, że będzie on znajdował się w katalogu głównym hostingu w pliku o zrozumiałej nazwie „ smsservice.wsdl.php" W drugiej linii mówimy serwerowi SOAP, jaką klasę należy pobrać, aby przetworzyć kopertę otrzymaną od klienta i zwrócić kopertę z odpowiedzią. Jak można się domyślić, to właśnie w tej klasie zostanie opisana nasza jedyna metoda Wyślij SMS. W trzeciej linii uruchamiamy serwer! To wszystko, nasz serwer jest gotowy! Czego nam wszystkim gratuluję!

Teraz musimy utworzyć plik WSDL. Aby to zrobić, możesz po prostu skopiować jego zawartość z poprzedniej sekcji lub pozwolić sobie na swobodę i trochę ją „spersonalizować”:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />

Na tym etapie powinniśmy być w pełni zadowoleni z powstałego serwera, gdyż Możemy rejestrować przychodzące do niego koperty, a następnie spokojnie analizować napływające dane. Abyśmy mogli cokolwiek odbierać na serwerze, potrzebujemy klienta. Więc przejdźmy do tego!

6 Klient SOAP w drodze

Na początek musimy stworzyć plik w którym będziemy pisać klienta. Jak zwykle utworzymy go w katalogu głównym hosta i nazwiemy „ klient.php", a w środku napiszemy co następuje:

MessageList = nowa MessageList(); $req->messageList->message = nowa wiadomość(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Wiadomość testowa 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->lista wiadomości->wiadomość->typ = 15; $client = nowy SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($klient->sendSms($req));

Opiszmy nasze obiekty. Kiedy pisaliśmy plik WSDL, opisywał on trzy elementy koperty przychodzącej na serwer: Wniosek, Lista wiadomości I Wiadomość. Odpowiednio zajęcia Wniosek, Lista wiadomości I Wiadomość są odzwierciedleniem tych bytów w naszym skrypcie PHP.

Po zdefiniowaniu obiektów musimy utworzyć obiekt ( wym. $), które wyślemy na serwer. Następnie następują dwie najbardziej dla nas cenione linie! Nasz klient SOAP! Wierzcie lub nie, ale to wystarczy, aby nasz serwer zaczął odbierać wiadomości od klienta, a także aby nasz serwer pomyślnie je odbierał i przetwarzał! W pierwszym z nich tworzymy instancję klasy SoapClient i przekazujemy jej konstruktorowi adres lokalizacji pliku WSDL, a w parametrach jednoznacznie wskazujemy, że będziemy pracować z wykorzystaniem protokołu SOAP w wersji 1.2. W następnej linii wywołujemy metodę Wyślij SMS obiekt $klient i natychmiast wyświetl wynik w przeglądarce.
Uruchommy to i zobaczmy, co w końcu otrzymaliśmy!

Z serwera zwrócono mi następujący obiekt:

Obiekt(stdClass) publiczny „status” => wartość logiczna prawda

I to jest świetne, bo... Teraz już wiemy na pewno, że nasz serwer działa i nie tylko działa, ale może też zwrócić klientowi pewne wartości!

Przyjrzyjmy się teraz logowi, który roztropnie przechowujemy po stronie serwera! W pierwszej części widzimy surowe dane, które dotarły na serwer:

79871234567 Wiadomość testowa 1 2013-07-21T15:00:00.26 15

To jest koperta. Teraz wiesz, jak to wygląda! Jest jednak mało prawdopodobne, że będziemy chcieli się temu przyglądać przez cały czas, więc deserializujmy obiekt z pliku dziennika i zobaczmy, czy wszystko jest w porządku:

Obiekt(stdClass) public "messageList" => obiekt(stdClass) public "wiadomość" => obiekt(stdClass) public "telefon" => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 1 " (długość=37) public "data" => string "2013-07-21T15:00:00.26" (długość=22) public "type" => string "15" (długość=2)

Jak widać obiekt został deserializowany poprawnie, za co chcę nam wszystkim pogratulować! W następnej kolejności czeka nas coś ciekawszego! Mianowicie wyślemy klientowi na serwer nie tylko jedną wiadomość SMS, ale całą paczkę (dokładniej trzy)!

7 Wysyłanie skomplikowanych obiektów

Zastanówmy się jak w jednym pakiecie możemy przesłać na serwer całą masę wiadomości? Prawdopodobnie najłatwiejszym sposobem byłoby zorganizowanie tablicy wewnątrz elementu MessageList! Zróbmy to:

// utwórz obiekt do wysłania na serwer $req = new Request(); $req->messageList = nowa MessageList(); $msg1 = nowa wiadomość(); $msg1->telefon = "79871234567"; $msg1->text = "Wiadomość testowa 1"; $msg1->data = "2013-07-21T15:00:00.26"; $msg1->typ = 15; $msg2 = nowa wiadomość(); $msg2->telefon = "79871234567"; $msg2->text = "Wiadomość testowa 2"; $msg2->data = "2014-08-22T16:01:10"; $msg2->typ = 16; $msg3 = nowa wiadomość(); $msg3->telefon = "79871234567"; $msg3->text = "Wiadomość testowa 3"; $msg3->data = "2014-08-22T16:01:10"; $msg3->typ = 17; $req->messageList->message = $msg1; $req->listawiadomości->wiadomość = $msg2; $req->messageList->message = $msg3;

Z naszych logów wynika, że ​​od klienta odebrano następujący pakiet:

79871234567 Wiadomość testowa 1 2013-07-21T15:00:00.26 15 79871234567 Wiadomość testowa 2 2014-08-22T16:01:10 16 79871234567 Wiadomość testowa 3 2014-08-22T16:01:10 17

Co za bzdury, mówisz? I w pewnym sensie będziesz mieć rację, bo... Gdy tylko dowiedzieliśmy się, że przedmiot opuścił klienta, trafił na nasz serwer w absolutnie takiej samej formie w postaci koperty. To prawda, że ​​wiadomości SMS nie były serializowane w formacie XML w taki sposób, w jaki tego potrzebowaliśmy - musiały być opakowane w elementy wiadomość, nie w Struktura. Zobaczmy teraz, w jakiej formie taki obiekt przychodzi do metody Wyślij SMS:

Obiekt(stdClass) public "messageList" => obiekt(stdClass) public "wiadomość" => obiekt(stdClass) public "Struct" => tablica (rozmiar=3) 0 => obiekt(stdClass) publiczny "telefon" => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 1" (długość=37) public "data" => string "2013-07-21T15:00:00.26" (długość=22) public " type" => string "15" (długość=2) 1 => obiekt(stdClass) public "phone" => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 2" (długość= 37) public "data" => string "2014-08-22T16:01:10" (długość=19) public "type" => string "16" (długość=2) 2 => obiekt(stdClass) publiczny "telefon " => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 3" (długość=37) public "data" => string "2014-08-22T16:01:10" (długość= 19) public "type" => string "17" (długość=2)

Co nam daje ta wiedza? Tyle tylko, że wybrana przez nas ścieżka jest błędna i nie otrzymaliśmy odpowiedzi na pytanie – „Jak uzyskać poprawną strukturę danych na serwerze?” Sugeruję jednak nie rozpaczać i spróbować przekonwertować naszą tablicę na typ obiekt:

$req->messageList->message = (obiekt)$req->messageList->message;

W takim przypadku otrzymamy kolejną kopertę:

79871234567 Wiadomość testowa 1 2013-07-21T15:00:00.26 15 79871234567 Wiadomość testowa 2 2014-08-22T16:01:10 16 79871234567 Wiadomość testowa 3 2014-08-22T16:01:10 17

Weszło w metodę Wyślij SMS obiekt ma następującą strukturę:

Obiekt(stdClass) public "messageList" => obiekt(stdClass) public "wiadomość" => obiekt(stdClass) public "BOGUS" => tablica (rozmiar=3) 0 => obiekt(stdClass) public "telefon" => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 1" (długość=37) public "data" => string "2013-07-21T15:00:00.26" (długość=22) public " type" => string "15" (długość=2) 1 => obiekt(stdClass) public "phone" => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 2" (długość= 37) public "data" => string "2014-08-22T16:01:10" (długość=19) public "type" => string "16" (długość=2) 2 => obiekt(stdClass) publiczny "telefon " => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 3" (długość=37) public "data" => string "2014-08-22T16:01:10" (długość= 19) public "type" => string "17" (długość=2)

Jeśli chodzi o mnie, „suma nie zmienia się wraz ze zmianą miejsca wyrazów” (c). Co PODROBIONY, Co Struktura– nie osiągnęliśmy jeszcze celu! A żeby to osiągnąć, musimy zadbać o to, aby zamiast tych niezrozumiałych nazw wyświetlała się nasza rodzima wiadomość. Jednak autor nie wie jeszcze, jak to osiągnąć. Dlatego jedyne, co możemy zrobić, to pozbyć się dodatkowego pojemnika. Innymi słowy, teraz upewnimy się, że zamiast wiadomość stał się PODROBIONY! Aby to zrobić, zmień obiekt w następujący sposób:

// utwórz obiekt do wysłania na serwer $req = new Request(); $msg1 = nowa wiadomość(); $msg1->telefon = "79871234567"; $msg1->text = "Wiadomość testowa 1"; $msg1->data = "2013-07-21T15:00:00.26"; $msg1->typ = 15; $msg2 = nowa wiadomość(); $msg2->telefon = "79871234567"; $msg2->text = "Wiadomość testowa 2"; $msg2->data = "2014-08-22T16:01:10"; $msg2->typ = 16; $msg3 = nowa wiadomość(); $msg3->telefon = "79871234567"; $msg3->text = "Wiadomość testowa 3"; $msg3->data = "2014-08-22T16:01:10"; $msg3->typ = 17; $req->listawiadomości = $msg1; $req->listawiadomości = $msg2; $req->listawiadomości = $msg3; $req->messageList = (obiekt)$req->messageList;

A co jeśli będziemy mieli szczęście i ze schematu wypadnie prawidłowa nazwa? Aby to zrobić, spójrzmy na otrzymaną kopertę:

79871234567 Wiadomość testowa 1 2013-07-21T15:00:00.26 15 79871234567 Wiadomość testowa 2 2014-08-22T16:01:10 16 79871234567 Wiadomość testowa 3 2014-08-22T16:01:10 17

Tak, cud się nie wydarzył! PODROBIONY– nie wygramy! Przyszedł do Wyślij SMS obiekt w tym przypadku będzie wyglądał następująco:

Obiekt(stdClass) public "messageList" => obiekt(stdClass) public "BOGUS" => tablica (rozmiar=3) 0 => obiekt(stdClass) public "phone" => string "79871234567" (długość=11) public " tekst" => string "Wiadomość testowa 1" (długość=37) public "data" => string "2013-07-21T15:00:00.26" (długość=22) public "typ" => string "15" (długość =2) 1 => obiekt(stdClass) public "phone" => string "79871234567" (długość=11) public "text" => string "Wiadomość testowa 2" (długość=37) public "data" => string " 2014-08-22T16:01:10" (długość=19) public "type" => string "16" (długość=2) 2 => obiekt(stdClass) public "phone" => string "79871234567" (długość= 11) public "text" => string "Wiadomość testowa 3" (długość=37) public "data" => string "2014-08-22T16:01:10" (długość=19) public "type" => string " 17" (długość=2)

Jak to mówią – „Prawie”! W tej (trochę smutnej) notatce proponuję powoli zakończyć sprawę i wyciągnąć wnioski dla siebie.

8 Wniosek

Wreszcie tu dotarliśmy! Zastanówmy się, co możesz teraz zrobić:

  • możesz napisać plik WSDL niezbędny dla Twojego serwisu WWW;
  • możesz łatwo napisać własnego klienta, który będzie mógł komunikować się z serwerem poprzez SOAP;
  • możesz napisać własny serwer komunikujący się ze światem zewnętrznym poprzez SOAP;
  • możesz wysyłać tablice obiektów tego samego typu na serwer ze swojego klienta (z pewnymi ograniczeniami).

Podczas naszych małych badań dokonaliśmy również kilku odkryć:

  • natywna klasa SoapClient nie serializuje poprawnie struktur danych tego samego typu w formacie XML;
  • podczas serializacji tablicy do formatu XML tworzy dodatkowy element o nazwie Struktura;
  • podczas serializacji obiektu do formatu XML tworzy dodatkowy element o nazwie PODROBIONY;
  • PODROBIONY mniej zła niż Struktura ze względu na to, że koperta jest bardziej zwarta (do nagłówka XML koperty nie są dodawane dodatkowe przestrzenie nazw);
  • Niestety klasa SoapServer nie sprawdza automatycznie danych koperty za pomocą naszego schematu XML (być może inne serwery też tego nie robią).