# Webservices

Wer uns vor nutzlosen Wegen warnt, leistet uns einen ebenso guten Dienst, wie derjenige, der uns den rechten Weg anzeigt.
Heinreich Heine, (1797–181), dt. Dichter

Kommunikation ist wichtiger denn je. Wir Menschen bedienen uns dazu der Telefone, E‑Mails, Faxgeräte, der Post und der Instant Messenger, um Informationen auszutauschen. Aber wie kommunizieren eigentlich Anwendungen, die auf unterschiedlichen Systemen laufen? Ganz einfach: durch Webservices.

# Was sind Webservices?

Grundsätzlich stellt die Kommunikation zwischen zwei Computern kein Problem dar, denn es gibt Netzwerke. Jedoch ist die Kommunikation zwischen zwei Computern in einem Netzwerk häufig eher von der Art Mensch-zu-Maschine. Der Benutzer gibt im Browser eine URL ein, dieser ruft die Daten vom Server ab und präsentiert sie dem Benutzer. Webservices dienen jedoch z. B. dem Informationsfluss zwischen zwei Servern. Ein Beispiel: Server A fragt bei Server B nach einer bestimmten Information wie der Uhrzeit oder seiner Festplattengröße. Server B überprüft, ob er diese Information zur Verfügung stellen kann, und antwortet dem Server A entsprechend.

Grundsätzlich klingt das sehr einfach, aber nicht alle Server sind gleich. Sie unterscheiden sich z. B. im Betriebssystem, der installierten Hardware oder den Anwendungen, die den Informationsaustausch durchführen sollen. Es muss also eine gemeinsame Sprache gefunden werden, die von allen verstanden und »gesprochen« werden kann. Auch die Weltbevölkerung hat dieses Problem, weshalb irgendwann Englisch als die internationale Sprache festgelegt wurde. Außerdem muss diese »Computersprache« auch in der Lage sein, unabhängig von der Art der auszutauschen Informationen zu sein.

# Die unterschiedlichen Varianten

Mittlerweile haben sich einige Standards für Webservices etabliert, die ich Ihnen nachfolgend kurz vorstellen werde.

# XML-RPC

Dieser Standard basiert auf den so genannten »Remote Procedure Calls« (RPCs). RPC bedeutet, dass die Anfrage so formuliert wird, dass auf dem entfernten System eine Funktion aufgerufen wird. Dieser Funktion können Parameter übergeben werden – also fast genauso, als würden Sie eine Funktion in einer Programmiersprachen aufrufen, nur dass dabei XML genutzt wird, um den Aufruf selbst zu formulieren.

Ein Beispiel:

<?xml version="1.0"?>
<methodCall>
    <methodName>translate</methodName>
    <params>
        <param>
            <string>Hallo Welt!</string>
        </param>
    </params>
</methodCall>

Listing 5.1: Beispiel für einen XML-RPC

In diesem Beispiel wird auf einem entfernten Server die Funktion translate aufgerufen. Dies wird durch das Element methodName festlegt. Als Parameter wird ihr die Zeichenfolge Hallo Welt! übergeben, festgelegt durch das Element param. Interessant ist, dass eine Typisierung des Wertes erfolgt, indem das string-Element genutzt wird. Da es in einem XML-Dokument nur Zeichenfolgen gibt, kann so zwischen normalem Text, Zahlen und anderen Datentypen unterschieden werden.

Anfragen, die mit XML-RPC gestellt werden, erfolgen über das HTTP-Protokoll. Der Server, an den die Anfrage gerichtet wird, muss also nicht erst ein neues Protokoll erlernen, sondern es reicht aus, wenn auf ihm ein HTTP-Daemon installiert ist, der diese Anfragen verarbeiten kann.

# SOAP

