Bem-vindo ao Manual do plug-in Invoice Radar para desenvolvedores!
Este guia irá ajudá-lo a criar plug-ins personalizados para obter faturas e recibos de várias plataformas.
Invoice Radar é uma ferramenta de automação de documentos que ajuda você a buscar, baixar e organizar faturas e recibos de diversas plataformas.
Saiba mais sobre o Radar de Faturas
Introdução
Começando
Estrutura do plug-in
Escrevendo seu primeiro plugin
Padrões úteis
Referência de etapas
Conhecimento básico de JSON, HTML, CSS e JavaScript.
Um editor de texto ou IDE (por exemplo, VSCode, Sublime Text).
Radar de fatura instalado no macOS ou Windows.
Baixe e instale o radar de fatura :
Solicitar acesso ao radar de fatura
Baixe o plugin em branco :
Baixe o plugin em branco para sua máquina local.
Renomeie o arquivo para your-plugin-name.json
.
Coloque-o em uma pasta de sua preferência.
Adicione o plug-in ao radar de fatura :
Abra o radar da fatura.
Navegue até as configurações e escolha a guia Available Plugins
.
Escolha Choose Plugin Directory
e selecione a pasta onde você salvou o plug-in.
Seu plugin agora deve aparecer na lista de plugins disponíveis.
Plugins para Invoice Radar são escritos em JSON e seguem uma estrutura específica. Cada plugin consiste nas seguintes seções:
Descrição do plug-in :
Metadados : informações básicas sobre o plugin, como nome, descrição e URL da página inicial.
configSchema : Propriedades de configuração que o plugin pode exigir.
Etapas de raspagem :
checkAuth : Etapas para verificar se o usuário já está autenticado.
startAuth : etapas para iniciar o processo de autenticação.
getDocuments : etapas para buscar e baixar documentos.
{ "$schema": "https://raw.githubusercontent.com/invoiceradar/plugins/main/schema.json", "id": "exemplo", "nome": "Plataforma de exemplo", "descrição": " Breve descrição do serviço.", "homepage": "https://example.com", "checkAuth": [ { "action": "navegar", "url": "https://example.com/dashboard" }, { "action": "checkElementExists", "selector": "#logout-button" } ], "startAuth": [ { "action": "navegar", "url": "https://example.com/login" }, { "action": "waitForElement", "selector": "#account-summary", "timeout": 120000 } ], "getDocumentos": [ { "action": "navegar", "url": "https://example.com/billing" }, { "action": "extractAll", "selector": ".invoice-row", "variable": "invoice", "fields": { "id": { "selector": ".invoice-id" }, "data": { "seletor": ".data da fatura" }, "total": { "seletor": ".fatura-total" }, "url": { "seletor": ".invoice-download", "atributo": "href" } }, "forEach": [ { "action": "downloadPdf", "url": "{{invoice.url}}", "document": "{{invoice}}" } ] } ] }
O esquema completo pode ser encontrado aqui.
Vamos criar um plugin simples para buscar faturas de um serviço hipotético.
Definir metadados :
Essas informações são utilizadas para identificar e exibir o plugin no Invoice Radar. O URL da página inicial é usado para obter o favicon do serviço.
Observe que o id
deve ser único e em letras minúsculas.
{ "id": "example-service", "name": "Example Service", "description": "Breve descrição do serviço.", "homepage": "https://example.com"}
Saiba mais sobre campos de metadados.
Definir esquema de configuração (opcional):
O esquema de configuração define quais campos são necessários para o funcionamento do plugin. Neste exemplo, precisamos de um teamID
e password
para autenticação.
Esses campos serão exibidos ao usuário ao adicionar o plugin no Invoice Radar.
"configSchema": { "teamID": { "type": "string", "title": "ID da equipe", "description": "O ID da sua equipe ou conta para buscar faturas.", "required": true } }
Saiba mais sobre os campos do esquema de configuração.
Verifique a autenticação :
checkAuth
contém etapas para verificar se o usuário está autenticado. Isso pode ser feito verificando a URL ou a existência do elemento. A última etapa do checkAuth
precisa ser uma etapa de verificação.
Estas etapas são executadas quando uma execução é iniciada. Caso o usuário já esteja autenticado, o plugin irá pular o processo de autenticação e ir diretamente para a busca de documentos.
"checkAuth": [ { "action": "navegar", "url": "https://example.com/dashboard" }, { "action": "checkElementExists", "selector": "#logout-button" } ]
Iniciar autenticação :
startAuth
contém etapas para iniciar o processo de autenticação. Isso pode envolver navegar até a página de login e aguardar um indicador de login bem-sucedido.
O navegador ficará visível durante o processo de autenticação, permitindo ao usuário interagir com o formulário de login.
"startAuth": [ { "action": "navegar", "url": "https://example.com/login" }, { "action": "waitForElement", "selector": "#account-summary", "timeout": 120000 } ]
Raspar documentos :
getDocuments
contém etapas para buscar e baixar documentos. Isso pode envolver navegar até a página de faturamento, extrair detalhes da fatura e baixar os PDFs.
"getDocumentos": [ { "action": "navegar", "url": "https://example.com/billing" }, { "action": "extractAll", "selector": ".invoice-row", "variable": "invoice", "fields": { "id": { "selector": ".invoice-id" }, "data": { "seletor": ".data da fatura" }, "total": { "seletor": ".fatura-total" }, "url": { "seletor": ".invoice-download", "atributo": "href" } }, "forEach": [ { "action": "downloadPdf", "url": "{{invoice.url}}", "document": { "type": "invoice", "id": "{{invoice.id}}", "data": "{{invoice.date}}", "total": "{{invoice.total}}" } } ] } ]
Você terminou! :
Salve o arquivo e adicione-o ao Invoice Radar. Agora você pode executar o plugin para buscar faturas do serviço.
checkAuth
)Muitos serviços redirecionam automaticamente para a página de login se o usuário não estiver autenticado. Podemos usar esse comportamento para verificar se o usuário está autenticado.
{ "action": "navigate", "url": "https://example.com/login"}, { "action": "checkURL", "url": "https://example.com/account", }
Dependendo do serviço, eles podem redirecioná-lo do painel para a página de login se você não estiver autenticado. Nesse caso, você pode usar a etapa checkURL
para verificar se o URL ainda corresponde após visitar o painel.
{ "action": "navigate", "url": "https://example.com/dashboard"}, { "action": "checkURL", "url": "https://example.com/dashboard", }
Observe que você pode usar padrões glob para corresponder a URLs dinâmicos: https://example.com/dashboard/**
.
Você pode usar um seletor exclusivo para o estado autenticado para verificar se o usuário está autenticado, por exemplo, um botão de logout ou link de perfil.
{ "action": "navigate", "url": "https://example.com/home"}, { "action": "waitForElement", "selector": "#logout-button"}
Em alguns casos, o site não carregou totalmente quando a etapa checkElementExists
é executada. Para evitar isso, você pode usar o atributo waitForNetworkIdle
para aguardar o carregamento completo da página.
{ "action": "navigate", "url": "https://example.com/home", "waitForNetworkIdle": true}, { "action": "checkElementExists", "selector": "#logout-button"}
startAuth
)A maioria dos processos de autenticação começa navegando até a página de login e aguardando que um elemento específico apareça após um login bem-sucedido.
Vale lembrar que o navegador ficará visível durante o processo de autenticação, permitindo ao usuário interagir com o formulário de login. O próprio fluxo de autenticação pode ser automatizado, mas não é obrigatório.
{ "action": "navigate", "url": "https://example.com/login"}, { "action": "waitForElement", "selector": "#logout-button", "timeout": 120000}
Para dar ao usuário tempo suficiente para fazer login, é recomendável fornecer um tempo limite longo para a etapa de espera, com um padrão de 120 segundos.
Esta seção fornece uma visão geral das etapas disponíveis que podem ser usadas para criar plug-ins para o Invoice Radar. Cada etapa representa uma ação específica que pode ser executada durante o processo de automação.
Etapas de navegação
Navegar ( navigate
)
Aguarde URL ( waitForURL
)
Aguarde o elemento ( waitForElement
)
Aguarde a navegação ( waitForNavigation
)
Aguarde a rede ociosa ( waitForNetworkIdle
)
Etapas de interação
Clique em Elemento ( click
)
Digite Texto ( type
)
Selecione o menu suspenso ( dropdownSelect
)
Execute JavaScript ( runJs
)
Etapas de verificação
Verifique se o elemento existe ( checkElementExists
)
Verifique URL ( checkURL
)
Execute JavaScript ( runJs
)
Etapas de extração de dados
Extrair ( extract
)
Extrair tudo ( extractAll
)
Etapas de recuperação de documentos
Baixar PDF ( downloadPdf
)
Aguarde o download do PDF ( waitForPdfDownload
)
Imprimir página como PDF ( printPdf
)
Baixar Base64 PDF ( downloadBase64Pdf
)
Etapas de lógica condicional
Se ( if
)
Etapas diversas
Dormir ( sleep
)
Trechos
Obter fatura do URL Stripe ( getInvoiceFromStripeUrl
)
Obtenha faturas do Portal do Cliente Stripe ( getInvoicesFromStripeBillingPortal
)
navigate
)Navega até o URL fornecido e aguarda o carregamento da página. Por padrão, ele aguarda apenas o carregamento inicial da página, e não quaisquer solicitações AJAX subsequentes.
{ "action": "navegar", "url": "https://example.com"}
Você pode definir waitForNetworkIdle
como true
para garantir que a página esteja totalmente carregada antes de continuar.
{ "action": "navigate", "url": "https://example.com/dashboard", "waitForNetworkIdle": true}
Bom saber :
URLs relativos são suportados e serão resolvidos com base na página atual.
A ação de navegação aguardará apenas o carregamento inicial da página, e não por quaisquer solicitações AJAX subsequentes.
waitForURL
)Aguarda que o URL atual corresponda ao URL fornecido, opcionalmente com um tempo limite. Suporta curingas.
{ "action": "waitForURL", "url": "https://example.com/profile/**", "timeout": 3000}
waitForElement
)Aguarda que determinado seletor apareça na página, opcionalmente com tempo limite.
{ "action": "waitForElement", "selector": "#example", "timeout": 3000}
waitForNavigation
)Aguarda que a navegação da página aconteça. Esta etapa não esperará que a página seja totalmente carregada. Use a etapa waitForNetworkIdle para essa finalidade. O tempo limite é opcional e o padrão é 10 segundos
{ "action": "waitForNavigation", "timeout": 10000}
waitForNetworkIdle
)Espera que a rede fique ociosa. Isso é útil se você quiser garantir que a página tenha concluído o carregamento de todos os recursos. As etapas serão concluídas quando não houver mais solicitações de rede por 500 ms. O tempo limite é opcional e o padrão é 15 segundos.
A etapa navigate
possui uma opção waitForNetworkIdle
que pode ser definida como true
para obter o mesmo comportamento.
{ "ação": "waitForNetworkIdle", "tempo limite": 10000}
click
)Clica no elemento especificado pelo seletor fornecido na página.
{ "action": "clique", "seletor": "#button"}
type
)Digita o texto fornecido no elemento especificado pelo seletor fornecido na página.
{ "action": "type", "selector": "#input", "value": "Olá mundo"}
dropdownSelect
) Seleciona o valor fornecido no menu suspenso especificado pelo seletor fornecido na página. A seleção acontece com base no atributo value
da opção.
{ "action": "dropdownSelect", "selector": "#dropdown", "value": "Opção 1"}
runJs
)Executa o JavaScript fornecido no contexto da página. Se uma promessa for devolvida, ela será aguardada.
Se quiser usar o resultado de um script nas etapas subsequentes, use a etapa de extração.
{ "action": "runJs", "script": "document.querySelector('#example').click();"}
Essas etapas são usadas dentro checkAuth
para verificar se o usuário está autenticado.
checkElementExists
)Verifica se o seletor fornecido existe na página. Normalmente usado para verificações de autenticação.
{ "action": "checkElementExists", "selector": "#example"}
checkURL
) Verifica se o URL atual corresponde ao URL fornecido. Suporta padrões curingas como https://example.com/dashboard/**
.
{ "action": "checkURL", "url": "https://example.com"}
runJs
) A etapa runJs
também pode ser usada como etapa de verificação. Ao executar um script que retorna um valor verdadeiro ou falso, você pode verificar se o usuário está autenticado.
{ "action": "runJs", "script": "document.cookie.includes('authToken');"}
Essas etapas são usadas para carregar dados da página, como uma lista de itens ou um único valor, e usá-los nas etapas subsequentes.
extract
)Extrai um único dado da página e o armazena em uma variável.
Usando campos CSS:
{ "action": "extract", "variable": "account", "fields": { "id": "#team-id", "name": "#team-name", "url": { " seletor": "#team-link", "atributo": "href" } } }
Neste exemplo, account
é usado como nome de variável e os campos id
, name
e url
são extraídos usando seletores CSS. Eles podem ser usados em etapas subsequentes usando os espaços reservados {{account.id}}
, {{account.name}}
e {{account.url}}
.
Usando JavaScript:
{ "action": "extrair", "variável": "token", "script": "localStorage.getItem('authToken')"}
Este exemplo cria uma variável token
que é extraída usando JavaScript. O valor pode ser acessado usando o espaço reservado {{token}}
. Também é possível retornar um objeto.
extractAll
)Extrai uma lista de dados da página e executa as etapas fornecidas para cada item. Isso é comumente usado para iterar uma lista de faturas e baixá-las.
Para cada elemento correspondente ao selector
, os campos são extraídos e armazenados na variable
disponível nas etapas forEach
.
Bom saber :
Cada seletor dentro do objeto fields
tem como escopo automático o elemento correspondente.
O campo variable
é opcional. Se não for fornecido, os dados extraídos serão armazenados na variável padrão item
.
O índice atual pode ser acessado usando o espaço reservado {{index}}
. Começa em 0 e aumenta para cada item.
Com campos CSS:
{ "action": "extractAll", "selector": ".invoice-list .invoice-item", "variable": "invoice", "fields": { "id": "td.invoice-id", " data": "td.invoice-date", "total": "td.invoice-total", "url": { "selector": "a.invoice-link", "attribute": "href" } }, "forEach": [ { "action": "navigate", "url": "{{invoice.url}}" }, { "action": "downloadPdf", "fatura": "{{fatura}}" } ] }
Com JavaScript:
Ao usar JavaScript, o resultado deve ser um array de objetos ou valores. Se o resultado for promissor, será aguardado.
{ "action": "extractAll", "script": "Array.from(document.querySelectorAll('#year-selector option')).map(option => option.value);", "variável": "ano ", "para cada": [ { "action": "dropdownSelect", "selector": "#year-selector", "value": "{{year}}" } ] }
Paginação
Suporte experimental, ainda não documentado.
Essas etapas são usadas para baixar documentos e processá-los no Invoice Radar. Todas as etapas exigem que o objeto document
seja passado como argumento, que contém os metadados do documento.
O argumento document
possui os seguintes campos:
Obrigatório
id
: o ID exclusivo do documento
Por exemplo, INV-123
ou 123456
date
: a data da fatura como string
Por exemplo 2022-01-01
ou 01/01/2022
ou January 1, 2022
Recomendado
total
: o valor total da fatura, incluindo a moeda.
Por exemplo, $100.00
ou €100.00
ou 100 EUR
ou 100,00€
O analisador integrado tentará extrair o valor e a moeda da string.
Opcional
type
: o tipo do documento (opcional. O padrão é auto
)
Pode ser definido como auto
, invoice
, receipt
, refund
ou other
.
metadata
: metadados adicionais para o documento (opcional)
Por exemplo, { "orderNumber": "12345" }
Você pode passar cada campo separadamente ou o objeto inteiro se ele contiver todos os campos obrigatórios.
Por exemplo, usando campos separados:
"documento": { "id": "{{item.invoiceId}}", "data": "{{item.data}}", "total": "{{item.amount}} {{item.currency }}", "type": "fatura"}
Por exemplo, se o objeto contiver todos os campos obrigatórios, você poderá passá-lo diretamente:
"documento": "{{item}}"
downloadPdf
)Baixa um PDF do URL fornecido.
{ "action": "downloadPdf", "url": "https://example.com/invoice.pdf", "documento": { "id": "{{item.invoiceId}}", "data": "{{item.data}}", "total": "{{item.total}}" } }
waitForPdfDownload
)Aguarda um download do PDF. O tempo limite é padrão para 15 segundos.
{ "action": "waitForPdfDownload", "timeout": 10000, "document": { "id": "{{item.invoiceId}}", "date": "{{item.date}}", "total ": "{{item.total}}" } }
printPdf
)Imprime a página atual em um arquivo PDF.
{ "action": "printPdf", "documento": { "id": "{{item.invoiceId}}", "data": "{{item.date}}", "total": "{{item .total}}" } }
downloadBase64Pdf
)Baixa um PDF de uma string codificada em base64.
{ "action": "downloadBase64Pdf", "base64": "{{item.base64String}}", "documento": { "id": "{{item.invoiceId}}", "data": "{{item .date}}", "total": "{{item.total}}" } }
if
) Executa as etapas fornecidas se a condição for verdadeira. Se a condição for falsa, as etapas else
serão executadas.
{ "action": "if", "script": "'{{invoice.url}}'.includes('pdf')", "então": [ { "ação": "clique", "seletor": "#exemplo" } ], "outro": [ { "action": "navegar", "url": "https://example.com/fallback" } ] }
sleep
)Aguarda o tempo determinado em milissegundos. Geralmente isso não é recomendado. Na maioria dos casos, é melhor usar as etapas waitForElement, waitForURL ou waitForNetworkIdle.
{ "ação": "sono", "duração": 1000}
Snippets são conjuntos pré-construídos de etapas que simplificam tarefas comuns. As etapas de um snippet específico ficam visíveis nas ferramentas do desenvolvedor
Atualmente não é possível criar snippets personalizados. Se você tiver uma tarefa comum que acha que seria útil como snippet, crie um problema no GitHub.
getInvoiceFromStripeUrl
)Extrai uma fatura de um URL de fatura Stripe.
{ "action": "runSnippet", "snippet": "getInvoiceFromStripeUrl", "args": { "url": "https://invoice.stripe.com/i/inv_123" } }
getInvoicesFromStripeBillingPortal
)Extrai faturas disponíveis de um portal de cobrança Stripe.
{ "action": "runSnippet", "snippet": "getInvoicesFromStripeBillingPortal", "args": { "url": "https://stripe-portal.example.com/billing" } }
Às vezes, pode ser necessário executar uma solicitação de busca dentro de uma etapa para buscar dados de uma API. Para fazer isso, você pode usar a ação extractAll
.
{ "action": "extractAll", "variable": "invoice", "script": "fetch('https://example.com/api/invoices').then(res => res.json()) " "para cada": [ { "action": "downloadPdf", "url": "{{invoice.url}}", "document": { "id": "{{invoice.id}}", "data": "{{fatura .date}}", "total": "{{fatura.total}}" } } ] }
Isso executará a solicitação de busca e retornará o resultado como um objeto JavaScript.
Em alguns cenários, pode ser necessário executar uma etapa dentro de um elemento . Para fazer isso, você pode usar o atributo
iframe
na etapa.
{ "action": "click", "selector": "#button-inside-iframe", "iframe": true},
Ao definir iframe
como true
, o Invoice Radar encontrará o primeiro elemento na página e executará a etapa dentro dele.
Você também pode usar uma string contida no atributo src
do iframe para direcionar um iframe específico.
{ "action": "click", "selector": "#button-inside-iframe", "iframe": "iframe.example.com"},