歡迎閱讀面向開發人員的發票雷達插件手冊!
本指南將協助您建立自訂外掛程式以從各種平台取得發票和收據。
發票雷達是一種文件自動化工具,可協助您從各種平台取得、下載和組織發票和收據。
了解有關發票雷達的更多信息
介紹
入門
插件結構
寫出你的第一個插件
有用的模式
步驟參考
JSON、HTML、CSS 和 JavaScript 的基本知識。
文字編輯器或 IDE(例如 VSCode、Sublime Text)。
安裝在 macOS 或 Windows 上的發票雷達。
下載並安裝發票雷達:
請求訪問發票雷達
下載空白外掛:
將空白插件下載到本機。
將檔案重新命名為your-plugin-name.json 。
將其放入您選擇的資料夾中。
將插件加入發票雷達:
開啟發票雷達。
導航至設定並選擇Available Plugins 。
選擇Choose Plugin Directory並選擇儲存插件的資料夾。
您的插件現在應該出現在可用插件清單中。
發票雷達插件以 JSON 編寫,並遵循特定的結構。每個插件由以下部分組成:
插件說明:
元資料:有關插件的基本信息,例如名稱、描述和主頁 URL。
configSchema :外掛程式可能需要的設定屬性。
刮痧步驟:
checkAuth :驗證使用者是否已通過身份驗證的步驟。
startAuth :啟動身份驗證過程的步驟。
getDocuments :取得和下載文件的步驟。
{ "$schema": "https://raw.githubusercontent.com/invoiceradar/plugins/main/schema.json", "id": "範例", "名稱": "範例平台", "描述": "服務的簡短描述。
{“action”:“導航”,“url”:“https://example.com/dashboard”
},
{“action”:“checkElementExists”,“選擇器”:“#logout-button”
}
], "開始驗證": [
{“action”:“導航”,“url”:“https://example.com/login”
},
{“操作”:“waitForElement”,“選擇器”:“#account-summary”,“超時”:120000
}
], "取得文件": [
{“action”:“導航”,“url”:“https://example.com/billing”
},
{ "action": "extractAll", "selector": ".invoice-row", "variable": "invoice", "fields": { "id": { "selector": ".invoice-id"
}, "日期": { "選擇器": ".發票日期"
}, "總計": { "選擇器": ".invoice-total"
}, "url": { "selector": ".invoice-download", "attribute": "href"
}
}, "forEach": [
{“action”:“downloadPdf”,“url”:“{{invoice.url}}”,“文件”:“{{invoice}}”
}
]
}
]
}完整的架構可以在這裡找到。
讓我們建立一個簡單的插件來從假設的服務中取得發票。
定義元資料:
此資訊用於在發票雷達中識別和顯示插件。主頁 URL 用於取得服務的圖示。
請注意, id應該是唯一的且小寫的。
{ "id": "example-service", "name": "範例服務", "description": "服務的簡短描述。", "homepage": "https://example.com"}了解有關元資料欄位的更多資訊。
定義配置架構(選用):
配置模式定義了插件運行所需的欄位。在此範例中,我們需要teamID和password進行身份驗證。
在發票雷達中新增插件時,這些欄位將顯示給使用者。
"configSchema": { "teamID": { "type": "string", "title": "團隊 ID", "description": "用於取得發票的團隊或帳戶的 ID。", "required": true
}
}了解有關配置架構欄位的更多資訊。
檢查身份驗證:
checkAuth包含驗證使用者是否經過驗證的步驟。這可以透過檢查 URL 或元素是否存在來完成。 checkAuth中的最後一步需要是驗證步驟。
這些步驟在運行開始時執行。如果使用者已經通過身份驗證,插件將跳過身份驗證過程並直接取得文件。
“檢查驗證”:[
{“action”:“導航”,“url”:“https://example.com/dashboard”
},
{“action”:“checkElementExists”,“選擇器”:“#logout-button”
}
]開始驗證:
startAuth包含啟動身分驗證流程的步驟。這可能涉及導航到登入頁面並等待成功登入指示符。
瀏覽器在身份驗證過程中將可見,允許使用者與登入表單互動。
「開始驗證」:[
{“action”:“導航”,“url”:“https://example.com/login”
},
{“操作”:“waitForElement”,“選擇器”:“#account-summary”,“超時”:120000
}
]抓取文檔:
getDocuments包含取得和下載文件的步驟。這可能涉及導航到計費頁面、提取發票詳細資訊以及下載 PDF。
“取得文件”:[
{“action”:“導航”,“url”:“https://example.com/billing”
},
{ "action": "extractAll", "selector": ".invoice-row", "variable": "invoice", "fields": { "id": { "selector": ".invoice-id"
}, "日期": { "選擇器": ".發票日期"
}, "總計": { "選擇器": ".invoice-total"
}, "url": { "selector": ".invoice-download", "attribute": "href"
}
}, "forEach": [
{ "action": "downloadPdf", "url": "{{invoice.url}}", "document": { "type": "invoice", "id": "{{invoice.id}}", “日期”:“{{發票.日期}}”,“總計”:“{{發票.總計}}”
}
}
]
}
]你完成了! :
儲存文件並將其新增至發票雷達。現在您可以運行該插件以從服務獲取發票。
checkAuth )如果使用者未經身份驗證,許多服務會自動重定向到登入頁面。我們可以使用此行為來檢查使用者是否經過身份驗證。
{ "action": "導航", "url": "https://example.com/login"},
{“action”:“checkURL”,“url”:“https://example.com/account”,
}根據服務的不同,如果您未經身份驗證,他們可能會將您從儀表板重定向到登入頁面。在這種情況下,您可以使用checkURL步驟來檢查存取儀表板後 URL 是否仍符合。
{ "action": "導航", "url": "https://example.com/dashboard"},
{“action”:“checkURL”,“url”:“https://example.com/dashboard”,
}請注意,您可以使用 glob 模式來匹配動態 URL: https://example.com/dashboard/** 。
您可以使用經過身份驗證狀態唯一的選擇器來檢查使用者是否經過身份驗證,例如登出按鈕或個人資料連結。
{ "action": "導航", "url": "https://example.com/home"},
{“action”:“waitForElement”,“selector”:“#logout-button”}在某些情況下,執行checkElementExists步驟時網站尚未完全載入。為了避免這種情況,您可以使用waitForNetworkIdle屬性來等待頁面完全載入。
{“action”:“導航”,“url”:“https://example.com/home”,“waitForNetworkIdle”:true},
{“action”:“checkElementExists”,“selector”:“#logout-button”}startAuth )大多數身份驗證過程都是從導航到登入頁面並等待成功登入後出現特定元素開始的。
請記住,瀏覽器在身份驗證過程中將可見,允許使用者與登入表單互動。身份驗證流程本身可以自動化,但這不是必要的。
{ "action": "導航", "url": "https://example.com/login"},
{“操作”:“waitForElement”,“選擇器”:“#logout-button”,“超時”:120000}為了給用戶足夠的時間登錄,建議為等待步驟提供較長的超時時間,預設為 120 秒。
本節概述了可用於建立發票雷達插件的可用步驟。每個步驟代表可以在自動化過程中執行的特定操作。
導航步驟
導航( navigate )
等待 URL ( waitForURL )
等待元素 ( waitForElement )
等待導航 ( waitForNavigation )
等待網路空閒 ( waitForNetworkIdle )
互動步驟
單擊元素( click )
輸入文字( type )
選擇下拉式選單 ( dropdownSelect )
運行 JavaScript ( runJs )
驗證步驟
檢查元素是否存在 ( checkElementExists )
檢查網址( checkURL )
運行 JavaScript ( runJs )
資料擷取步驟
萃取物( extract )
全部提取 ( extractAll )
文件檢索步驟
下載 PDF ( downloadPdf )
等待 PDF 下載 ( waitForPdfDownload )
將頁面列印為 PDF ( printPdf )
下載 Base64 PDF ( downloadBase64Pdf )
條件邏輯步驟
如果( if )
雜項步驟
睡覺( sleep )
片段
從 Stripe URL 取得發票 ( getInvoiceFromStripeUrl )
從 Stripe 客戶入口網站取得發票 ( getInvoicesFromStripeBillingPortal )
navigate )導航到給定的 URL 並等待頁面加載。預設情況下,它僅等待初始頁面加載,而不等待任何後續 AJAX 請求。
{“action”:“導航”,“url”:“https://example.com”}您可以將waitForNetworkIdle設為true以確保頁面已完全加載,然後再繼續。
{“action”:“導航”,“url”:“https://example.com/dashboard”,“waitForNetworkIdle”:true}很高興知道:
支援相對 URL,並根據目前頁面進行解析。
導航操作將僅等待初始頁面加載,而不等待任何後續 AJAX 請求。
waitForURL )等待當前 URL 與給定 URL 匹配,可以選擇逾時。支援通配符。
{“action”:“waitForURL”,“url”:“https://example.com/profile/**”,“超時”:3000}waitForElement )等待給定的選擇器出現在頁面上,可以選擇逾時。
{“操作”:“waitForElement”,“選擇器”:“#example”,“超時”:3000}waitForNavigation )等待頁面導航發生。此步驟不會等待頁面完全載入。為此,請使用 waitForNetworkIdle 步驟。超時是可選的,預設為 10 秒
{“操作”:“waitForNavigation”,“超時”:10000}waitForNetworkIdle )等待網路空閒。如果您想確保頁面已完成加載所有資源,這非常有用。當 500 毫秒內不再有網路請求時,這些步驟完成。超時是可選的,預設為 15 秒。
navigate步驟有一個waitForNetworkIdle選項,可以將其設為true以獲得相同的行為。
{“操作”:“waitForNetworkIdle”,“超時”:10000}click )點選頁面上給定選擇器指定的元素。
{“操作”:“點擊”,“選擇器”:“#button”}type )將給定文字鍵入到頁面上給定選擇器指定的元素中。
{“操作”:“類型”,“選擇器”:“#input”,“值”:“Hello World”}dropdownSelect )從頁面上給定選擇器指定的下拉清單中選擇給定值。選擇是基於選項的value屬性進行的。
{ "action": "dropdownSelect", "selector": "#dropdown", "value": "選項 1"}runJs )在頁面上下文中執行給定的 JavaScript。如果承諾被返回,則將等待它。
如果您想在後續步驟中使用腳本的結果,請改用擷取步驟。
{ "action": "runJs", "script": "document.querySelector('#example').click();"}這些步驟在checkAuth中使用,以驗證使用者是否已通過身份驗證。
checkElementExists )檢查頁面上是否存在給定的選擇器。通常用於身份驗證檢查。
{“action”:“checkElementExists”,“選擇器”:“#example”}checkURL )檢查目前 URL 是否與給定 URL 相符。支援通配符模式,例如https://example.com/dashboard/** 。
{“action”:“checkURL”,“url”:“https://example.com”}runJs ) runJs步驟也可以用作驗證步驟。透過執行傳回真值或假值的腳本,您可以驗證使用者是否已通過身份驗證。
{ "action": "runJs", "script": "document.cookie.includes('authToken');"}這些步驟用於從頁面載入資料(例如項目清單或單一值),並在後續步驟中使用它。
extract )從頁面中提取單一資料並將其儲存在變數中。
使用 CSS 字段:
{ "action": "extract", "variable": "account", "fields": { "id": "#team-id", "name": "#team-name", "url": { "選擇器”:“#team-link”,“屬性”:“href”
}
}
}在此範例中, account用作變數名稱,並使用 CSS 選擇器來提取欄位id 、 name和url 。它們可以在後續步驟中使用{{account.id}} 、 {{account.name}}和{{account.url}}佔位符來使用。
使用 JavaScript:
{ "action": "extract", "variable": "token", "script": "localStorage.getItem('authToken')"}此範例建立一個使用 JavaScript 提取的token變數。可以使用{{token}}佔位符存取該值。也可以回傳一個物件。
extractAll )從頁面中提取資料列表,並為每個項目運行給定的步驟。這通常用於迭代發票列表並下載它們。
對於與selector相符的每個元素,提取欄位並將其儲存在forEach步驟中可用的variable中。
很高興知道:
fields物件內的每個選擇器都會自動將範圍限定為符合的元素。
variable字段是可選的。如果沒有提供,提取的資料將儲存在預設變數item中。
可以使用{{index}}佔位符存取目前索引。它從 0 開始,並針對每個項目遞增。
使用 CSS 字段:
{ "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”:“導航”,“url”:“{{invoice.url}}”
},
{“action”:“downloadPdf”,“發票”:“{{發票}}”
}
]
}使用 JavaScript:
使用 JavaScript 時,結果應該是物件或值的陣列。如果結果是一個承諾,我們就會等待。
{ "action": "extractAll", "script": "Array.from(document.querySelectorAll('#year-selector option')).map(option => option.value);", "variable": "year ”,“forEach”:[
{“action”:“dropdownSelect”,“selector”:“#year-selector”,“value”:“{{year}}”
}
]
}分頁
實驗支持,尚未記錄。
這些步驟用於下載文件並在發票雷達中處理它們。所有步驟都需要將document物件作為參數傳遞,其中包含文檔的元資料。
document參數具有以下欄位:
必需的
id : 唯一的文檔 ID
例如INV-123或123456
date :發票日期作為字串
例如2022-01-01或01/01/2022或January 1, 2022
受到推崇的
total :包含貨幣的發票總金額。
例如$100.00或€100.00或100 EUR或100,00€
內建解析器將嘗試從字串中提取金額和貨幣。
選修的
type :文檔的類型(可選。預設為auto )
可設定為auto 、 invoice 、 receipt 、 refund或other 。
metadata :文件的附加元資料(可選)
例如{ "orderNumber": "12345" }
您可以單獨傳遞每個字段,也可以傳遞整個物件(如果它包含所有必填字段)。
例如使用單獨的字段:
“文件”:{ “id”:“{{item.invoiceId}}”,“日期”:“{{item.date}}”,“總計”:“{{item.amount}} {{item.currency ” }}", "類型": "發票"}例如,如果物件包含所有必填字段,您可以直接傳遞它:
“文檔”:“{{項目}}”downloadPdf )從給定 URL 下載 PDF。
{“action”:“downloadPdf”,“url”:“https://example.com/invoice.pdf”,“文件”:{“id”:“{{item.invoiceId}}”,“日期”: “{{item.date}}”,“總計”:“{{item.total}}”
}
}waitForPdfDownload )等待 PDF 下載。超時預設為 15 秒。
{“action”:“waitForPdfDownload”,“超時”:10000,“文檔”:{“id”:“{{item.invoiceId}}”,“日期”:“{{item.date}}”,“總計": "{{item.total}}"
}
}printPdf )將目前頁面列印為 PDF 檔案。
{ "action": "printPdf", "document": { "id": "{{item.invoiceId}}", "date": "{{item.date}}", "total": "{{item 。
}
}downloadBase64Pdf )從 Base64 編碼字串下載 PDF。
{“action”:“downloadBase64Pdf”,“base64”:“{{item.base64String}}”,“文件”:{“id”:“{{item.invoiceId}}”,“日期”:“{{item ” .date}}", "總計": "{{item.total}}"
}
}if )如果條件為真,則執行給定步驟。如果條件為假,則執行else步驟。
{ "action": "if", "script": "'{{invoice.url}}'.includes('pdf')", "then": [
{“操作”:“單擊”,“選擇器”:“#example”
}
], 「別的」: [
{“action”:“導航”,“url”:“https://example.com/fallback”
}
]
}sleep )等待給定的時間(以毫秒為單位)。一般不建議這樣做。在大多數情況下,最好使用 waitForElement、waitForURL 或 waitForNetworkIdle 步驟。
{“行動”:“睡眠”,“持續時間”:1000}片段是預先建構的步驟集,可簡化常見任務。特定程式碼片段的步驟在開發人員工具中可見
目前,無法建立自訂片段。如果您認為作為程式碼片段有用的常見任務,請在 GitHub 上建立問題。
getInvoiceFromStripeUrl )從 Stripe 發票 URL 中提取發票。
{“action”:“runSnippet”,“snippet”:“getInvoiceFromStripeUrl”,“args”:{“url”:“https://invoice.stripe.com/i/inv_123”
}
}getInvoicesFromStripeBillingPortal )從 Stripe 計費入口網站提取可用發票。
{“action”:“runSnippet”,“snippet”:“getInvoicesFromStripeBillingPortal”,“args”:{“url”:“https://stripe-portal.example.com/billing”
}
}有時,您可能需要在步驟內執行取得請求以從 API 取得資料。為此,您可以使用extractAll操作。
{ "action": "extractAll", "variable": "invoice", "script": "fetch('https://example.com/api/invoices').then(res => res.json()) ” “對於每個”:[
{“action”:“downloadPdf”,“url”:“{{invoice.url}}”,“文件”:{“id”:“{{invoice.id}}”,“日期”:“{{invoice ” .date}}", "總計": "{{invoice.total}}"
}
}
]
}這將運行獲取請求並將結果作為 JavaScript 物件傳回。
<iframe/>內運行步驟在某些情況下,您可能需要在<iframe/>元素內執行步驟。為此,您可以在步驟上使用iframe屬性。
{ "action": "點選", "選擇器": "#button-inside-iframe", "iframe": true},透過將iframe設為true ,發票雷達將找到頁面上的第一個<iframe/>元素並執行其中的步驟。
您也可以使用 iframe 的src屬性中包含的字串來定位特定的 iframe。
{ "action": "點擊", "selector": "#button-inside-iframe", "iframe": "iframe.example.com"},