SOAP, das »Simple Object Access Protocol«, beschreitet einen ähnlichen Weg wie XML-RPC. Es ist trotz des anders lautenden Namens jedoch nicht trivial, einen Webservice mit SOAP zu erstellen. Zusammenfassend lässt sich sagen, dass SOAP alle Nachrichten in einem Umschlag (engl. envelope) verpackt. Das Besondere an diesem Umschlag ist, dass er beschreibt, welche Daten in der Nachricht enthalten sind und von wem und vor allem wie diese Daten zu verarbeiten sind.

Der Unterschied zu einem RPC ist, dass Nachrichten keine Antworten erwarten. Wenn Sie z. B. mittels XML-RPC auf einem entfernten System eine Funktion aufrufen, erwarten Sie in der Regel eine Antwort, z. B. einen Rückgabewert oder Ähnliches. Nachrichten bedürfen keiner Antwort. Dies ähnelt einem Telefongespräch und einer E‑Mail. Wenn Sie jemanden anrufen, möchten Sie zeitnah eine Antwort oder Reaktion. Eine E‑Mail hingegen schicken Sie ab, erledigen in der Zwischenzeit andere Dinge und bekommen irgendwann eine Antwort oder auch nicht.

Ein Beispiel für Frage und Antwort:

Frage
Kannst du mir »Hallo Welt!« ins Englische übersetzen?
Antwort
Ja, es heißt »Hello world!«

Ein Beispiel für eine Nachricht:

Nachricht
Übersetze mir »Hallo Welt!« ins Englische, und schicke mir nach Möglichkeit eine Antwort.

Dies bedeutet jedoch nicht, dass RPC mit SOAP nicht möglich wäre, sondern dass es nur eine der verschiedenen Möglichkeiten ist.

Eine SOAP-Nachricht könnte folgendermaßen aussehen:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <translate xmlns="http://www.translator.tld/dictionary">
            <text>Hallo Welt!</text>
        </translate>
    </soap:Body>
</soap:Envelope>

Listing 5.2: Beispiel für eine SOAP-Nachricht

Zunächst folgen der Umschlag (soap:Envelope) und der Namespace für SOAP (Attribut xmlns). Einen Namespace können Sie sich in etwa wie eine Bibliothek vorstellen. Bei PHP wäre so etwas eine Datei, die Sie über include einbinden und in der Funktionen, Variablen oder auch Klassen definiert worden sind. Diese sind anschließend in dem PHP-Dokument verfügbar.

Anschließend folgt die eigentliche Nachricht, und zwar im soap:Body-Element:

<soap:Body>  
  <translate xmlns="http://www.translator.tld/dictionary">  
    <text>Hallo Welt!</text>  
  </translate>  
</soap:Body>

Auch hier wird wieder ein Namespace eingebunden, der festlegt, wo translate zu finden ist. Anschließend folgen Werte für translate.

So kompliziert, wie es auf den ersten Blick wirkt, ist SOAP auch. Ich kann Ihnen nur das Buch »Web Services – Die Standards« von Tobias Hauser und Ulrich M. Löwer, erschienen bei Galileo Press (ISBN: 3–89842–393-X), empfehlen, falls Sie ein tiefergehendes Interesse an SOAP und dessen Entwicklung haben. Ansonsten sollten Sie die wesentlich einfachere Variante XML-RPC im Hinterkopf behalten, denn auf diese werden wir etwas später noch einmal zurückkommen.

# WSDL

Mit WSDL wird eine Möglichkeit bezeichnet, einen Webservice zu beschreiben, daher auch der Name: Web Service Description Language. SOAP ist z. B. so umfangreich und flexibel, dass Sie wissen müssen, welche Methoden ein SOAP-Service bietet, und diese Definition erfolgt in den meisten Fällen mit WSDL. Stellen Sie sich SOAP einfach als den Wortschatz einer Sprache vor, also als die Vokabeln. Nun benötigen Sie jedoch Regeln, um diese Wörter in eine sinnvolle Reihenfolge zu bringen, und das ist die Grammatik bzw. WSDL.

