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).
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.asmxWSDL
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.
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).
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.asmxWSDL
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).
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).
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)!
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.
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.
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 Set objXML = New MSXML2.DOMDocument objXML.loadXML strXML Set objElement = objXML.documentElement Set objNode = objElement.selectSingleNode(strElement) If Not objNode Is Nothing Then GetXMLElement = objNode.nodeTypedValue End If End Function
Listing 5: Die Hilfsfunktion GetXMLElement
Die Funktion GetBankInfo liest also die Elemente Result/Error/ErrorCode und Result/Error/ErrorText und speichert die Inhalte in den Rückgabeparametern strErrorCode und strErrorText.
SOAP-Request zusammenstellen
Damit kommen wir zunächst zur Funktion CreateSoapRequest (s. Listing 6). Diese steuert eine Reihe weiterer Funktionen, die den Basis-Request aus der Variablen strBasicRequest und den Funktionsnamen zusammenstellen. Diese Funktion können wir für weitere Anfragen wiederverwenden, denn wir brauchen auch für die übrigen Requests eigentlich nur den Funktionsnamen (hier GetBankInfo) und die paar Zeilen XML-Code mit den notwendigen Parametern.
Public Function CreateSoapRequest(strBasicRequest As String, strFunction As String) As String Dim strRequest As String strRequest = RequestEnvelopeStart strRequest = strRequest & RequestBodyStart(strFunction) strRequest = strRequest & strBasicRequest & vbCrLf strRequest = strRequest & RequestBodyEnde(strFunction) strRequest = strRequest & RequestEnvelopeEnde CreateSoapRequest = strRequest End Function
Listing 6: Die Funktion CreateSoapRequest
Die Funktion stellt in der String-Variablen strRequest den Request zusammen. Den Beginn macht die Funktion Re-quest-EnvelopeStart (s. Listing 7). Die Prozedur liefert das öffnende Element des SOAP-Umschlages €“ also in gekürzter Form etwa diese beiden Zeilen:
Public Function RequestEnvelopeStart() As String Dim strRequest As String strRequest = strRequest _ & "<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" " _ & "xmlns:ser=""http://service.ddbac.de/"">" & vbCrLf strRequest = strRequest & " <soapenv:Body>" & vbCrLf RequestEnvelopeStart = strRequest End Function
Listing 7: Die Funktion RequestEnvelopeStart
<soapenv:Envelope ...> <soapenv:Body>
Danach folgt der öffnende Teil des eigentlich XML-Requests, den die Funktion RequestBodyStart beisteuert (s. Listing 8). Diese Funktion erwartet den Namen der zu verwendenden Methode als Parameter und liefert dann diese Zeile:
Public Function RequestBodyStart(strMethod As String) As String Dim strRequest As String strRequest = strRequest & " <ser:" & strMethod & ">" & vbCrLf RequestBodyStart = strRequest End Function
Listing 8: Die Funktion RequestBodyStart
<ser:GetBankInfo>
Nun folgt der eigentliche Inhalt aus der Variablen strBasicRequest:
<ser:sBankCode>70000997</ser:sBankCode>"
Die folgende Funktion RequestBodyEnde (s. Listing 9) schließt den Request €“ wieder mithilfe des Wertes aus der Variablen strMethod:
Public Function RequestBodyEnde(strMethod As String) As String Dim strRequest As String strRequest = strRequest & " </ser:" & strMethod & ">" & vbCrLf RequestBodyEnde = strRequest End Function
Listing 9: Die Funktion RequestBodyEnde
<ser:sBankCode>70000997</ser:sBankCode>"
Nun fehlen nur noch die schließenden Elemente des SOAP-Umschlags, welche die Funktion RequestEnvelopeEnde aus Listing 10 beisteuert:
Public Function RequestEnvelopeEnde() As String Dim strRequest As String strRequest = strRequest & " </soapenv:Body>" & vbCrLf strRequest = strRequest & "</soapenv:Envelope>" & vbCrLf RequestEnvelopeEnde = strRequest End Function
Listing 10: Die Funktion RequestEnvelopeEnde
</soapenv:Body> </soapenv:Envelope>
Dieser Request wird dann von der Funktion CreateSoapRequest an die aufrufende Routine GetBankInfo zurückgeschickt.
Request ausführen
Die Routine GetBankInfo ruft nun schlussendlich die Funktion Request auf, welche die folgenden zwei Parameter verwendet (s. Listing 11):
Public Function Request(strRequest As String, objXMLResponse As MSXML2.DOMDocument) _ As Boolean Dim strURL As String Dim objXMLHTTP As MSXML2.XMLHTTP60 Set objXMLHTTP = New MSXML2.XMLHTTP60 Set objXMLResponse = New MSXML2.DOMDocument strURL = cURLBase With objXMLHTTP .Open "post", strURL, False .setRequestHeader "Content-Type", "text/xml; charset=utf-8" .setRequestHeader "Content-Length", Len(strRequest) .send strRequest objXMLResponse.loadXML .responseText Request = True End With End Function
Listing 11: Die Funktion Request führt den eigentliche Request aus.
- strRequest erwartet den Request als String und
- objXMLResponse ist ein Rückgabeparameter, der ein Objekt des Typs MSXML2.DOMDocument zurückliefert.
Die Prozedur erzeugt ein neues Objekt des Typs MSXML2.DOMDocument und liest dann den Wert der Konstanten cURLBase in die Variable strURL ein.
Aktuell können Sie die Konstante wie folgt mit der Zieladresse versehen:
Public Const cURLBase As String = "https://service.ddbac.de/demo/ServiceNG.asmx"
Diese kann sich gegebenenfalls einmal ändern €“ sollte diese also nicht mehr funktionieren, wenden Sie sich per E-Mail an info@access-im-unternehmen.de.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo