Invoiceninja - automatisch Zahlungen aus Onlinebanking verbuchen

Anlaß

Mit Beginn des Jahres 2017 wurde ein Wechsel des Rechnungssystems von Invoiceplane auf Invoiceninja vollzogen. Der Grund war der, daß im Jahre 2016 die Weiterentwicklung von Invoiceplane auf der Kippe stand und ich auf ein modernes Rechnungstool umsteigen wollte. Dieses sollte im Gegensatz zu Invoiceplane eine einfachere Anpassung des Layouts von Rechnungen ermöglichen.
Meine Invoiceplane Installation wurde von mir an diversen Stellen angepaßt, sei es um Fehler zu beheben oder um die Rechnungen dem Erscheinungsbild, welches ich mir vorstellte anzupassen. Bei jeder neuen Version war es jedoch erforderlich jede Änderung erneut vorzunehmen. Diesen Aufwand wollte ich nicht mehr betreiben.
 

Vorgehen

Der Umstieg auf Invoiceninja verlief reibungslos. Im Gegensatz zu anderslautenden Informationen ist es möglich Invoiceninja in einem Unterverzeichnis zu installieren. Ein Auszug aus der Nginx Konfiguration befindet sich hier
 
Da ich den Jahreswechsel gewählt hatte, mußten auch nur die Kunden importiert werden. Ein einfacher SQL Befehl auf die Invoiceplane Datenbank und ein Export als CSV brachten eine Datei hervor, die einfach in Invoiceninja importiert werden konnte:
 

SELECT *, SUBSTRING(client_name, 1, locate(' ', client_name) - 1) AS FirstName,
SUBSTRING(client_name, locate(' ', client_name) + 1, 8000) AS LastName FROM `ip_clients`

Mein ursprünglich für Invoiceplane angedachtes Programm zur automatischen Eintragen von Zahlungen, habe ich daher für Invoiceninja in der Programmiersprache Python realisiert.

Zuerst mußten die Zahlungen in einem möglichst gut verarbeitbaren Format vorliegen. Als Kunde der Commerzbank, nahm ich mir daher die App Kontostand aus dem Google Appstore vor. Da ich keine Erfahrung mit App Programmierung habe, entpackte ich sie mit 7 Zip und fand in der Datei:

assets\www\js\common.js

einen Hinweis wie dies zu bewerkstelligen ist. Dort sind zu Beginn verschiedene Variablen definiert, die wohl von den Entwicklern stammen und auf das Intranet verweisen:

var restServiceURL = "https://app.ccb-stum06.intranet.commerzbank.com/app/rest/";
var loginServiceURL = "https://app.ccb-stum06.intranet.commerzbank.com/app/lp/login";
var transactionOverviewServiceURL = restServiceURL + "account/transactionOverview";

Die externe URL erhielt ich indem ich die Banking App ebenfalls mit 7 Zip entpackte. In der Datei:

assets\configurations\environments.json

die baseUrl https://app.commerzbank.de

Beides sind augenscheinlich webapps, so daß sich der Zugriff automatisieren lassen müßte. Damit waren die URLs für den Login bekannt und diejenige unter der die Umsätze abzugreifen sein sollten. Nach einem Kurzversuch mußte ich erneut in die App eintauchen, um zu sehen in welchem Format die Logindaten erwartet wurden. Fündig wurde ich in der Kontostandsapp in Datei:

assets\www\views\login\login-controller-donotusethisinapp.js

Aus dem Namen schließe ich, daß dies nicht in der App verwendet werden soll aber relevant sind die Informationen für den weiteren Prozeß. Die Logindaten werden als JSON erwartet und per POST an die loginServiceURL https://app.commerzbank.de/app/lp/login übergeben:

$scope.createLoginRequestObject = function() {
"use strict";
var loginParticipant = {
userid : $scope.username,
pin : $scope.password
};
return loginParticipant;
}