Vokabeln lassen sich sehr schnell erklären und lernen, aber mit der Grammatik ist das immer so eine Sache. Selbst eine einfache Erklärung für den kleinsten gemeinsamen Nenner in einer Sprache führt zu einer komplexen Struktur. Aus diesem Grunde verzichte ich an dieser Stelle auch auf ein Beispiel, weil dies fast eine Seite füllen würde.

# Webservices nutzen

In letzter Zeit wird die eBay-API immer beliebter. Sie hat sich zwar noch keinem gängigen Standard untergeordnet, mit ihr lässt sich aber die Funktionsweise von Webservices sehr schnell und übersichtlich verdeutlichen, da sie dem XML-RPC-Standard sehr stark ähnelt. In den folgenden Unterkapiteln werden zum einen die Maßnahmen zur Registrierung beim eBay Developer Program vorgestellt, und zum anderen wird erläutert, wie Sie mit PHP die aktuelle Uhrzeit des eBay-Servers »erfragen« können.

# eBay Developer Program

Bevor Sie Zugriff auf die eBay-API erhalten können, ist eine Registrierung beim eBay Developer Program notwendig. Dieses finden Sie unter der Adresse: http://developer.ebay.com

Wählen Sie auf der Startseite den Link MembershipJoin aus (siehe Abbildung 5.1 links unten). Auf der sich öffnenden Seite können Sie mit der Registrierungsprozedur beginnen. Sie erhalten einige Informationen darüber, wie die einzelnen Schritte aussehen. Wählen Sie Join now. Auf der ersten Seite müssen Sie Informationen über sich eingeben sowie etwaige Firmenkontaktdaten. Klicken Sie nach der Eingabe dieser Daten auf den Button Next am unteren Seitenende.

Startseite des eBay Developer Program
Abbildung 5.1: Startseite des eBay Developer Program

Nun wird die API-Lizenz angezeigt. Für Testzwecke und zum Nachvollziehen der Beispiele in diesem Kapitel reicht die Individual API License vollkommen aus. Lesen Sie sich die Bedingungen dieser Lizenz in Ruhe durch, und klicken Sie erneut auf Next.

Nachdem Sie sich über die Lizenz informiert haben, können Sie diese nun auswählen. Die Individual License finden Sie gleich zu Beginn der Seite. Markieren Sie den Radiobutton Individual Tier sowohl im Bereich API License Decision and Pricing Tier als auch im Bereich Developer Technical Support Tier. Außerdem sollten Sie alle Auswahlmöglichkeiten im Bereich Permitted Use und Terms and Conditions that Apply to the API License lesen und die zutreffenden entsprechend markieren. Wechseln Sie mit Next zur nächsten Seite.

Es folgen nun einige Vereinbarungen zwischen Ihnen und eBay. Lesen und bestätigen Sie diese durch das Aktivieren der Checkboxen. Wählen Sie abschließend I Accept This Agreement.

Nun folgt die Eingabe der Daten Ihres eBay-Accounts. Das sind die gleichen Daten, die Sie auch nutzen, um bei ebay.de in Auktionen mitzubieten. Nach dem Abschluss der Registrierung erhalten Sie eine Bestätigungs-E‑Mail von eBay. Diese E‑Mail ist außerordentlich wichtig, weil sie zum Erzeugen der Lizenzschlüssel, der Sandbox-Keys, benötigt wird. Folgen Sie dazu den Anweisungen und Punkt 1, 2 und 3 der E‑Mail. Nachdem die Keys erzeugt worden sind, speichern Sie diese ab oder drucken sie aus.

Was Sie nun benötigen, ist ein Test-Account. Gehen Sie auf http://sandbox.ebay.com/, und registrieren Sie dort einen Account. Wichtig ist die Angabe einer gültigen Adresse in den USA. Um an eine solche Adresse zu gelangen, können Sie die Yellow Pages nutzen, die Sie unter http://www.yellowpages.com/ finden.

Dieser »Hack« mit den Yellow Pages ist durchaus legal, solange Sie einen Testaccount einrichten. Da Sie bei der Individual Tier-Lizenz auf einem Testsystem arbeiten, nämlich in der so genannten »Sandbox«, ist dies erlaubt. Beim echten ebay.com wäre dies natürlich ein Verstoß gegen die Regeln. Den »Hack« können Sie übrigens auch im eBay Developer Forum finden.

