Willkommen beim Invoice Radar Plugin-Handbuch für Entwickler!
Dieser Leitfaden hilft Ihnen beim Erstellen benutzerdefinierter Plugins zum Abrufen von Rechnungen und Quittungen von verschiedenen Plattformen.
Invoice Radar ist ein Tool zur Dokumentenautomatisierung, mit dem Sie Rechnungen und Quittungen von verschiedenen Plattformen abrufen, herunterladen und organisieren können.
Erfahren Sie mehr über Invoice Radar
Einführung
Erste Schritte
Plugin-Struktur
Schreiben Sie Ihr erstes Plugin
Nützliche Muster
Schritte-Referenz
Grundkenntnisse in JSON, HTML, CSS und JavaScript.
Ein Texteditor oder eine IDE (z. B. VSCode, Sublime Text).
Rechnungsradar auf macOS oder Windows installiert.
Laden Sie Invoice Radar herunter und installieren Sie es :
Fordern Sie Zugriff auf Invoice Radar an
Laden Sie das Blank-Plugin herunter :
Laden Sie das leere Plugin auf Ihren lokalen Computer herunter.
Benennen Sie die Datei in your-plugin-name.json
um.
Legen Sie es in einen Ordner Ihrer Wahl.
Fügen Sie das Plugin zu Invoice Radar hinzu :
Rechnungsradar öffnen.
Navigieren Sie zu den Einstellungen und wählen Sie die Registerkarte Available Plugins
.
Wählen Sie Choose Plugin Directory
und wählen Sie den Ordner aus, in dem Sie das Plugin gespeichert haben.
Ihr Plugin sollte nun in der Liste der verfügbaren Plugins erscheinen.
Plugins für Invoice Radar sind in JSON geschrieben und folgen einer bestimmten Struktur. Jedes Plugin besteht aus den folgenden Abschnitten:
Plugin-Beschreibung :
Metadaten : Grundlegende Informationen zum Plugin, wie Name, Beschreibung und Homepage-URL.
configSchema : Konfigurationseigenschaften, die das Plugin möglicherweise benötigt.
Schabeschritte :
checkAuth : Schritte zur Überprüfung, ob der Benutzer bereits authentifiziert ist.
startAuth : Schritte zum Initiieren des Authentifizierungsprozesses.
getDocuments : Schritte zum Abrufen und Herunterladen von Dokumenten.
{ „$schema“: „https://raw.githubusercontent.com/invoiceradar/plugins/main/schema.json“, „id“: „example“, „name“: „Beispielplattform“, „description“: „ Kurze Beschreibung des Dienstes.“, „homepage“: „https://example.com“, „checkAuth“: [ { „action“: „navigate“, „url“: „https://example.com/dashboard“ }, { „action“: „checkElementExists“, „selector“: „#logout-button“ } ], "startAuth": [ { „action“: „navigate“, „url“: „https://example.com/login“ }, { „action“: „waitForElement“, „selector“: „#account-summary“, „timeout“: 120000 } ], „getDocuments“: [ { „action“: „navigate“, „url“: „https://example.com/billing“ }, { „action“: „extractAll“, „selector“: „.invoice-row“, „variable“: „invoice“, „fields“: { „id“: { „selector“: „.invoice-id“ }, „date“: { „selector“: „.invoice-date“ }, „total“: { „selector“: „.invoice-total“ }, „url“: { „selector“: „.invoice-download“, „attribute“: „href“ } }, "forEach": [ { „action“: „downloadPdf“, „url“: „{{invoice.url}}“, „document“: „{{invoice}}“ } ] } ] }
Das vollständige Schema finden Sie hier.
Lassen Sie uns ein einfaches Plugin erstellen, um Rechnungen von einem hypothetischen Dienst abzurufen.
Metadaten definieren :
Diese Informationen werden verwendet, um das Plugin im Invoice Radar zu identifizieren und anzuzeigen. Die Homepage-URL wird verwendet, um das Favicon des Dienstes abzurufen.
Beachten Sie, dass die id
eindeutig und in Kleinbuchstaben sein sollte.
{ „id“: „example-service“, „name“: „Example Service“, „description“: „Kurzbeschreibung des Services.“, „homepage“: „https://example.com“}
Erfahren Sie mehr über Metadatenfelder.
Konfigurationsschema definieren (optional):
Das Konfigurationsschema definiert, welche Felder erforderlich sind, damit das Plugin funktioniert. In diesem Beispiel benötigen wir zur Authentifizierung eine teamID
und password
.
Diese Felder werden dem Benutzer angezeigt, wenn er das Plugin in Invoice Radar hinzufügt.
„configSchema“: { „teamID“: { „type“: „string“, „title“: „Team-ID“, „description“: „Die ID Ihres Teams oder Kontos zum Abrufen von Rechnungen.“, „erforderlich“: true } }
Erfahren Sie mehr über Konfigurationsschemafelder.
Authentifizierung prüfen :
checkAuth
enthält Schritte zur Überprüfung, ob der Benutzer authentifiziert ist. Dies kann durch Überprüfen der URL oder des Vorhandenseins eines Elements erfolgen. Der letzte Schritt innerhalb checkAuth
muss ein Verifizierungsschritt sein.
Diese Schritte werden ausgeführt, wenn ein Lauf gestartet wird. Wenn der Benutzer bereits authentifiziert ist, überspringt das Plugin den Authentifizierungsprozess und geht direkt zum Abrufen von Dokumenten über.
„checkAuth“: [ { „action“: „navigate“, „url“: „https://example.com/dashboard“ }, { „action“: „checkElementExists“, „selector“: „#logout-button“ } ]
Authentifizierung starten :
startAuth
enthält Schritte zum Initiieren des Authentifizierungsprozesses. Dies kann das Navigieren zur Anmeldeseite und das Warten auf eine erfolgreiche Anmeldeanzeige umfassen.
Der Browser ist während des Authentifizierungsprozesses sichtbar und ermöglicht dem Benutzer die Interaktion mit dem Anmeldeformular.
„startAuth“: [ { „action“: „navigate“, „url“: „https://example.com/login“ }, { „action“: „waitForElement“, „selector“: „#account-summary“, „timeout“: 120000 } ]
Scrape-Dokumente :
getDocuments
enthält Schritte zum Abrufen und Herunterladen von Dokumenten. Dies kann das Navigieren zur Abrechnungsseite, das Extrahieren von Rechnungsdetails und das Herunterladen der PDFs umfassen.
„getDocuments“: [ { „action“: „navigate“, „url“: „https://example.com/billing“ }, { „action“: „extractAll“, „selector“: „.invoice-row“, „variable“: „invoice“, „fields“: { „id“: { „selector“: „.invoice-id“ }, „date“: { „selector“: „.invoice-date“ }, „total“: { „selector“: „.invoice-total“ }, „url“: { „selector“: „.invoice-download“, „attribute“: „href“ } }, "forEach": [ { „action“: „downloadPdf“, „url“: „{{invoice.url}}“, „document“: { „type“: „invoice“, „id“: „{{invoice.id}}“, „date“: „{{invoice.date}}“, „total“: „{{invoice.total}}“ } } ] } ]
Du bist fertig! :
Speichern Sie die Datei und fügen Sie sie zu Invoice Radar hinzu. Sie können jetzt das Plugin ausführen, um Rechnungen vom Dienst abzurufen.
checkAuth
)Viele Dienste leiten automatisch zur Anmeldeseite weiter, wenn der Benutzer nicht authentifiziert ist. Wir können dieses Verhalten nutzen, um zu prüfen, ob der Benutzer authentifiziert ist.
{ „action“: „navigate“, „url“: „https://example.com/login“}, { „action“: „checkURL“, „url“: „https://example.com/account“, }
Je nach Dienst werden Sie möglicherweise vom Dashboard zur Anmeldeseite weitergeleitet, wenn Sie nicht authentifiziert sind. In diesem Fall können Sie mit dem Schritt checkURL
prüfen, ob die URL nach dem Besuch des Dashboards noch übereinstimmt.
{ „action“: „navigate“, „url“: „https://example.com/dashboard“}, { „action“: „checkURL“, „url“: „https://example.com/dashboard“, }
Beachten Sie, dass Sie Glob-Muster verwenden können, um dynamische URLs abzugleichen: https://example.com/dashboard/**
.
Sie können einen für den authentifizierten Status eindeutigen Selektor verwenden, um zu überprüfen, ob der Benutzer authentifiziert ist, z. B. eine Abmeldeschaltfläche oder einen Profillink.
{ „action“: „navigate“, „url“: „https://example.com/home“}, { „action“: „waitForElement“, „selector“: „#logout-button“}
In einigen Fällen wurde die Website nicht vollständig geladen, wenn der Schritt checkElementExists
ausgeführt wird. Um dies zu vermeiden, können Sie mit dem Attribut „ waitForNetworkIdle
warten, bis die Seite vollständig geladen ist.
{ „action“: „navigate“, „url“: „https://example.com/home“, „waitForNetworkIdle“: true}, { „action“: „checkElementExists“, „selector“: „#logout-button“}
startAuth
)Die meisten Authentifizierungsprozesse beginnen damit, dass Sie zur Anmeldeseite navigieren und darauf warten, dass nach einer erfolgreichen Anmeldung ein bestimmtes Element angezeigt wird.
Denken Sie daran, dass der Browser während des Authentifizierungsprozesses sichtbar ist, sodass der Benutzer mit dem Anmeldeformular interagieren kann. Der Authentifizierungsablauf selbst kann automatisiert werden, ist jedoch nicht erforderlich.
{ „action“: „navigate“, „url“: „https://example.com/login“}, { „action“: „waitForElement“, „selector“: „#logout-button“, „timeout“: 120000}
Um dem Benutzer genügend Zeit zum Anmelden zu geben, wird empfohlen, für den Warteschritt eine lange Zeitüberschreitung festzulegen, mit einem Standardwert von 120 Sekunden.
Dieser Abschnitt bietet einen Überblick über die verfügbaren Schritte, die zum Erstellen von Plugins für Invoice Radar verwendet werden können. Jeder Schritt stellt eine bestimmte Aktion dar, die während des Automatisierungsprozesses ausgeführt werden kann.
Navigationsschritte
Navigieren ( navigate
)
Auf URL warten ( waitForURL
)
Auf Element warten ( waitForElement
)
Auf Navigation warten ( waitForNavigation
)
Warten auf Netzwerk-Leerlauf ( waitForNetworkIdle
)
Interaktionsschritte
Klicken Sie auf Element ( click
).
Text eingeben ( type
)
Dropdown auswählen ( dropdownSelect
)
Führen Sie JavaScript aus ( runJs
)
Überprüfungsschritte
Überprüfen Sie, ob das Element vorhanden ist ( checkElementExists
)
URL prüfen ( checkURL
)
Führen Sie JavaScript aus ( runJs
)
Schritte zur Datenextraktion
Auszug ( extract
)
Alle extrahieren ( extractAll
)
Schritte zum Abrufen von Dokumenten
PDF herunterladen ( downloadPdf
)
Warten Sie auf den PDF-Download ( waitForPdfDownload
).
Seite als PDF drucken ( printPdf
)
Base64-PDF herunterladen ( downloadBase64Pdf
)
Bedingte Logikschritte
Wenn ( if
)
Verschiedene Schritte
Schlaf ( sleep
)
Ausschnitte
Rechnung von Stripe-URL abrufen ( getInvoiceFromStripeUrl
)
Erhalten Sie Rechnungen vom Stripe-Kundenportal ( getInvoicesFromStripeBillingPortal
)
navigate
)Navigiert zur angegebenen URL und wartet darauf, dass die Seite geladen wird. Standardmäßig wartet es nur auf das erste Laden der Seite, nicht auf nachfolgende AJAX-Anfragen.
{ „action“: „navigate“, „url“: „https://example.com“}
Sie können waitForNetworkIdle
auf true
setzen, um sicherzustellen, dass die Seite vollständig geladen ist, bevor Sie fortfahren.
{ „action“: „navigate“, „url“: „https://example.com/dashboard“, „waitForNetworkIdle“: true}
Gut zu wissen :
Relative URLs werden unterstützt und werden basierend auf der aktuellen Seite aufgelöst.
Die Navigationsaktion wartet nur auf das erste Laden der Seite, nicht auf nachfolgende AJAX-Anfragen.
waitForURL
)Wartet darauf, dass die aktuelle URL mit der angegebenen URL übereinstimmt, optional mit einer Zeitüberschreitung. Unterstützt Platzhalter.
{ „action“: „waitForURL“, „url“: „https://example.com/profile/**“, „timeout“: 3000}
waitForElement
)Wartet darauf, dass der angegebene Selektor auf der Seite angezeigt wird, optional mit einer Zeitüberschreitung.
{ „action“: „waitForElement“, „selector“: „#example“, „timeout“: 3000}
waitForNavigation
)Wartet darauf, dass die Seitennavigation erfolgt. Bei diesem Schritt wird nicht darauf gewartet, dass die Seite vollständig geladen ist. Verwenden Sie zu diesem Zweck den Schritt „waitForNetworkIdle“. Timeout ist optional und beträgt standardmäßig 10 Sekunden
{ „action“: „waitForNavigation“, „timeout“: 10000}
waitForNetworkIdle
)Wartet darauf, dass das Netzwerk inaktiv ist. Dies ist nützlich, wenn Sie sicherstellen möchten, dass die Seite alle Ressourcen vollständig geladen hat. Der Schritt ist abgeschlossen, wenn 500 ms lang keine Netzwerkanforderungen mehr vorliegen. Timeout ist optional und beträgt standardmäßig 15 Sekunden.
Der navigate
verfügt über die Option waitForNetworkIdle
, die auf true
gesetzt werden kann, um dasselbe Verhalten zu erzielen.
{ „action“: „waitForNetworkIdle“, „timeout“: 10000}
click
)Klickt auf das durch den angegebenen Selektor auf der Seite angegebene Element.
{ „action“: „click“, „selector“: „#button“}
type
)Gibt den angegebenen Text in das durch den angegebenen Selektor auf der Seite angegebene Element ein.
{ „action“: „type“, „selector“: „#input“, „value“: „Hello World“}
dropdownSelect
) Wählt den angegebenen Wert aus der Dropdown-Liste aus, die durch den angegebenen Selektor auf der Seite angegeben wird. Die Auswahl erfolgt basierend auf dem value
der Option.
{ „action“: „dropdownSelect“, „selector“: „#dropdown“, „value“: „Option 1“}
runJs
)Führt das angegebene JavaScript im Seitenkontext aus. Wird ein Versprechen zurückgegeben, wird darauf gewartet.
Wenn Sie das Ergebnis eines Skripts in nachfolgenden Schritten verwenden möchten, verwenden Sie stattdessen den Extraktionsschritt.
{ "action": "runJs", "script": "document.querySelector('#example').click();"}
Diese Schritte werden in checkAuth
verwendet, um zu überprüfen, ob der Benutzer authentifiziert ist.
checkElementExists
)Überprüft, ob der angegebene Selektor auf der Seite vorhanden ist. Wird normalerweise für Authentifizierungsprüfungen verwendet.
{ „action“: „checkElementExists“, „selector“: „#example“}
checkURL
) Überprüft, ob die aktuelle URL mit der angegebenen URL übereinstimmt. Unterstützt Platzhaltermuster wie https://example.com/dashboard/**
.
{ „action“: „checkURL“, „url“: „https://example.com“}
runJs
) Der runJs
-Schritt kann auch als Verifizierungsschritt verwendet werden. Durch Ausführen eines Skripts, das einen wahren oder falschen Wert zurückgibt, können Sie überprüfen, ob der Benutzer authentifiziert ist.
{ "action": "runJs", "script": "document.cookie.includes('authToken');"}
Diese Schritte werden verwendet, um Daten von der Seite zu laden, z. B. eine Liste von Elementen oder einen einzelnen Wert, und sie in nachfolgenden Schritten zu verwenden.
extract
)Extrahiert ein einzelnes Datenelement aus der Seite und speichert es in einer Variablen.
Verwendung von CSS-Feldern:
{ "action": "extract", "variable": "account", "fields": { "id": "#team-id", "name": "#team-name", "url": { " selector": "#team-link", "attribute": "href" } } }
In diesem Beispiel wird account
als Variablenname verwendet und die Felder id
, name
und url
werden mithilfe von CSS-Selektoren extrahiert. Sie können in nachfolgenden Schritten mithilfe der Platzhalter {{account.id}}
, {{account.name}}
und {{account.url}}
verwendet werden.
Verwendung von JavaScript:
{ „action“: „extract“, „variable“: „token“, „script“: „localStorage.getItem('authToken')“}
In diesem Beispiel wird eine token
erstellt, die mithilfe von JavaScript extrahiert wird. Auf den Wert kann über den Platzhalter {{token}}
zugegriffen werden. Es ist auch möglich, ein Objekt zurückzugeben.
extractAll
)Extrahiert eine Liste von Daten aus der Seite und führt die angegebenen Schritte für jedes Element aus. Dies wird häufig verwendet, um eine Liste von Rechnungen zu durchlaufen und herunterzuladen.
Für jedes Element, das mit dem selector
übereinstimmt, werden die Felder extrahiert und in der variable
gespeichert, die in den forEach
-Schritten verfügbar ist.
Gut zu wissen :
Jeder Selektor innerhalb des fields
wird automatisch auf das übereinstimmende Element beschränkt.
Das variable
ist optional. Wenn nicht angegeben, werden die extrahierten Daten in der Standardvariablen item
gespeichert.
Auf den aktuellen Index kann über den Platzhalter {{index}}
zugegriffen werden. Es beginnt bei 0 und erhöht sich für jedes Element.
Mit CSS-Feldern:
{ „action“: „extractAll“, „selector“: „.invoice-list .invoice-item“, „variable“: „invoice“, „fields“: { „id“: „td.invoice-id“, „ date": "td.invoice-date", "total": "td.invoice-total", "url": { "selector": "a.invoice-link", "attribute": "href" } }, "forEach": [ { „action“: „navigate“, „url“: „{{invoice.url}}“ }, { „action“: „downloadPdf“, „invoice“: „{{invoice}}“ } ] }
Mit JavaScript:
Bei Verwendung von JavaScript sollte das Ergebnis ein Array von Objekten oder Werten sein. Wenn das Ergebnis ein Versprechen ist, wird es erwartet.
{ "action": "extractAll", "script": "Array.from(document.querySelectorAll('#year-selector option')).map(option => option.value);", "variable": "year ", "forEach": [ { „action“: „dropdownSelect“, „selector“: „#year-selector“, „value“: „{{year}}“ } ] }
Pagination
Experimentelle Unterstützung, noch nicht dokumentiert.
Mit diesen Schritten werden Dokumente heruntergeladen und in Invoice Radar verarbeitet. Bei allen Schritten muss das document
als Argument übergeben werden, das die Metadaten des Dokuments enthält.
Das document
hat die folgenden Felder:
Erforderlich
id
: Die eindeutige Dokument-ID
ZB INV-123
oder 123456
date
: Das Rechnungsdatum als Zeichenfolge
Z. B. 2022-01-01
oder 01/01/2022
oder January 1, 2022
Empfohlen
total
: Der Gesamtbetrag der Rechnung einschließlich der Währung.
ZB $100.00
oder €100.00
oder 100 EUR
oder 100,00€
Der integrierte Parser versucht, den Betrag und die Währung aus der Zeichenfolge zu extrahieren.
Optional
type
: Der Typ des Dokuments (Optional. Standardmäßig ist auto
)
Kann auf auto
, invoice
, receipt
, refund
oder other
eingestellt werden.
metadata
: Zusätzliche Metadaten für das Dokument (optional)
Beispiel { "orderNumber": "12345" }
Sie können entweder jedes Feld einzeln oder das gesamte Objekt übergeben, wenn es alle erforderlichen Felder enthält.
Beispiel: Verwendung separater Felder:
„document“: { „id“: „{{item.invoiceId}}“, „date“: „{{item.date}}“, „total“: „{{item.amount}} {{item.currency }}", "type": "invoice"}
Wenn das Objekt beispielsweise alle erforderlichen Felder enthält, können Sie es direkt übergeben:
„document“: „{{item}}“
downloadPdf
)Lädt ein PDF von der angegebenen URL herunter.
{ „action“: „downloadPdf“, „url“: „https://example.com/invoice.pdf“, „document“: { „id“: „{{item.invoiceId}}“, „date“: „{{item.date}}“, „total“: „{{item.total}}“ } }
waitForPdfDownload
).Wartet auf einen PDF-Download. Der Timeout beträgt standardmäßig 15 Sekunden.
{ „action“: „waitForPdfDownload“, „timeout“: 10000, „document“: { „id“: „{{item.invoiceId}}“, „date“: „{{item.date}}“, „total ": "{{item.total}}" } }
printPdf
)Druckt die aktuelle Seite in eine PDF-Datei.
{ „action“: „printPdf“, „document“: { „id“: „{{item.invoiceId}}“, „date“: „{{item.date}}“, „total“: „{{item .gesamt}}" } }
downloadBase64Pdf
)Lädt eine PDF-Datei aus einer Base64-codierten Zeichenfolge herunter.
{ „action“: „downloadBase64Pdf“, „base64“: „{{item.base64String}}“, „document“: { „id“: „{{item.invoiceId}}“, „date“: „{{item .date}}", "total": "{{item.total}}" } }
if
) Führt die angegebenen Schritte aus, wenn die Bedingung wahr ist. Wenn die Bedingung falsch ist, werden die else
-Schritte ausgeführt.
{ "action": "if", "script": "'{{invoice.url}}'.includes('pdf')", "then": [ { „action“: „click“, „selector“: „#example“ } ], "anders": [ { „action“: „navigate“, „url“: „https://example.com/fallback“ } ] }
sleep
)Wartet die angegebene Zeit in Millisekunden. Dies wird grundsätzlich nicht empfohlen. In den meisten Fällen ist es besser, die Schritte „waitForElement“, „waitForURL“ oder „waitForNetworkIdle“ zu verwenden.
{ „action“: „sleep“, „duration“: 1000}
Snippets sind vorgefertigte Schrittsätze, die häufige Aufgaben vereinfachen. Die Schritte für ein bestimmtes Snippet sind in den Entwicklertools sichtbar
Derzeit ist es nicht möglich, benutzerdefinierte Snippets zu erstellen. Wenn Sie eine allgemeine Aufgabe haben, die Ihrer Meinung nach als Snippet nützlich wäre, erstellen Sie bitte ein Issue auf GitHub.
getInvoiceFromStripeUrl
)Extrahiert eine Rechnung aus einer Stripe-Rechnungs-URL.
{ „action“: „runSnippet“, „snippet“: „getInvoiceFromStripeUrl“, „args“: { „url“: „https://invoice.stripe.com/i/inv_123“ } }
getInvoicesFromStripeBillingPortal
)Extrahiert verfügbare Rechnungen aus einem Stripe-Abrechnungsportal.
{ "action": "runSnippet", "snippet": "getInvoicesFromStripeBillingPortal", "args": { "url": "https://stripe-portal.example.com/billing" } }
Manchmal müssen Sie möglicherweise innerhalb eines Schritts eine Abrufanforderung ausführen, um Daten von einer API abzurufen. Dazu können Sie die Aktion extractAll
verwenden.
{ „action“: „extractAll“, „variable“: „invoice“, „script“: „fetch('https://example.com/api/invoices').then(res => res.json()) " "forEach": [ { "action": "downloadPdf", "url": "{{invoice.url}}", "document": { "id": "{{invoice.id}}", "date": "{{invoice .date}}", "total": "{{invoice.total}}" } } ] }
Dadurch wird die Abrufanforderung ausgeführt und das Ergebnis als JavaScript-Objekt zurückgegeben.
aus In einigen Szenarien müssen Sie möglicherweise einen Schritt innerhalb eines Elements ausführen. Dazu können Sie das
iframe
Attribut für den Schritt verwenden.
{ „action“: „click“, „selector“: „#button-inside-iframe“, „iframe“: true},
Wenn Sie iframe
auf true
setzen, findet Invoice Radar das erste Element auf der Seite und führt den darin enthaltenen Schritt aus.
Sie können auch eine Zeichenfolge verwenden, die im src
Attribut des Iframes enthalten ist, um auf einen bestimmten Iframe abzuzielen.
{ „action“: „click“, „selector“: „#button-inside-iframe“, „iframe“: „iframe.example.com“},