Zum Hauptinhalt springen

ArtinTech Solution

MikroTik billing automation in Linkhive: routers page with online status, customer count, RouterOS version and CPU load

Ein Internetanbieter hat zwei Wahrheitsquellen: das Abrechnungssystem und den Router. Wer die MikroTik-Abrechnung automatisieren will, muss beide im Einklang halten, und die teuren Fehler liegen in der Lücke dazwischen: ein Kunde, der bezahlt hat und trotzdem gesperrt ist, ein Kunde, der nicht mehr zahlt und online bleibt, oder eine Verlängerung, die doppelt greift, weil ein Zahlungsanbieter seinen Webhook wiederholt. Beim Bau von Linkhive, unserer selbst gehosteten Laravel-Abrechnungsplattform für Breitband- und WLAN-Anbieter, haben diese drei Fehler das Design stärker geprägt als jede Funktion.

MikroTik-Abrechnung automatisieren beginnt mit wiederholbaren Schritten

Der Abrechnungszyklus von Linkhive ist eine geordnete Liste von Schritten: Verlängerungsrechnungen erstellen, automatisch aus dem Prepaid-Guthaben verlängern, bezahlte Rechnungen ausführen, Erinnerungen senden, auslaufen lassen und sperren, dann Voucher verarbeiten. Der Scheduler startet ihn alle 15 Minuten, und auf Hosting ohne Cron läuft derselbe Zyklus über Web-Zugriffe höchstens alle 15 Minuten.

Häufige Läufe sind nur sicher, wenn ein zweiter Lauf nichts ändert. Darum prüft jeder Schritt, ob seine Arbeit schon erledigt ist. Vor einer Verlängerungsrechnung sucht er nach einer Rechnung für denselben Kunden, dasselbe Paket und denselben Zeitraum. Vor einer Erinnerung prüft er im Nachrichtenprotokoll, ob heute schon eine verschickt wurde. Jeder Schritt läuft außerdem in einem eigenen try/catch: Ein Fehler wird protokolliert, die übrigen Schritte laufen weiter, und ein defekter Datensatz stoppt nicht alle Sperren im Netz.

Die Zeiten sind einstellbar. Standardmäßig entsteht die Rechnung drei Tage vor Ablauf, Erinnerungen gehen drei Tage und einen Tag vorher raus, und der Dienst endet nach zwei Kulanztagen.

Linkhive Kundenkonto mit Paket, Ablaufdatum, Prepaid-Guthaben mit automatischer Verlängerung und Rechnungsverlauf
Ein Demo-Kunde zwei Tage vor Ablauf, mit automatischer Verlängerung und bereits erstellter nächster Rechnung.

Ein atomares Update verhindert die doppelte Verlängerung

Eine Zahlung kann das System auf drei Wegen gleichzeitig erreichen: über den Browser des Kunden, der vom Zahlungsanbieter zurückkehrt, über dessen Webhook und über den Abrechnungszyklus, der eine bezahlte Rechnung aufgreift. Prüft jeder Weg erst „wurde das schon verlängert?“ und verlängert dann, können zwei die Prüfung gleichzeitig bestehen, und der Kunde bekommt zwei Monate zum Preis von einem.

Eine Prüfung mit anschließendem Schreiben lässt diese Lücke, also haben wir beides zu einer Anweisung gemacht:

$claimed = Invoice::whereKey($invoice->id)
    ->whereNull('fulfilled_at')
    ->update(['fulfilled_at' => now()]);

if ($claimed === 0) {
    return false; // another request got here first
}

Die Datenbank lässt nur ein UPDATE auf diese Zeile treffen, egal welche Anfrage zuerst kommt. Die anderen sehen null betroffene Zeilen und stoppen. Zahlungen werden ähnlich behandelt: approvePayment() sperrt die Zeile mit lockForUpdate() in einer Transaktion, sodass zwei Aufrufe das Geld nur einmal verbuchen.

Den Zahlungsanbieter fragen, nie den Browser

Alles, was über eine Rückkehr-URL kommt, lässt sich fälschen, deshalb gilt es nur als Hinweis. Bei Stripe speichert Linkhive beim Start die ID der Checkout-Session und ruft diese Session bei der Rückkehr über die Stripe-API ab. Das Geld wird nur verbucht, wenn die Session passt und Stripe sie als bezahlt meldet, mit richtiger Referenz, exaktem Betrag und richtiger Währung. PayPal folgt demselben Muster, und die Treiber für SSLCommerz, bKash und Nagad bestätigen Betrag und Referenz über ihre eigenen APIs.