Neben den durch die Registrierung erhaltenen Daten benötigen Sie noch einen Auth & Auth Token. Diesen können Sie unter der folgenden Adresse erhalten: http://developer.ebay.com/tokentool/Credentials.aspx

Wählen Sie aus dem Dropdown-Menü Sandbox aus, und tragen Sie in die restlichen Felder Ihre Daten ein. Generieren Sie anschließend den Token durch einen Klick auf Continue to generate token, und speichern Sie diesen nach Möglichkeit in einer Datei ab.

Geschafft! Nun wird es Zeit für einen ersten Einsatz!

# Grundlagen

Eine Anfrage an die eBay-API gliedert sich in zwei Stücke: den Header und die Anfrage.

In den vorangegangenen Teilen dieses Buches haben Sie bereits MIME-Typen kennen gelernt und Sie wissen, wie Sie mit der PHP-Funktion header dem Browser einen anderen MIME-Typ mitteilen können. Vor allem bei der Erzeugung dynamischer Grafiken ist dies wichtig. Ein Beispiel:

header('Content-Type: image/png');

Für den Aufruf einer Funktion der eBay-API sind jedoch noch einige weitere Informationen erforderlich, die im Header mitgeteilt werden müssen.

X-EBAY-API-COMPATIBILITY-LEVEL:  
X-EBAY-API-SESSION-CERTIFICATE:  
X-EBAY-API-DEV-NAME:  
X-EBAY-API-APP-NAME:  
X-EBAY-API-CERT-NAME:  
X-EBAY-API-CALL-NAME:  
X-EBAY-API-SITEID:  
X-EBAY-API-DETAIL-LEVEL:  
Content-Type:  
Content-Length:

Listing 5.3: Beispiel für den modifizierten HTTP-Header

Die Header-Information X-EBAY-API-COMPATIBILITY-LEVEL legt fest, auf welche Version der eBay-API sich diese Anfrage bezieht. Der Grund ist, dass sich die eBay-API im Laufe der Zeit weiterentwickelt und erweitert oder verändert wird. Jeder Kompatibilitätslevel bleibt für ca. 1 Jahr aktuell und abwärtskompatibel. Momentan ist dies der Level 367.

Für die drei Informationen X-EBAY-API-DEV-NAME, ...APP-NAME und ...CERT-NAME werden die Werte angegeben, die Sie bei der Registrierung erhalten haben. Diese Werte werden Sie noch häufiger benötigen und somit empfiehlt es sich, diese in eine externe Datei auszulagern.

Achten Sie darauf, diese Zugangsdaten nicht an andere Personen weiterzugeben, da dies unter Umständen Kosten nach sich ziehen kann, wenn Sie eine andere Lizenz als die Individual Tier-Lizenz nutzen.

Der Wert für X-EBAY-API-SESSION-CERTIFICATE basiert auf den zuvor genannten drei Sandbox-Keys und wird aus diesen folgendermaßen aufgebaut:

dev-name; app-name; cert-name

Die Werte werden also durch ein Semikolon getrennt aneinander gehängt.

Der Name der Funktion, die Sie aufrufen möchten, wird mit Hilfe der Information X-EBAY-CALL-NAME angegeben. Für den Abruf der Server-Uhrzeit ist dies die Funktion GeteBayOfficialTime.

Da eBay eine internationale Plattform ist, gibt es für fast jedes Land ein eigenes eBay. eBay.com und eBay.de führen unterschiedliche Auktionen, und auch die Benutzer sind andere. Es muss also mit angegeben werden, für welche der eBay-Seiten Ihre Anfrage gültig ist. Dies geben Sie mit der Information X-EBAY-API-SITEID an. Für die USA lautet die ID z. B. 0 und für Deutschland 77.

