Onlinebanking per Webservice

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Onlinebanking per Webservice

Die Firma B+S Banksysteme AG bietet einen Webservice für das Onlinebanking an. Damit können Sie einfache Aktionen durchführen – zum Beispiel den Kontostand ermitteln, Umsätze einlesen oder Überweisungen tätigen. Bislang ist der Gebrauch für Privatpersonen kostenlos, und für die geschäftliche Nutzung gibt es günstige Jahreslizenzen. Eine Einschränkung ist, dass dieser Webservice aktuell nur mit Konten funktioniert, die PIN/TAN per HBCI anbieten. Dies ist leider nicht bei allen Kreditinsituten der Fall.

Onlinebanking ist ein interessanter Anwendungsfall für Access-Datenbanken. Egal, ob Sie eine Anwendung für Kunden damit ausstatten – etwa eine Vereinsverwaltung – oder selbst eine selbst entwickelte Software nutzen möchten, um ihre eigenen Konten im Überblick zu behalten und gegebenenfalls auch einmal eine Überweisung zu tätigen.

In Access im Unternehmen haben wir bereits die DDBAC-Komponente vorgestellt, die ebenfalls vom Hersteller B+S Banksysteme AG stammt (zum Beispiel in Onlinebanking mit SEPA, http://www.access-im-unternehmen.de/898).

Während Sie diese Komponente vor der Nutzung installieren mussten, fällt dieser Aufwand bei Verwendung eines Webservice natürlich nicht an: Access liefert, ergänzt um einige externe Bibliotheken, die aber auf jedem Rechner installiert sind, alle notwendigen Werkzeuge für den Zugriff auf Webservices.

Dafür muss man natürlich das Vertrauen mitbringen, dass die Daten vor der Übermittlung an die Bank über den Webservice des Anbieters laufen und auf dem Rückweg ebenso (s. Bild 1).

Verlauf einer Anfrage beim Onlinebanking per Webservice

Bild 1: Verlauf einer Anfrage beim Onlinebanking per Webservice

Allerdings weiß man als Otto Normalverbraucher bei den gängigen Softwarepaketen, die Onlinebanking-Funktionen bereitstellen, auch nicht, über welche Wege die Daten zur Bank und zurück gelangen.

Schlussendlich entscheiden Sie aber selbst, ob Sie einen solchen Webservice nutzen möchten oder nicht.

Wir zeigen Ihnen in diesem Beitrag jedenfalls, wie dies gelingt. Sollten Sie dem Braten vorerst nicht trauen oder einfach ein wenig mit dem Webservice experimentieren wollen, können Sie auch eines der für diesen Zweck vorgesehenen Testkonten nutzen – mehr dazu siehe weiter hinten.

Was kann die Bank?

Als Erstes wollen wir überhaupt einen Kontakt zur Bank herstellen und herausfinden, welche Möglichkeiten die Bank überhaupt über den Webservice anbietet.

Wie bereits erwähnt, können Sie über den Webservice nur Daten mit Banken austauschen, die PIN/TAN als Authentifizierungsmethode anbieten – und wir wollen nun zunächst herausfinden, ob die gewünschte Bank dieses Feature anbietet.

Grundsätzlich müssen wir dazu eine geeignete SOAP-Anfrage im XML-Format an den Webservice schicken. Dieser verarbeitet die Anfrage dann und liefert die Antwort ebenfalls im XML-Format zurück.

Eine solche Abfrage kann beispielsweise wie in Listing 1 aussehen. Diese Abfrage enthält beispielsweise die Information, dass wir die Funktion GetBankInfo ausführen wollen, welche als einzigen Parameter die Bankleitzahl erwartet. Diese platzieren wir in einem weiteren Element namens sBankCode.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" ...>
   <SOAP-ENV:Body>
     <s0:GetBankInfo xmlns:s0="http://service.ddbac.de/">
       <s0:sBankCode>70000997</s0:sBankCode>
     </s0:GetBankInfo>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Listing 1: Abfrage an den Webservice, um die Funktionen für eine bestimmte Bank zu ermitteln

Wenn wir diese Anfrage an den Server schicken, erhalten wir eine Antwort, die etwa wie in Listing 2 erscheint. Auf den ersten Blick sieht das alles etwas verwirrend aus. Wenn man weiß, was man sucht, erleichtert dies die Sache jedoch erheblich. Um herauszufinden, ob die Bank Pin/Tan anbietet, muss hier beispielsweise ein Element namens PinTanConnection vorliegen – genau das ist hier der Fall.

<GetBankInfoResponse xmlns="http://service.ddbac.de/">
     <GetBankInfoResult>
         <FinTSConnection>
             ...
         </FinTSConnection>
         <PinTanConnection>
             <CommAddress>https://fints.datadesign.de/j2hbci-gateway/j2hbci
                                                                     </CommAddress>
             <AdressSuffix>64</AdressSuffix>
             <FinTSVersion>300</FinTSVersion>
             <UserIDName>Benutzerkennung</UserIDName>
             <CustomerIDName>Kunden ID</CustomerIDName>
             <Parameters>
                 <ContactParameter>
                     <ID>CountryCode</ID>
                     <DefaultValue>280</DefaultValue>
                     <IsVisible>true</IsVisible>
                     <IsMandatory>true</IsMandatory>
                     <Label>Länderkennzeichen</Label>
                     <MinLength>3</MinLength>
                     <MaxLength>3</MaxLength>
                     <Pattern>d{3}</Pattern>
                 </ContactParameter>
                 <ContactParameter><ID>SecurityMediaDetailID</ID>...</ContactParameter>
                 <ContactParameter><ID>HBCIVersion</ID>...</ContactParameter>
                 <ContactParameter><ID>CommunicationsAddress</ID>...</ContactParameter>
                 <ContactParameter><ID>CommunicationsAddressSuffix</ID>...
                                                                 </ContactParameter>
                 <ContactParameter><ID>BankCode</ID>...</ContactParameter>
                 <ContactParameter><ID>UserID</ID>...</ContactParameter>
                 <ContactParameter><ID>CustomerID</ID>...</ContactParameter>
             </Parameters>
         </PinTanConnection>
         <BankCode>70000997</BankCode>
         <BIC>DDBADEMM002</BIC>
         <Bankname>B+S Banksysteme Demobank FinTS3</Bankname>
         <DefaultUserIDName>Benutzerkennung</DefaultUserIDName>
         <DefaultCustomerIDName>Kunden ID</DefaultCustomerIDName>
         <Xml>...</Xml>
         <TestSystem>true</TestSystem>
     </GetBankInfoResult>
</GetBankInfoResponse>

Listing 2: Rückmeldungen mit den Bankinformationen

Wenn Sie die obige Anfrage etwa für die Bankleitzahl 35040038 gestellt hätten (Commerzbank), hätte die Antwort kein Element namens PinTanConnection enthalten.

Innerhalb dieses Elements finden Sie einige Informationen, welche Daten Sie für die Authentifizierung benötigen. Darunter finden Sie die Bankleitzahl, die BIC, den Namen der Bank, die Bezeichnung für die Felder UserID und CustomerID sowie einige weitere Informationen.

Aufbau der Webservice-Anfragen

Wie bei jedem anderen Webservice gibt es auch für den Onlinebanking-Webservice eine Beschreibung in Form einer WDSL-Datei. Diese finden Sie unter dem folgenden Link:

https://service.ddbac.de/demo/ServiceNG.asmx?WSDL

Diese Seite zeigt den Aufbau der verschiedenen Request- und Response-Elemente des Webservice an (s. Bild 2). Mit ein wenig Erfahrung lassen sich hiermit die gewünschten Requests zusammenstellen (die Antworten liefert ohnehin der Webservice). Es gibt jedoch auch eine einfachere Möglichkeit – nämlich eine Software, die aus dieser Datei alle Requests ausliest und in einer Form aufbereitet, in der Sie sogar die benötigten Parameter einfügen und die Requests gegen den Webservice testen können.

Beschreibung der Requests und Responses des Webservice

Bild 2: Beschreibung der Requests und Responses des Webservice

Webservice-Anfragen testen

Bevor wir den Zugriff auf die Webservices per VBA programmieren, schauen wir uns eine solche Plattform an, mit der Sie die einzelnen Anfragen testen und die Antworten einsehen können.

Dies ist insbesondere inte­ressant, wenn beim Absenden der SOAP-Anfrage per VBA Fehler auftreten, die Sie sich nicht erklären können. In diesem Fall macht es Sinn, den Request separat über eine externe Plattform zu testen, um zu prüfen, ob es an dem Request selbst liegt.

Die Testplattform nennt sich SoapUI und ist kostenlos verfügbar. Sie können dieses Tool unter soapui.org herunterladen. Nachdem Sie es gestartet haben, können Sie mit dem Menübefehl File|New Soap Project ein neues Projekt erstellen. Dazu erscheint ein kleiner Dialog, dem Sie die benötigten Daten für den Zugriff auf den Webservice mitteilen können (s. Bild 3).

Eingabe der Daten des Webservices in die Testoberfläche

Bild 3: Eingabe der Daten des Webservices in die Testoberfläche

Tragen Sie für das Feld Project Name den Wert AiUOnlinebanking ein, für InitialWDSL die Adresse der WDSL-Datei:

https://service.ddbac.de/demo/ServiceNG.asmx?WSDL

Setzen Sie den Haken für die Option Create Requests, die übrigen Optionen können Sie deaktivieren.

Nach dem Klick auf die Schaltfläche OK ackert das Tool einige Augenblicke und präsentiert dann links in der Übersicht alle Funktionen des Webservices (s. Bild 4).

Auflistung der Funktionen des Webservices

Bild 4: Auflistung der Funktionen des Webservices

Wir wollen uns zunächst die einfache Funktion GetBankInfo ansehen. Also klicken Sie mit der rechten Maustaste auf diese Funktion und wählen dort den Eintrag New Request aus. Geben Sie als Name die Bezeichnung der Funktion ein, also GetBankInfo.

SoapUI erstellt nun ein neues Fenster, das den kompletten Request enthält – mit Ausnahme des einzigen Parameters sBankCode (s. Bild 5).

Der Webservice-Request GetBankInfo

Bild 5: Der Webservice-Request GetBankInfo

Den Request können Sie nach Belieben anpassen, also können Sie dort auch das einzige Fragezeichen durch den gewünschten Wert ersetzen. Wir verwenden die Test-Bankleitzahl 70000997 und klicken dann oben links im Fenster auf die Schaltfläche mit dem grünen Pfeil. Und siehe da: Nach kurzer Wartezeit erscheint im Bereich rechts von unserem Request schon die Antwort des Webservers (s. Bild 6)!

Test eines Requests inklusive Response des Webservers

Bild 6: Test eines Requests inklusive Response des Webservers

Die Arbeit mit SoapUI ist wirklich so einfach, dass ich nur jedem Entwickler, der einmal den Zugriff auf einen Webservice programmiert, die Nutzung dieses Tools empfehlen kann.

Sollten Sie SOAP-Requests absetzen wollen, die weitere Informationen wie etwa Header-Daten oder eine Authentifizierung erfordern, nutzen Sie die Bereiche unter dem Request.

Dort können Sie alle benötigten Informationen hinzufügen.

Der Request funktioniert also wie gewünscht – dann können wir uns an die Umsetzung mit VBA begeben.

Request per VBA absetzen

Für den ersten Request und zum Einarbeiten bauen wir uns ein kleines Formular, in das wir den Wert für den einzigen Parameter eintragen. Mit der Schaltfläche cmdRequest wollen wir den Request zusammenstellen und absenden sowie die Antwort des Webservers entgegennehmen. Der Request soll im Textfeld txtRequest landen, die Response im Textfeld txtResponse (s. Bild 7). Beide Textfelder sollen für die Eigenschaft Bildlaufleisten den Wert Vertikal erhalten. Sofern Sie Access 2007 oder neuer nutzen, stellen Sie auch die Eigenschaft Horizontaler Anker für beide Textfelder auf den Wert Beide ein.

Formular zur Ausgabe von Response und Request

Bild 7: Formular zur Ausgabe von Response und Request

Bevor wir mit der Programmierung beginnen, richten wir noch einen Verweis auf die Bibliothek Microsoft XML, v6.0 im Verweise-Dialog ein (VBA-Editor, Menübefehl Extras|Verweise) – s. Bild 8.

Verweis auf die XML-Bibliothek

Bild 8: Verweis auf die XML-Bibliothek

Danach stellen wir den Request zusammen – mit einigen Hilfsfunktionen, die den Vorgang ein wenig besser strukturieren und außerdem wiederverwendbar sind. Den Start macht die Prozedur, die durch den Mausklick auf die Schaltfläche cmdRequest ausgelöst wird (s. Listing 3). Die Prozedur prüft zunächst, ob der Benutzer eine Bankleitzahl im korrekten Format eingegeben hat. Anderenfalls erscheint eine entsprechende Meldung. Gegen ungültige Bankleitzahlen ist die Prozedur hingegen nicht gefeit – es kommt lediglich ein leeres Request-Dokument zurück.

Private Sub cmdRequest_Click()
     Dim strRequest As String
     Dim strResponse As String
     Dim strErrorCode As String
     Dim strErrorText As String
     If Not (Len(Me!txtBLZ) = 8 And IsNumeric(Me!txtBLZ)) Then
         MsgBox "Geben Sie eine BLZ mit acht Stellen ein."
         Me!txtBLZ.SetFocus
         Exit Sub
     End If
     GetBankInfo Me!txtBLZ, strErrorCode, strErrorText, strRequest, strResponse
     Me!txtRequest = FormatXML(strRequest)
     Me!txtResponse = FormatXML(strResponse)
End Sub

Listing 3: Aufruf der Webservice-Funktion GetBankInfo

Hat die Bankleitzahl das korrekte Format, ruft die Prozedur die Routine GetBankInfo auf. Diese erwartet fünf Parameter, von denen zwei optional sind. Der erste erwartet die BLZ der zu untersuchenden Bank, der zweite und der dritte leere Variablen, die beim Auftreten eines Fehlers gefüllt werden. Für beiden Variablen strRequest und strResponse übergeben Sie ebenfalls leere String-Variablen, die dann mit dem Request und dem Response gefüllt werden.

Nach dem Aufruf der Routine GetBank­Info trägt die Prozedur cmdRequest_Click noch den erhaltenen Request und Response in die entsprechenden Textfelder zur genaueren Betrachtung ein. Dabei werden beide mit der Funktion FormatXML formatiert, also mit Zeilenumbrüchen und Einrückungen versehen. Der Webservice liefert seine Daten nämlich komplett ohne solche Formatierungen.

GetBankInfo

Die Funktion GetBackInfo aus Listing 4 steuert die Erstellung des Requests und sendet diesen ab – beides mit weiteren Hilfsfunktionen. Die Parameter dieser Funktion haben wir ja schon weiter oben beschrieben. Die Funktion speichert zunächst den Namen der Webservice-Funktion in der Variablen strFunction. Diese übergibt sie zusammen mit dem Kern-Element des Requests an eine weitere Routine namens CreateSoapRequest. Der Kern sieht mit der Beispiel-BLZ 70000997 so aus:

Public Function GetBankInfo(strBLZ As String, strErrorCode As String, _
         strErrorText As String, Optional strRequest As String, _
         Optional strResponse As String) As String
     Dim objXMLResponse As MSXML2.DOMDocument
     Dim strFunction As String
     strFunction = "GetBankInfo"
     strRequest = CreateSoapRequest("            <ser:sBankCode>" & strBLZ _
         & "</ser:sBankCode>", strFunction)
     Request strRequest, objXMLResponse
     strResponse = objXMLResponse.selectSingleNode("//" & strFunction & "Response").XML
     strErrorCode = GetXMLElement(strResponse, strFunction & "Result/Error/ErrorCode")
     strErrorText = GetXMLElement(strResponse, strFunction & "Result/Error/ErrorText")
     GetBankInfo = GetXMLElement(strResponse, strFunction & "Result")
End Function

Listing 4: Die Funktion GetBankInfo

<ser:sBankCode>70000997</ser:sBankCode>"

Die Routine CreateSoapRequest stellt aus dem Kern des XML-Dokuments und dem Namen der Funktion den Request zusammen und liefert diesen zurück.

Der Aufruf der Prozedur Request ist der nächste Schritt: Diese erwartet den Request in Form der String-Variablen strRequest und eine leere Variable namens objXMLResponse. Diese hat den Typ MSXML2.DOMDocument.

Das mit objXMLResponse zurückgelieferte XML-Dokument wertet die Prozedur anschließend aus. Die Funktion selectSingleNode nimmt einen XPath-Ausdruck (die Abfragesprache für XML-Dokumente), der in diesem Fall das Element //GetBankInfoResponse zurückliefern soll. Damit befreit die Prozedur quasi die Antwort aus dem SOAP-Umschlag, also die umschließenden SOAP-Elemente:

<?xml version="1.0"?>
<soap:Envelope ...>
     <soap:Body>
         <GetBankInfoResponse ...>
             <GetBankInfoResult>
                 ...
             </GetBankInfoResult>
         </GetBankInfoResponse>
     </soap:Body>
</soap:Envelope>

Übrig bleibt dann also:

<GetBankInfoResponse ...>
     <GetBankInfoResult>
         ...
     </GetBankInfoResult>
</GetBankInfoResponse>

Das Ergebnis landet in der Variablen strResponse. Außerdem ermittelt die Prozedur noch eventuell auftretende Fehler. Dazu verwendet sie eine Hilfsfunktion namens GetXMLElement. Diese bietet eine einfache Möglichkeit, durch einen Einzeiler ein Element aus einem XML-Dokument auszulesen (s. Listing 5). Dies kann man zwar auch wie in der vorherigen Anweisung direkt mit der Funktion selectSingleNode erledigen. Allerdings liefert dies einen Fehler, wenn Sie direkt auf den Inhalt dieses Elements zugreifen, dieses aber nicht gefunden werden konnte. Dies umgeht die Funktion GetXMLElement, indem sie erst das Element mit einer Objektvariablen referenziert und dann prüft, ob die Objektvariable überhaupt gefüllt ist. Nur dann fragt die Funktion den Wert dieses Elements ab und liefert diesen als Funktionswert zurück. Anderenfalls ist eine leere Zeichenkette das Ergebnis.

Public Function GetXMLElement(strXML As String, strElement As String)
     Dim objXML As MSXML2.DOMDocument
     Dim objElement As MSXML2.IXMLDOMNode
     Dim objNode As MSXML2.IXMLDOMNode

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.