PHP und BiPRO Teil 6: Norm410 Response und die Classmap

Seit etwas längerer Zeit beschäftige ich mich mal wieder intensiv mit dem Thema BiPRO, weil ich für die vs vergleichen-und-sparen GmbH ein BiPRO Modul für das Zend Framework 2 programmiere. Wer das Zend Framework 2 kennt, weiß, dass dort wirklich alles ein Objekt ist. Das ist auch gut so. Im Zusammenhang mit BiPRO stehe ich da allerdings oft vor Problemen. Die Anbieter selbst geben in ihren Beispielen String- oder Template basierte Lösungen an. Kann man mit dem Zend Framework 2 natürlich auch machen, geht mir, als jemand der objektorientierte Programmierung ziemlich geil findet, aber ziemlich gegen den Strich. Zumal der Client und Server die XML Strukturen vollkommen allein zusammen setzen können. Man muss eben nur wissen wie.

Heute erweitern wir das Security Token Service Beispiel (Norm 410), welches in diesem Blog als Download verfügbar ist. Ich zeige Euch, wie man die ein wenig ekelige Response direkt mit einem Objekt auffangen kann. Dieses Objekt wird über entsprechende Getter Methoden verfügen, mit denen ihr die Inhalte der Response sehr einfach bekommen könnt. Wieso ist das cool? Weil die SoapClient und SoapServer Objekte diesen Job eigentlich schon von Haus aus übernehmen. Also bleiben wir in einem objektorientierten Kontext und nutzen diese Eigenschaft einfach.

Wie sieht die Response des STS in Rohform aus

Folgend ist die Response aus meinem Download Beispiel so dargestellt, wie sie einfach vom Client interpretiert wird.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
object(stdClass)#14 (1) {
  ["any"]=>
  array(4) {
    [0]=>
    string(75) "http://schemas.xmlsoap.org/ws/2005/02/sc/sct"
    ["Lifetime"]=>
    &object(stdClass)#15 (2) {
      ["Created"]=>
      object(stdClass)#16 (1) {
        ["_"]=>
        string(19) "2016-10-21 11:35:18"
      }
      ["Expires"]=>
      object(stdClass)#17 (1) {
        ["_"]=>
        string(19) "2016-10-21 12:35:18"
      }
    }
    ["RequestedSecurityToken"]=>
    object(stdClass)#18 (1) {
      ["any"]=>
      string(124) "bipro:3fb8a718b859b940af53208ecd1e4bc7"
    }
    [1]=>
    string(46) "2.1.0.1.0"
  }
}

Die im Security Token Request verwendeten BiPRO und Web Defintionen (XSD) geben diese Struktur des zurück gelieferten Objektes vor. Wir sehen hier also ein strikt nach Definitionen übersetztes Objekt mit den üblichen Eigenheiten von PHP. Soap Responses mit PHP geben, sofern in den Webservice Definitionen nicht anders notiert, Werte mit einem Unterstrich zurück.

Zum Verständnis auch noch mal die XML Struktur, aus der dieses Objekt resultiert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< ?xml version="1.0" encoding="UTF-8"?>
<env:envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns3="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:ns4="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:ns5="http://www.bipro.net/namespace/allgemein">
  <env:body>
    <ns3:requestsecuritytokenresponse>
      <ns1:tokentype>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</ns1:tokentype>
      <ns3:lifetime>
        <ns2:created>2016-10-21 11:35:18</ns2:created>
        <ns2:expires>2016-10-21 12:35:18</ns2:expires>
      </ns3:lifetime>
      <ns3:requestedsecuritytoken>
        <ns4:securitycontexttoken>
          <ns4:identifier>bipro:3fb8a718b859b940af53208ecd1e4bc7</ns4:identifier>
        </ns4:securitycontexttoken>
      </ns3:requestedsecuritytoken>
      <ns5:biproversion>2.1.0.1.0</ns5:biproversion>
    </ns3:requestsecuritytokenresponse>
  </env:body>
</env:envelope>

Dieses XML Schema wird von dem im Beispiel enthaltenen Soap Server zurück geliefert und entsprecht der BiPRO Norm 410. Ja, ich weiß, dass der Identifier in der echten Welt mindestens ein 1024 Bit String ist. Als Beispiel soll dieser verkürzte Hash einfach mal reichen.

Wie geht das denn vernünftig?