Linkhive Rechnungsliste mit Rechnungsnummern, Kunden, Fälligkeitsdaten, Salden und Status unbezahlt
Rechnungen bleiben unbezahlt, bis ein Mitarbeiter oder die API des Zahlungsanbieters etwas anderes bestätigt.

Ein Offline-Router darf keine Zahlung zurückrollen

Das verlockende Design spricht innerhalb der Zahlungstransaktion mit dem Router. Dann macht ein Router-Neustart aus einer erfolgreichen Kartenzahlung eine Fehlerseite. In Linkhive läuft jede Router-Änderung durch eine Klasse, Provisioner, und die wirft nie eine Ausnahme. Das Geld wird zuerst verbucht. Ist der Router nicht erreichbar, landet der Fehler im Provisioning-Log, und das Abonnement wird zur Wiederholung markiert.

Ein stündlicher Job wiederholt markierte Abonnements bis zu drei Tage lang. Er liest den aktuellen Zustand, statt den alten Befehl erneut abzuspielen: Ein aktives Abonnement wird aktiviert, jedes andere gesperrt. Hat ein Kunde gezahlt, während der Router ausgefallen war, verbindet die Wiederholung ihn neu und wendet nicht die veraltete Sperre an.

Für die automatisierte MikroTik-Abrechnung arbeitet der Treiber über die RouterOS-API, auf Port 8728 oder per TLS auf 8729, mit einem selbst geschriebenen Client. Er aktualisiert /ppp/secret für PPPoE oder /ip/hotspot/user für Hotspot-Benutzer und trennt dann die aktive Sitzung, damit der Kunde sich mit dem richtigen Profil neu verbindet. FreeRADIUS sitzt hinter derselben Treiber-Schnittstelle, dem Abrechnungscode ist es also egal, was ein Anbieter einsetzt.

MikroTik-Abrechnung automatisieren mit Linkhive: Router-Seite mit Online-Status, Kundenzahl, RouterOS-Version und CPU-Last
Der Router-Zustand wird alle fünf Minuten geprüft. Die Router in der Demo sind simuliert.

Mit Tests beweisen, die die Regeln angreifen

Solche Regeln versagen lautlos, deshalb braucht eine automatisierte MikroTik-Abrechnung Tests, die sie brechen wollen. Linkhive enthält 147 automatisierte Tests, die auf SQLite und MySQL 8.4 bestehen. Sie lassen den Abrechnungszyklus wiederholt laufen, um die Idempotenz zu prüfen, senden gefälschte Rückmeldungen und testen abweichende Beträge und Währungen. Die statische Analyse mit Larastan auf Stufe 5 meldet keine Fehler.

Linkhive Admin-Dashboard im dunklen Design mit aktiven Kunden, Einnahmen, wiederkehrendem Umsatz und offenen Beträgen
Die Sicht des Betreibers auf das Demo-Netz im dunklen Design.

Die wichtigsten Punkte

  • Schreiben Sie Abrechnungsschritte so, dass ein zweiter Lauf nichts ändert, und lassen Sie sie oft laufen.
  • Beanspruchen Sie Arbeit mit einem einzigen atomaren UPDATE, nicht mit Lesen und anschließendem Schreiben.
  • Bestätigen Sie jede Zahlung über die API des Anbieters, auch Betrag und Währung.
  • Halten Sie Router-Aufrufe aus Zahlungstransaktionen heraus und protokollieren Sie Fehler für Wiederholungen.
  • Wiederholen Sie vom aktuellen Zustand aus, nie durch das Abspielen eines alten Befehls.

Sehen Sie sich alles in der Linkhive Live-Demo an, lesen Sie die Funktionsübersicht auf Charming Theme oder holen Sie sich Linkhive auf Vibe96.

Betreiben Sie ein Breitband- oder WLAN-Netz und wachsen aus Ihren Tabellen heraus? Sprechen wir darüber. ArtinTech Solution baut solche Abrechnungs- und Integrationslösungen im Rahmen unserer Laravel-Entwicklung.

Share this article