Um dies zu testen verwendete ich die Chrome App Postman zur Erstellung des Post Requests und rief im Anschluß die transactionOverviewServiceURL https://app.commerzbank.de/app/rest/account/transactionOverview auf.

Als Server Response gab es dann als Webseite alle Transaktionen des letzten Jahres im JSON Format. Das war der Jackpot, denn dieses Format ist mit gängigen Programmiersprachen relativ einfach einzulesen und zu verarbeiten.

Die Automatisierung

Da das manuelle Eingeben der URLs und der Logindaten kein wirklicher Fortschritt im Prozeß wäre, mußte der Abruf der Umsätze automatisiert werden. Meine Wahl fiel auf den bekannten headless Browser phantomjs.
Mit Hilfe eines sebst erstellten Scriptes, welches hier heruntergeladen werden kann, werden die 2 o.a. URLs aufgerufen und das Ergebnis als JSON gerendert.
Der Aufruf auf der Kommandozeile sieht dann folgendermaßen aus:
 
phantomjs phantomjs_trx_script.js > /tmp/trx.json
 
Die Datei trx.json dient dann als Eingabedatei für ein selbstgeschriebenes Python Programm welches grob zusammengefaßt folgende Anweisungen durchläuft:
 
  1. suchen aller Rechnungen im Status 2-5 in der Tabelle invoices von invoiceninja und ermitteln der Rechnungsnummern
  2. durchsuchen aller Buchungen der Eingabedatei nach den Rechnungsnummern
  3. wenn eine Rechnungsnummer gefunden wurde, Erstellung einer Zahlung in der Tabelle payments, Reduzierung der Spalte balances in der Tabelle invoices und setzen des Rechnungsstatus
  4. Update der Spalten balances und paid_to_date in der Tabelle clients
 

Ergänzung 

 
Um die Umsatzabfrage des Commerzbank Kontos zu vereinfachen und dabei auch mehrere Konten zu berücksichtigen, wurde der Netzwerkverkehr der Banking App analysiert. Dieser wird zwar über https verschlüsselt aber die App scheint nicht zu prüfen ob das Zertifikat wirklich von der Commerzbank stammt oder nicht. So verwendete ich den SSL Proxy Charles, um den Netzwerkverkehr des Smartphones umzulenken und so die https Requests analysieren zu können. Die Demoversion genügte hierzu.
 
Dabei zeigte sich, daß die App die URL: https://app.commerzbank.de/app/rest/transactionoverview aufruft und dabei folgende Suchkriterien im JSON Format mitgiebt wenn in der Banking App das entsprechende Konto aufgerufen wird:
 

{
"identifier": {
"currency": "EUR",
"identifier": "12345689",
"productBranch": "100",
"productType": "CurrentAccount"
},
"searchCriteriaDto": {
"amountType": "ALL",
"page": 0,
"transactionsPerPage": 50
}
}

Der identifier gibt hier die Kontonummer mit den ersten 3 Stellen der FILHB an. Über den Parameter transactionsPerPage kann auf einfache Weise die Anzahl der Umsätze, die auf einmal abgeholt werden angepaßt werden.
Das Skript: phantomjs_trx_script.js ändert sich dazu nur unwesentlich. Das Ergebnis sind auch hier die Umsätze im JSON Format.
 
Auf Nachfrage und gegen eine Gebühr kann ich das Programm gern zur Verfügung stellen, damit auch Sie bei Interesse Ihren Arbeitsablauf vereinfachen können.

Kontaktformular

Der Übermittlung und Speicherung meiner Daten zur Kontaktaufnahme und Auftragserteilung stimme ich zu.
Form by ChronoForms - ChronoEngine.com
Cookies erleichtern die Bereitstellung unserer Dienste. Mit der Nutzung unserer Dienste erklären Sie sich damit einverstanden, dass wir Cookies verwenden.
Weitere Informationen Ok