Natürlich bietet PHP eine Lösung, um mit dieser Response vernünftig umgehen zu können. Vernünftig heißt in diesem Sinne einfach, dass mit einer Getter Methode einfach das SecurityContextToken Element zur weiteren Verwendung zurück gegeben wird. Oder einfach eine Getter Methode, um den Identifier als String zurück zu liefern. Oder eine Getter Methode, die die Lifetime zurück gibt.

Die Lösung lautet einfach Classmap. Eigentlich eine Classmap, wie man sie eventuell auch schon aus dem Zend Framework 2 Autoloading kennt. Ein einfaches Array mit Zuweisungen von Namensräumen zu entsprechenden Klassen. Einsolches Array können wir auch dem Soap Client mitgeben. Das sieht dann im Download Beispiel wie folgt aus.

1
2
3
4
5
6
7
8
9
10
11
12
13
$oClient = new \SoapClient(
    $sWsdl,
    [
        'trace'        => true,
        'exception'    => true,
        'cache_wsdl'   => WSDL_CACHE_NONE,
        'compression'  => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
        'soap_version' => SOAP_1_2,
        'classmap'     => [
            'RequestSecurityTokenResponseType' => 'MMNewmedia\BiPRO\Norm410\Model\RequestSecurityTokenResponseType',
        ],
    ]
);

Was habe ich jetzt hier gemacht? Das PHP SoapClient Objekt bietet die Option classmap, welche das eben schon erwähnte Array mit Zuweisungen von Typ Bezeichnungen zu Klassen beinhaltet. Diese Klasse wird dann vom Client voll automatisch aufgerufen, sobald eine Response mit dem angegebenen Namen verfügbar ist. Jetzt werdet ihr Euch wahrscheinlich fragen, woher der Nerd eigentlich weiß, wie der zurück gelieferte Typ eigentlich heißt? Nun, lasse ich mir vom Client die Funktionen des Werbservices ausgeben, erhalte ich folgende Ausgabe.

1
2
3
4
array(1) {
  [0]=>
  string(91) "RequestSecurityTokenResponseType RequestSecurityToken(RequestSecurityTokenType $parameters)"
}

Hieraus geht hervor, dass der zurückgegebene Typ den Namen RequestSecurityTokenResponseType trägt. Dies geht auch aus der WSDL Datei und den damit verbundenen XSD Dateien hervor. Der Soap Client bedient sich anhand dieser Informationen. Ich kann mir nun den entsprechen Typen aus der Lise der Typen heraussuchen, die mir der Soap Client zurück gibt.

1
2
3
4
string(75) "struct RequestSecurityTokenResponseType {
  any;
  anyURI Context;
}"

Was sagt uns diese Definition? Unfassbar wenig! Eigentlich sagt es uns nur, dass wir hier eine Eigenschaft mit dem Namen any haben. Darunter kann dann alles mögliche stehen. Um das alles in einem Objekt verwertet zu bekommen, benötigen wir das eingangs erwähnte, ekelige Response Objekt, um einfach in Erfahrung zu bringen, wie die Datenstruktur aussieht. Daraus können wir dann unser Objekt aufbauen.

Das Datenobjekt für die Response

Fassen wir mal zusammen, was wir jetzt wissen. Wir haben den Namen des Typs, der zurück geliefert wird. Wir wissen, dass wir diesem Typen mittels Classmap eine Klasse zuweisen können, die automatisch vom Client aufgerufen wird, wenn die Response eintrifft. Wir wissen, wie die Datenstruktur aussieht, die vom Client empfangen wird. Also setzen wir uns einfach mal unser Objekt zusammen. Im folgenden Beispiel lasse ich mir einfach das SecurityContextToken Element als SoapVar Objekt zurückgeben. Dieses kann dann in weiteres Requestes verwendet werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
namespace MMNewmedia\BiPRO\Norm410\Model;
 
use MMNewmedia\BiPRO\Entity\SecurityContextToken;
 
/**
 * RequestSecurityTokenResponse Entity nach BiPRO Norm (utf-8)
 * Wertet die RequestSecurtiyToken Response eines BiPRO Security Token Webservices aus
 *
 * @author Marcel Maaß 
 * @copyright 2016 MM Newmedia 
 * @package de.mmnewmedia.bipro
 * @subpackage entity
 * @since 2016-10-20
 * @version
 */
class RequestSecurityTokenResponseType {
 
    /**
     * Liefert den SecurityContextToken Knoten als SoapVar für die weitere Verwendung
     * @return \SoapVar
     */
    public function getSecurityContextToken() {
        $oIdentifier = new \SoapVar(
            $this->any['RequestedSecurityToken']->any,
            XSD_STRING,
            null,
            null,
            'Identifier',
            'http://schemas.xmlsoap.org/ws/2005/02/sc'
        );
 
        $oSecurityContextToken = new SecurityContextToken();
        $oSecurityContextToken->setIdentifier($oIdentifier);
 
        return $oSecurityContextToken->encode();
    }
}
 
// Beispiel
$oResult = $oClient->RequestSecurityToken($oMeineParameter);
$oSecurityContextToken = $oResult->getSecurityContextToken();

Wie man hier sehr schön sehen kann, kann ich in diesem Objekt direkt auf $this->any zugreifen. Ich verfüge also direkt über die Datenstruktur der Response (dem ekeligen Objekt), die eingangs schon erwähnt wurde, und kann die erhaltenen Daten dann entsprechend aufbereiten. So kann ich also ganz bequem alles so aufbereiten, wie ich es brauche. Im Download sind weitere Methoden enthalten, die unter anderem das Lifetime Objekt und den Identifier zurück geben.

Fazit

Zugegeben sieht das am Anfang alles ganz schön unstrukturiert und vielleicht auch überdimensioniert aus. Letztendlich kann ich mir aber so ganz komfortabel die Teile aus der Response so zurückgeben lassen, wie ich sie im weiteren Verlauf benötige. Die oben dargestellte Funktion benötige ich z.B., um den ermittelten Security Token für die Requests der Tarifierung nach BiPRO Norm 421 weiter zu verwenden.
Schade ist nur, dass diese Vorgehensweise in der PHP Dokumentation zwar erwähnt, aber nicht erklärt wird. An einigen wenigen Stellen im Netz wird zwar an einfachen Beispielen erklärt, wie Classmaps im SoapClient funktionieren. Aber BiPRO Prozesse sind um einiges komplexer, als die im Netz erwähnten Beispiele. Also wird der Lernerfolg hier einfach erzielt, indem man es einfach macht.
Nachteil ist mal wieder, dass selbst die BiPRO Norm 410 ziemlich unterschiedlich von den verschiedenen Anbietern umgesetzt wird. Das gezeigte Beispiel funktioniert mit dem Standard Security Token Service der BiPRO, so wie sie sich ihn im Idealfall vorstellt. In der Praxis muss man oftmals für jeden Service ein eigenes Response Model entwickeln, um die Eigenheiten der Versicherer zu berücksichtigen. Beim Security Token Service nicht so oft. Bei den Tarifierungs Services sieht es da schon ganz anders aus.

Mit dem Response Objekt wäre die Norm 410 jetzt also komplett mit PHP umgesetzt. War doch gar nicht so schwer, oder?

Download

Wie auch schon beim letzten Download, müsst ihr beachten, dass in der mitgelieferten WSDL Datei der Endpunkt an Eure Umgebung angepasst werden muss. Bitte beachtet auch, dass das gelieferte Beispiel auch wirklich nur ein Beispiel ist. Ich übernehme keinerlei Haftung, falls ihr das Beispiel trotz dieser kleinen Warnung produktiv einsetzt.

Der Aufruf erfolgt dann über http://www.deinedomain.tld/bipro/norm410/client.php.

Download “BiPRO Norm 410 Version 1.1” mmnewmedia-bipro-norm410_1.1.zip – 98-mal heruntergeladen – 74 KB

Noch ein kleines persönliches Anliegen. Wenn ihr das Beispiel nutzt hinterlasst ruhig mal eine Kritik oder ein Like. Sagt ruhig mal, was ihr denkt. Ich persönlich bin immer am Austausch mit anderen interessiert.

In diesem Sinne. Haben wir wieder was gelernt. 😉

Tags: , , , , , ,
About Author: Marcel
Ich bin Senior PHP Developer bei MM Newmedia. Seit 2005 bin ich begeisterter Webentwickler und arbeite als Freelancer für namenhafte Firmen und entwickle jede Menge abgefahrenes Zeug und berichte darüber in meinem Blog.

Kommentar verfassen