Die IDs anderer Seiten finden Sie in der Dokumentation zur API unter http://developer.ebay.com/DevZone/docs/API_Doc/.

So lange Sie Ihre Programme jedoch in der Sandbox testen, beziehen sich die erhaltenen Informationen immer auf die amerikanische Plattform, weil die Sandbox eine Kopie von eBay.com ist.

Die Information X-EBAY-API-DETAIL-LEVEL legt schließlich fest, wie detailliert die Antwort der eBay-API sein soll. Wird von der Funktion kein Detail-Level unterstützt, lautet der Standardwert 0.

# Anfrage

Einen Teil der Informationen, die Sie bereits im HTTP-Header übergeben haben, müssen außerdem im XML-Dokument wiederholt werden. Ein Beispiel für die Anfrage:

<?xml version="1.0" encoding="iso-8859–1"?>
<request>
    <RequestToken>SANDBOX_TOKEN</RequestToken>
    <RequestUserId>EBAY_TESTUSER_USERNAME</RequestUserId>
    <RequestPassword>EBAY_TESTUSER_PASSWORD</RequestPassword>
    <ErrorLevel>1</ErrorLevel>
    <DetailLevel>0</DetailLevel>
    <Verb>GeteBayOfficialTime</Verb>
    <SiteId>0</SiteId>
</request>

Listing 5.4: Beispiel für eine XML-Anfrage

Das Wurzelelement einer Anfrage ist immer request. Aus dem Header sind bereits die folgenden Informationen bekannt: DetailLevel, SiteId und auch Verb (alias CALL-NAME). Der Rest ist neu.

Den aus den drei Sandbox-Keys generierten Token geben Sie mit dem Element RequestToken an. Dazu muss es lediglich zwischen den beiden Tags notiert werden.

Den Benutzernamen und das Passwort des Users geben Sie mit RequestUserId und RequestPassword an. Diese Daten müssen zu einem existierenden eBay-User gehören, z. B. zu dem Test-Account, den Sie in der Sandbox eingerichtet haben.

Sollte es während der Ausführung seitens der eBay-API zu einem Fehler kommen, z. B. weil Ihre Anfrage falsch gestellt ist, gibt Ihnen die eBay-API eine Fehlermeldung zurück. Je nachdem, wie hoch der Level ist, wird die Meldung detaillierter oder ungenauer. Solange Sie in der Sandbox arbeiten und noch »üben«, sollten Sie den ErrorLevel 1 nutzen. Dieser gibt detailliert genug aus, warum es zu einem Fehler gekommen ist, und das Problem kann anschließend gelöst werden.

# Beispiel

Die Umsetzung in PHP ist für einen Anfänger ein wenig knifflig. Dies liegt zum einen daran, dass Sie den Header modifizieren müssen, und zum anderen daran, dass die Anfragen verschlüsselt mit HTTPS erfolgen. Leider können Sie zum Modifizieren des Headers nicht auf die Funktion header zurückgreifen. Der Grund dafür ist, dass PHP-Scripts normalerweise auf Anfragen von einem Browser reagieren. Ändern Sie also den HTTP-Header mit header, wird dieser geänderte HTTP-Header an den Browser gesendet. Für den Zugriff auf die eBay-API muss aber in diesem Moment Ihr Script die Aufgabe des Browsers übernehmen.

Für solche Aufgaben gibt es jedoch eine Bibliothek für PHP, die diese Möglichkeiten zur Verfügung stellt: cURL. Mit Hilfe von cURL können Sie jede beliebige Art von Anfragen stellen, die auf dem HTTP-Protokoll basieren.

Standardmäßig ist cURL nicht aktiviert, so dass Sie nun PHP entsprechend konfigurieren müssen. Falls Sie Zugriff auf die php.ini haben, müssen Sie lediglich das Semikolon ; vor der Zeile

;extension=php_curl.dll

entfernen. Eine andere Möglichkeit wäre, die Bibliothek dynamisch zur Laufzeit des Scripts zu aktivieren. Hier brauchen Sie die Funktion dl. Je nach Betriebssystem, auf dem der Apache und PHP laufen, trägt die Bibliothek einen anderen Namen, weshalb sich auch der Aufruf unterscheidet.

