¡Bienvenido al manual del complemento Invoice Radar para desarrolladores!
Esta guía lo ayudará a crear complementos personalizados para recuperar facturas y recibos de varias plataformas.
Invoice Radar es una herramienta de automatización de documentos que le ayuda a buscar, descargar y organizar facturas y recibos desde varias plataformas.
Obtenga más información sobre el radar de facturas
Introducción
Empezando
Estructura del complemento
Escribiendo su primer complemento
Patrones útiles
Referencia de pasos
Conocimientos básicos de JSON, HTML, CSS y JavaScript.
Un editor de texto o IDE (por ejemplo, VSCode, Sublime Text).
Invoice Radar instalado en macOS o Windows.
Descargue e instale Radar de facturas :
Solicitar acceso al radar de facturas
Descargue el complemento en blanco :
Descargue el complemento en blanco en su máquina local.
Cambie el nombre del archivo a your-plugin-name.json
.
Colóquelo en una carpeta de su elección.
Agregue el complemento a Invoice Radar :
Abrir radar de facturas.
Navegue hasta la configuración y elija la pestaña Available Plugins
.
Elija Choose Plugin Directory
y seleccione la carpeta donde guardó el complemento.
Su complemento ahora debería aparecer en la lista de complementos disponibles.
Los complementos para Invoice Radar están escritos en JSON y siguen una estructura específica. Cada complemento consta de las siguientes secciones:
Descripción del complemento :
Metadatos : información básica sobre el complemento, como nombre, descripción y URL de la página de inicio.
configSchema : Propiedades de configuración que el complemento puede requerir.
Pasos de raspado :
checkAuth : Pasos para verificar si el usuario ya está autenticado.
startAuth : Pasos para iniciar el proceso de autenticación.
getDocuments : pasos para buscar y descargar documentos.
{ "$schema": "https://raw.githubusercontent.com/invoiceradar/plugins/main/schema.json", "id": "ejemplo", "nombre": "Plataforma de ejemplo", "descripción": " Breve descripción del servicio.", "homepage": "https://example.com", "checkAuth": [ { "acción": "navegar", "url": "https://example.com/dashboard" }, { "action": "checkElementExists", "selector": "#logout-button" } ], "iniciarAuth": [ { "acción": "navegar", "url": "https://example.com/login" }, { "action": "waitForElement", "selector": "#account-summary", "timeout": 120000 } ], "obtenerDocumentos": [ { "acción": "navegar", "url": "https://ejemplo.com/facturación" }, { "acción": "extractAll", "selector": ".fila-factura", "variable": "factura", "campos": { "id": { "selector": ".id-factura" }, "fecha": { "selector": ".fecha-factura" }, "total": { "selector": ".factura-total" }, "url": { "selector": ".descarga-factura", "atributo": "href" } }, "para cada uno": [ { "acción": "descargarPdf", "url": "{{factura.url}}", "documento": "{{factura}}" } ] } ] }
El esquema completo se puede encontrar aquí.
Creemos un complemento simple para recuperar facturas de un servicio hipotético.
Definir metadatos :
Esta información se utiliza para identificar y mostrar el complemento en Invoice Radar. La URL de la página de inicio se utiliza para obtener el favicon del servicio.
Tenga en cuenta que la id
debe ser única y estar en minúsculas.
{ "id": "servicio-ejemplo", "nombre": "Servicio ejemplo", "descripción": "Breve descripción del servicio.", "página de inicio": "https://ejemplo.com"}
Obtenga más información sobre los campos de metadatos.
Definir esquema de configuración (opcional):
El esquema de configuración define qué campos son necesarios para que funcione el complemento. En este ejemplo, necesitamos un teamID
y password
para autenticarnos.
Estos campos se mostrarán al usuario al agregar el complemento en Invoice Radar.
"configSchema": { "teamID": { "type": "string", "title": "Team ID", "description": "El ID de su equipo o cuenta para recuperar facturas.", "required": true } }
Obtenga más información sobre los campos del esquema de configuración.
Verificar autenticación :
checkAuth
contiene pasos para verificar si el usuario está autenticado. Esto se puede hacer comprobando la URL o la existencia del elemento. El último paso dentro de checkAuth
debe ser un paso de verificación.
Estos pasos se ejecutan cuando se inicia una ejecución. Si el usuario ya está autenticado, el complemento omitirá el proceso de autenticación e irá directamente a buscar documentos.
"verificarAuth": [ { "acción": "navegar", "url": "https://example.com/dashboard" }, { "action": "checkElementExists", "selector": "#logout-button" } ]
Iniciar autenticación :
startAuth
contiene pasos para iniciar el proceso de autenticación. Esto puede implicar navegar a la página de inicio de sesión y esperar un indicador de inicio de sesión exitoso.
El navegador será visible durante el proceso de autenticación, permitiendo al usuario interactuar con el formulario de inicio de sesión.
"iniciarAuth": [ { "acción": "navegar", "url": "https://example.com/login" }, { "action": "waitForElement", "selector": "#account-summary", "timeout": 120000 } ]
Documentos raspados :
getDocuments
contiene pasos para buscar y descargar documentos. Esto puede implicar navegar a la página de facturación, extraer los detalles de la factura y descargar los archivos PDF.
"obtenerDocumentos": [ { "acción": "navegar", "url": "https://ejemplo.com/facturación" }, { "acción": "extractAll", "selector": ".fila-factura", "variable": "factura", "campos": { "id": { "selector": ".id-factura" }, "fecha": { "selector": ".fecha-factura" }, "total": { "selector": ".factura-total" }, "url": { "selector": ".descarga-factura", "atributo": "href" } }, "para cada uno": [ { "action": "descargarPdf", "url": "{{factura.url}}", "documento": { "tipo": "factura", "id": "{{factura.id}}", "fecha": "{{factura.fecha}}", "total": "{{factura.total}}" } } ] } ]
¡Ya terminaste! :
Guarde el archivo y agréguelo a Invoice Radar. Ahora puede ejecutar el complemento para recuperar facturas del servicio.
checkAuth
)Muchos servicios redireccionan automáticamente a la página de inicio de sesión si el usuario no está autenticado. Podemos utilizar este comportamiento para comprobar si el usuario está autenticado.
{ "acción": "navegar", "url": "https://example.com/login"}, { "acción": "checkURL", "url": "https://ejemplo.com/cuenta", }
Dependiendo del servicio, es posible que lo redireccionen desde el panel a la página de inicio de sesión si no está autenticado. En este caso, puede utilizar el paso checkURL
para comprobar si la URL aún coincide después de visitar el panel.
{ "acción": "navegar", "url": "https://example.com/dashboard"}, { "acción": "checkURL", "url": "https://example.com/dashboard", }
Tenga en cuenta que puede utilizar patrones globales para hacer coincidir las URL dinámicas: https://example.com/dashboard/**
.
Puede utilizar un selector que sea exclusivo del estado autenticado para comprobar si el usuario está autenticado, por ejemplo, un botón de cierre de sesión o un enlace de perfil.
{ "acción": "navegar", "url": "https://example.com/home"}, { "action": "waitForElement", "selector": "#logout-button"}
En algunos casos, el sitio web no se ha cargado completamente cuando se ejecuta el paso checkElementExists
. Para evitar esto, puede utilizar el atributo waitForNetworkIdle
para esperar a que la página se cargue por completo.
{ "acción": "navegar", "url": "https://example.com/home", "waitForNetworkIdle": verdadero}, { "action": "checkElementExists", "selector": "#logout-button"}
startAuth
)La mayoría de los procesos de autenticación comienzan navegando a la página de inicio de sesión y esperando a que aparezca un elemento específico después de un inicio de sesión exitoso.
Recuerde que el navegador estará visible durante el proceso de autenticación, permitiendo al usuario interactuar con el formulario de inicio de sesión. El flujo de autenticación en sí puede automatizarse, pero no es necesario.
{ "acción": "navegar", "url": "https://example.com/login"}, { "action": "waitForElement", "selector": "#logout-button", "timeout": 120000}
Para darle al usuario suficiente tiempo para iniciar sesión, se recomienda proporcionar un tiempo de espera prolongado al paso de espera, con un valor predeterminado de 120 segundos.
Esta sección proporciona una descripción general de los pasos disponibles que se pueden utilizar para crear complementos para Invoice Radar. Cada paso representa una acción específica que se puede realizar durante el proceso de automatización.
Pasos de navegación
Navegar ( navigate
)
Esperar URL ( waitForURL
)
Esperar elemento ( waitForElement
)
Esperar navegación ( waitForNavigation
)
Esperar a que la red esté inactiva ( waitForNetworkIdle
)
Pasos de interacción
Haga clic en Elemento ( click
)
Escriba texto ( type
)
Seleccionar menú desplegable ( dropdownSelect
)
Ejecutar JavaScript ( runJs
)
Pasos de verificación
Comprobar que el elemento existe ( checkElementExists
)
Comprobar URL ( checkURL
)
Ejecutar JavaScript ( runJs
)
Pasos de extracción de datos
extraer ( extract
)
Extraer todo ( extractAll
)
Pasos de recuperación de documentos
Descargar PDF ( downloadPdf
)
Espere la descarga del PDF ( waitForPdfDownload
)
Imprimir página como PDF ( printPdf
)
Descargar Base64 PDF ( downloadBase64Pdf
)
Pasos de lógica condicional
Si ( if
)
Pasos varios
Dormir ( sleep
)
Fragmentos
Obtener factura desde la URL de Stripe ( getInvoiceFromStripeUrl
)
Obtenga facturas desde el portal del cliente de Stripe ( getInvoicesFromStripeBillingPortal
)
navigate
)Navega a la URL proporcionada y espera a que se cargue la página. De forma predeterminada, solo espera la carga de la página inicial, no ninguna solicitud AJAX posterior.
{ "acción": "navegar", "url": "https://ejemplo.com"}
Puede configurar waitForNetworkIdle
en true
para asegurarse de que la página esté completamente cargada antes de continuar.
{ "acción": "navegar", "url": "https://example.com/dashboard", "waitForNetworkIdle": verdadero}
Es bueno saberlo :
Las URL relativas son compatibles y se resolverán en función de la página actual.
La acción de navegación solo esperará a que se cargue la página inicial, no a ninguna solicitud AJAX posterior.
waitForURL
)Espera a que la URL actual coincida con la URL proporcionada, opcionalmente con un tiempo de espera. Admite comodines.
{ "acción": "waitForURL", "url": "https://example.com/profile/**", "timeout": 3000}
waitForElement
)Espera a que el selector dado aparezca en la página, opcionalmente con un tiempo de espera.
{ "acción": "waitForElement", "selector": "#ejemplo", "timeout": 3000}
waitForNavigation
)Espera a que se realice la navegación de la página. Este paso no esperará a que la página esté completamente cargada. Utilice el paso waitForNetworkIdle para ese fin. El tiempo de espera es opcional y su valor predeterminado es 10 segundos.
{ "acción": "waitForNavigation", "timeout": 10000}
waitForNetworkIdle
)Espera a que la red esté inactiva. Esto es útil si desea asegurarse de que la página haya terminado de cargar todos los recursos. Los pasos se completan cuando no hay más solicitudes de red durante 500 ms. El tiempo de espera es opcional y el valor predeterminado es 15 segundos.
El paso navigate
tiene una opción waitForNetworkIdle
que se puede establecer en true
para obtener el mismo comportamiento.
{ "acción": "waitForNetworkIdle", "tiempo de espera": 10000}
click
)Hace clic en el elemento especificado por el selector dado en la página.
{ "acción": "hacer clic", "selector": "#botón"}
type
)Escribe el texto dado en el elemento especificado por el selector dado en la página.
{ "acción": "tipo", "selector": "#input", "valor": "Hola mundo"}
dropdownSelect
) Selecciona el valor dado del menú desplegable especificado por el selector dado en la página. La selección se realiza en función del atributo value
de la opción.
{ "action": "dropdownSelect", "selector": "#dropdown", "value": "Opción 1"}
runJs
)Ejecuta el JavaScript proporcionado en el contexto de la página. Si se devuelve una promesa, se esperará.
Si desea utilizar el resultado de un script en pasos posteriores, utilice el paso de extracción.
{ "acción": "runJs", "script": "document.querySelector('#ejemplo').click();"}
Estos pasos se utilizan dentro de checkAuth
para verificar si el usuario está autenticado.
checkElementExists
)Comprueba si el selector dado existe en la página. Normalmente se utiliza para comprobaciones de autenticación.
{ "acción": "checkElementExists", "selector": "#ejemplo"}
checkURL
) Comprueba si la URL actual coincide con la URL proporcionada. Admite patrones de comodines como https://example.com/dashboard/**
.
{ "acción": "checkURL", "url": "https://ejemplo.com"}
runJs
) El paso runJs
también se puede utilizar como paso de verificación. Al ejecutar un script que devuelve un valor verdadero o falso, puede verificar si el usuario está autenticado.
{ "action": "runJs", "script": "document.cookie.includes('authToken');"}
Estos pasos se utilizan para cargar datos de la página, como una lista de elementos o un valor único, y utilizarlos en pasos posteriores.
extract
)Extrae un solo dato de la página y lo almacena en una variable.
Usando campos CSS:
{ "acción": "extraer", "variable": "cuenta", "campos": { "id": "#team-id", "name": "#team-name", "url": { " selector": "#team-link", "atributo": "href" } } }
En este ejemplo, account
se utiliza como nombre de variable y los campos id
, name
y url
se extraen mediante selectores CSS. Se pueden utilizar en pasos posteriores utilizando los marcadores de posición {{account.id}}
, {{account.name}}
y {{account.url}}
.
Usando JavaScript:
{ "acción": "extraer", "variable": "token", "script": "localStorage.getItem('authToken')"}
Este ejemplo crea una variable token
que se extrae mediante JavaScript. Se puede acceder al valor utilizando el marcador de posición {{token}}
. También es posible devolver un objeto.
extractAll
)Extrae una lista de datos de la página y ejecuta los pasos indicados para cada elemento. Esto se usa comúnmente para iterar sobre una lista de facturas y descargarlas.
Para cada elemento que coincida con el selector
, los campos se extraen y almacenan en la variable
disponible en los pasos forEach
.
Es bueno saberlo :
Cada selector dentro del objeto fields
tiene automáticamente como alcance el elemento coincidente.
El campo variable
es opcional. Si no se proporcionan, los datos extraídos se almacenarán en el item
variable predeterminado.
Se puede acceder al índice actual utilizando el marcador de posición {{index}}
. Comienza en 0 y aumenta para cada elemento.
Con campos 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" } }, "para cada uno": [ { "acción": "navegar", "url": "{{factura.url}}" }, { "acción": "descargarPdf", "factura": "{{factura}}" } ] }
Con JavaScript:
Cuando se utiliza JavaScript, el resultado debe ser una matriz de objetos o valores. Si el resultado es una promesa, se esperará.
{ "action": "extractAll", "script": "Array.from(document.querySelectorAll('#year-selector option')).map(option => option.value);", "variable": "año ", "para cada uno": [ { "action": "dropdownSelect", "selector": "#year-selector", "value": "{{year}}" } ] }
Paginación
Soporte experimental, aún no documentado.
Estos pasos se utilizan para descargar documentos y procesarlos en Invoice Radar. Todos los pasos requieren que se pase el objeto document
como argumento, que contiene los metadatos del documento.
El argumento document
tiene los siguientes campos:
Requerido
id
: El ID único del documento
Por ejemplo, INV-123
o 123456
date
: la fecha de la factura como cadena
Ej. 2022-01-01
o 01/01/2022
o January 1, 2022
Recomendado
total
: el importe total de la factura, incluida la moneda.
Por ejemplo, $100.00
o €100.00
o 100 EUR
o 100,00€
El analizador integrado intentará extraer la cantidad y la moneda de la cadena.
Opcional
type
: El tipo de documento (Opcional. El valor predeterminado es auto
)
Se puede configurar en auto
, invoice
, receipt
, refund
u other
.
metadata
: metadatos adicionales para el documento (opcional)
Por ejemplo, { "orderNumber": "12345" }
Puede pasar cada campo por separado o el objeto completo si contiene todos los campos obligatorios.
Por ejemplo, usando campos separados:
"documento": { "id": "{{item.invoiceId}}", "fecha": "{{item.date}}", "total": "{{item.amount}} {{item.currency }}", "tipo": "factura"}
Por ejemplo, si el objeto contiene todos los campos obligatorios, puedes pasarlo directamente:
"documento": "{{elemento}}"
downloadPdf
)Descarga un PDF desde la URL proporcionada.
{ "acción": "descargarPdf", "url": "https://example.com/factura.pdf", "documento": { "id": "{{item.invoiceId}}", "fecha": "{{item.fecha}}", "total": "{{item.total}}" } }
waitForPdfDownload
)Espera una descarga de PDF. El tiempo de espera predeterminado es 15 segundos.
{ "acción": "waitForPdfDownload", "timeout": 10000, "document": { "id": "{{item.invoiceId}}", "fecha": "{{item.date}}", "total ": "{{elemento.total}}" } }
printPdf
)Imprime la página actual en un archivo PDF.
{ "action": "printPdf", "document": { "id": "{{item.invoiceId}}", "fecha": "{{item.date}}", "total": "{{item .total}}" } }
downloadBase64Pdf
)Descarga un PDF desde una cadena codificada en base64.
{ "action": "downloadBase64Pdf", "base64": "{{item.base64String}}", "document": { "id": "{{item.invoiceId}}", "fecha": "{{item .fecha}}", "total": "{{item.total}}" } }
if
) Ejecuta los pasos dados si la condición es verdadera. Si la condición es falsa, se ejecutan los pasos else
.
{ "acción": "si", "script": "'{{factura.url}}'.includes('pdf')", "entonces": [ { "acción": "hacer clic", "selector": "#ejemplo" } ], "demás": [ { "acción": "navegar", "url": "https://example.com/fallback" } ] }
sleep
)Espera el tiempo indicado en milisegundos. Generalmente esto no se recomienda. En la mayoría de los casos, es mejor utilizar los pasos waitForElement, waitForURL o waitForNetworkIdle.
{ "acción": "dormir", "duración": 1000}
Los fragmentos son conjuntos de pasos prediseñados que simplifican las tareas comunes. Los pasos para un fragmento específico están visibles dentro de las herramientas de desarrollador.
Actualmente, no es posible crear fragmentos personalizados. Si tiene una tarea común que cree que sería útil como fragmento, cree un problema en GitHub.
getInvoiceFromStripeUrl
)Extrae una factura de una URL de factura de Stripe.
{ "action": "runSnippet", "snippet": "getInvoiceFromStripeUrl", "args": { "url": "https://invoice.stripe.com/i/inv_123" } }
getInvoicesFromStripeBillingPortal
)Extrae facturas disponibles de un portal de facturación de Stripe.
{ "action": "runSnippet", "snippet": "getInvoicesFromStripeBillingPortal", "args": { "url": "https://stripe-portal.example.com/billing" } }
A veces, es posible que necesites ejecutar una solicitud de recuperación dentro de un paso para recuperar datos de una API. Para hacer esto, puede utilizar la acción extractAll
.
{ "acción": "extractAll", "variable": "factura", "script": "fetch('https://example.com/api/invoices').luego(res => res.json()) " "para cada uno": [ { "acción": "descargarPdf", "url": "{{factura.url}}", "documento": { "id": "{{factura.id}}", "fecha": "{{factura .fecha}}", "total": "{{factura.total}}" } } ] }
Esto ejecutará la solicitud de recuperación y devolverá el resultado como un objeto JavaScript.
En algunos escenarios, es posible que necesites ejecutar un paso dentro de un elemento . Para hacer esto, puede usar el atributo
iframe
en el paso.
{ "acción": "hacer clic", "selector": "#botón-dentro-iframe", "iframe": verdadero},
Al configurar iframe
en true
, Invoice Radar encontrará el primer elemento en la página y ejecutará el paso dentro de él.
También puede utilizar una cadena contenida dentro del atributo src
del iframe para apuntar a un iframe específico.
{ "acción": "hacer clic", "selector": "#botón-dentro-iframe", "iframe": "iframe.example.com"},