Unter Windows:

dl('php_curl.dll');

Unter Linux:

dl('php_curl.so');

Anstatt in jedem Script die Sandbox-Keys oder den Token erneut zu hinterlegen, sollte dafür eine Konfigurationsdatei verwendet werden, die lediglich in das eigentliche Script eingebunden wird:

<?php

  $config['compatibility_level'] = '367';
  $config['dev_name'] = 'DEV-NAME';
  $config['app_name'] = 'APP-NAME';
  $config['cert_name'] = 'CERT-NAME';
  $config['session_certificate'] = $config['dev_name'].';'.$config['app_name'].';'.$config['cert_name'];
  $config['request_token'] = 'TOKEN';
  $config['siteid'] = '0';
  $config['detaillevel'] = '0';
  
?>

Listing 5.5: Die Datei config.inc.php

Natürlich müssen Sie die Werte in der config.inc.php durch Ihre eigenen ersetzen. Dies betrifft in diesem Fall dev_name, app_name, cert_name und request_token.

Das Hauptscript sieht wie folgt aus:

<?php

  /* Konfiguration einbinden */
  include('config.inc.php');
  
  $ebay_username = 'EBAY_TESTUSER_USERNAME';
  $ebay_password = 'EBAY_TESTUSER_PASSWORD';
  $ebay_url = 'https://api.sandbox.ebay.com/ws/api.dll';
  
  /* cURL laden */
  /* die nachfolgende Zeile können Sie aktivieren um cURL dynamisch zu laden */
  /* dies ist jedoch nicht nötig, wenn Sie cURL in der php.ini aktiviert haben */
  //  dl('php_curl.dll');

  /* XML-Dokument erzeugen */
  $apiXML = '<?xml version="1.0" encoding="iso-8859-1"?>';
  $apiXML .= '<request>';
  $apiXML .= '<RequestToken>'.$config['request_token'].'</RequestToken>';
  $apiXML .= '<RequestUserId>'.$ebay_username.'</RequestUserId>';
  $apiXML .= '<RequestPassword>'.$ebay_password.'</RequestPassword>';
  $apiXML .= '<ErrorLevel>1</ErrorLevel>';
  $apiXML .= '<DetailLevel>'.$config['detaillevel'].'</DetailLevel>';
  $apiXML .= '<Verb>GeteBayOfficialTime</Verb>';
  $apiXML .= '<SiteId>'.$config['siteid'].'</SiteId>';
  $apiXML .= '</request>';

  /* Header erzeugen */
  $apiHeader[] = 'X-EBAY-API-COMPATIBILITY-LEVEL: '.$config['compatibility_level'];
  $apiHeader[] = 'X-EBAY-API-SESSION-CERTIFICATE: '.$config['session_certificate'];
  $apiHeader[] = 'X-EBAY-API-DEV-NAME: '.$config['dev_name'];
  $apiHeader[] = 'X-EBAY-API-APP-NAME: '.$config['app_name'];
  $apiHeader[] = 'X-EBAY-API-CERT-NAME: '.$config['cert_name'];
  $apiHeader[] = 'X-EBAY-API-CALL-NAME: GetebayOfficialTime';
  $apiHeader[] = 'X-EBAY-API-SITEID: '.$config['siteid'];
  $apiHeader[] = 'X-EBAY-API-DETAIL-LEVEL: '.$config['detaillevel'];
  $apiHeader[] = 'Content-Type: text/xml';
  $apiHeader[] = 'Content-Length: '.strlen($apiXML);
  
  /* Anfrage senden */
  $apiAnswer = '';
  $chApi = curl_init($ebay_url);
  if($chApi)
  {
    curl_setopt($chApi,CURLOPT_CAINFO,'<vollständiger-pfad-zum-bundle>\ca-bundle.crt');
    curl_setopt($chApi,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($chApi,CURLOPT_POST,1);
    curl_setopt($chApi,CURLOPT_POSTFIELDS,$apiXML);
    curl_setopt($chApi,CURLOPT_HTTPHEADER,$apiHeader);
    $apiAnswer = curl_exec($chApi);
  }
  else
  {
    die('Fehler bei der Initialisierung von cURL.');
  }
  
  /* Antwort überprüfen */
  if($apiAnswer == false)
  {
    header('Content-Type: text/html');
    echo 'Fehler:<br><b>'.curl_errno($chApi).'</b> / '.curl_error($chApi);
  }
  else
  { 
    /* Daten ausgeben */
    header('Content-Type: text/xml');
    echo $apiAnswer;
  }

?>

Listing 5.6: Das eigentliche Script, das die Anfrage stellt

Zunächst erfolgt das Einbinden der Konfigurationsdatei config.inc.php. Da noch niemand anderes außer uns das Skript nutzen wird, werden der Benutzername und das Kennwort des eBay-Testusers direkt im Script festgelegt. In einem produktiven Einsatz sollten diese Daten nach Möglichkeit über das Array $_POST entgegengenommen werden. Anschließend wird noch die URL zur eBay-API der Sandbox in der Variablen $ebay_url gespeichert.

Da Sie die exakte Länge des XML-Dokuments in Byte benötigen, müssen Sie dieses definieren, bevor Sie den Header modifizieren können. Das eigentliche Dokument unterscheidet sich von dem aus Listing 5.4 nur darin, dass die korrekten Werte eingefügt werden. Das gesamte Dokument wird als Zeichenkette in der Variablen $apiXML gespeichert.

cURL erwartet, dass alle Zusatzangaben oder Modifizierungen der Informationen im Header als Array übergeben werden. Dabei wird für jede Information ein eigenes Element in dem Array verwendet. Jede Angabe wird außerdem als zusammenhängende Zeichenkette übergeben. Um die Länge des XML-Dokuments festlegen zu können, müssen Sie lediglich die Funktion strlen aufrufen und ihr als Parameter $apiXML übergeben:

$apiHeader[] = 'Content-Length: '.strlen($apiXML);

Nach diesen Vorbereitungen kann die Anfrage durchgeführt werden. cURL gibt Ihnen die Antwort als String zurück. Dieser String wird in der Variablen $apiAnswer gespeichert. Zunächst wird mit curl_init ein neues Handle erzeugt und der Variablen $chApi zugewiesen. Zusätzlich wird der Funktion die URL übergeben, zu der eine Verbindung hergestellt werden soll, in diesem Fall die eBay-API der Sandbox.

$chApi = curl_init($ebay_url);

Ist der Rückgabewert der Funktion ungleich false, war der Versuch erfolgreich. Im if-Anweisungsblock werden mit curl_setopt einige Informationen an cURL übergeben:

  • CURLOPT_RETURNTRANSFER
    Ein Wert ungleich 0 bedeutet, dass die Antwort auf die Anfrage als String zurückgegeben wird. Andernfalls würde cURL direkt die Ausgabe vornehmen.
  • CURLOPT_POST
    Ein Wert ungleich 0 bedeutet, dass die Daten mittels POST an den Empfänger verschickt werden sollen.
  • CURLOPT_POSTFIELDS
    Die mittels POST zu übertragenden Daten werden durch diesen Parameter übergeben. Im Fall der Anfrage ist dies das eigentliche XML-Dokument, das in $apiXML gespeichert wurde.
  • CURLOPT_HTTPHEADER
    Um den Header zu modifizieren, werden die Informationen mit diesem Parameter übergeben. Die notwendigen Modifizierungen wurden im Array $apiHeader gespeichert, das mit diesem Parameter übergeben wird.

Die Funktion curl_exec führt schlussendlich die Anfrage aus. Als Parameter muss das cURL-Handle übergeben werden. Je nachdem, ob cURL die Ausgabe der Antwort vornehmen soll, gibt die Funktion die Antwort als String zurück.

Sollte beim Versuch des Verbindungsaufbaus ein Fehler auftreten, wird die Ausführung des Scripts im else-Anweisungsblock abgebrochen.

Schlussendlich muss noch überprüft werden, ob überhaupt eine Antwort verfügbar ist. Ist der Wert von $apiAnswer gleich false, dann haben wir keine Antwort bekommen. In einem solchen Fall gibt curl_errno die Fehlernummer und curl_error die Fehlermeldung zurück.

Wurde eine Antwort geliefert, erfolgt ihre Ausgabe im else-Anweisungsblock. Normalerweise müsste nun eine Verarbeitung der Antwort erfolgen. Die Antwort ist immer ein XML-Dokument. In diesem Beispiel wird die Antwort jedoch einfach ausgegeben. Damit eine entsprechende Darstellung erfolgt, wird dem Browser mitgeteilt, dass es sich um ein XML-Dokument handelt.

Die Ausgabe des Scripts im Internet Explorer 6.0 und im Mozilla Firefox 0.93
Abbildung 5.2: Die Ausgabe des Scripts im Internet Explorer 6.0 und im Mozilla Firefox 0.93

In Abbildung 5.2 können Sie die Antwort der eBay-API auf unsere Frage nach der Uhrzeit auf dem Server sehen. Zu der erhaltenen Uhrzeit müssen Sie zwei Stunden hinzurechnen, um die Uhrzeit mit der in unserer Zeitzone gleichsetzen zu können. Beim Erstellen der Screenshots war es also einmal 13:25:25 Uhr und einmal 13:35:12 Uhr.

# Wichtiger Hinweis

Ein Problem stellt unter Umständen die verschlüsselte Verbindung mittels SSL dar. Bei SSL erfolgen Authentifizierungen über ein Zertifikat. Sollte PHP respektive cURL während des Versuchs, eine Anfrage zu stellen, abbrechen und Ihnen die Meldung

SSL certificate problem, verify that the CA cert is OK

ausgeben, kann das erhaltene Zertifikat nicht auf Gültigkeit überprüft werden. Sie benötigen dann eine Datei namens ca-bundle.crt, die Sie auf der dem Buch beiliegenden CD‑ROM im Verzeichnis x:\listings\xml\ebay finden.

Um cURL mitzuteilen, wo es diese Datei finden kann, müssen Sie folgende Zeile auskommentieren:

// curl_setopt($chApi,CURLOPT_CAINFO, <vollständiger-pfad-zum-bundle>\ca-bundle.crt’);

Wichtig ist, dass Sie auf jeden Fall einen vollständigen Pfad zum Bundle eintragen. Liegt die Datei ca-bundle.crt also im htdocs-Verzeichnis Ihres Webservers, könnte der Pfad folgendermaßen aussehen: c:\apache group\apache2\htdocs\ca-bundle.crt

Die Angabe eines relativen Pfades führt dazu, dass cURL das Bundle nicht finden kann.

# Zusammenfassung

  • Webservices dienen zur Kommunikation zwischen zwei Maschinen.
  • Es gibt zwei gängige Standards: XML-RPC und SOAP.
  • Sowohl XML-RPC als auch SOAP nutzen als Protokoll HTTP, jedoch wird der Header des Protokolls in der Regel modifiziert.
  • Beide Standards nutzen bei der Formulierung der Anfragen XML.
  • Die eBay-API ist zwar ein Webservice, basiert aber auf keinem der beiden gängigen Standards. Anlehnungen sind jedoch zu finden.

# Fragen und Übungen

  1. Was ist WSDL?
  2. Worin besteht der Unterschied zwischen einem auf XML-RPC basierenden Webservice und einem, der SOAP nutzt?
  3. Wozu dient bei der eBay-API das Element DetailLevel im Header und dem Dokument?
  4. Welche Bibliothek benötigen Sie in PHP, um Webservices wie z. B. die eBay-API nutzen zu können?
  5. Was ist die »Sandbox«?