Crear una extensión
Esta página está pensada para desarrolladores. Una extensión se describe con un manifiesto JSON: lo que declara (permisos, columnas, bloques, reglas) lo valida Sweescape al guardarlo. Su interfaz es una página HTML alojada en Sweescape que se muestra en un iframe aislado de la página de venta.
Cualquier cuenta puede crear extensiones y usarlas en sus propios eventos. La publicación en el marketplace está reservada al equipo de Sweescape.
Crear la extensión
Sección titulada «Crear la extensión»-
Abre el menú de tu cuenta, haz clic en Extensiones y luego en Crear extensión.
-
Rellena el formulario:
- Nombre: el nombre que aparece en tus listas y en el editor de página.
- Nombre del paquete: el identificador único de la extensión, en notación DNS inversa y en minúsculas, por ejemplo
com.subsol.plano-sala. No se puede cambiar después de crearla y tiene que estar libre en todo Sweescape. - Descripción: opcional.
-
Haz clic en Crear. La ventana pasa al paso Escribe el manifiesto, con un manifiesto de ejemplo ya rellenado.
Subir los archivos de interfaz
Sección titulada «Subir los archivos de interfaz»Debajo del editor de manifiesto, el campo Sube los archivos de interfaz y luego copia su URL en el manifiesto envía tus archivos a Sweescape.
- Formatos aceptados:
html,js,mjs,css,json,svg,png,jpg,jpeg,gif,webp,ico,woff,woff2,ttf,map,txt. - 5 MB como máximo por archivo, 50 archivos como máximo por envío.
- Cada archivo subido aparece con su URL pública, un botón para copiar la URL y una cruz para eliminarlo.
Escribir el manifiesto
Sección titulada «Escribir el manifiesto»
Un manifiesto mínimo que muestra un bloque en la página de venta:
{ "id": "com.subsol.plano-sala", "apiVersion": 1, "version": "1.0.0", "name": "Plano de sala SUBSOL", "description": "Elección del asiento antes de la compra.", "scopes": ["ui:render", "ticket:read"], "contributes": { "uiExtensions": [ { "surface": "page.block", "entry": "https://…/URL-copiada-del-archivo", "sandbox": { "allowedDomains": [] }, "descriptor": { "name": "SeatMap", "category": "media", "description": "Plano de sala", "fields": { "title": { "type": "text", "description": "Título del bloque" }, "ticket": { "type": "event_ticket", "description": "Entrada vendida" } }, "defaultProps": { "title": "Elige tu asiento", "ticket": "" } } } ] }}| Clave | Función |
|---|---|
id |
Igual al nombre del paquete. |
apiVersion |
Versión del contrato de extensión. Solo se acepta el valor 1. |
version |
Versión de tu extensión en formato semver (1.2.0). |
name, description |
Obligatorias. |
scopes |
Los permisos declarados. |
contributes |
Lo que añade la extensión: resourceFields, blocks, uiExtensions, rules. |
configSchema |
Opcional: ajustes descritos a nivel de la extensión. |
El campo author se rellena automáticamente con el nombre de tu cuenta: no hace falta escribirlo.
Los permisos (scopes)
Sección titulada «Los permisos (scopes)»Un permiso se escribe recurso:acción. Los recursos son event, ticket, participant, order, payment, ticket_code, audience, campaign, automation, contact, invitation, invoice, analytics, ticket_page, badge. Las acciones son read, write, create, act, subscribe. Se añaden dos permisos especiales: ui:render y net:fetch.
Cada contribución exige su permiso; si no, el guardado falla:
| Contribución | Permiso exigido |
|---|---|
Un bloque (blocks) o una interfaz (uiExtensions) |
ui:render |
Una interfaz con allowedDomains |
net:fetch |
Una columna de participante (resourceFields) |
participant:write |
Una regla activada por order.created (por ejemplo) |
order:subscribe |
Una acción adjust_price, reject o assign_ticket |
order:act |
Una acción webhook |
net:fetch |
Una acción set_field sobre un recurso |
recurso:write |
Las superficies
Sección titulada «Las superficies»La surface de una interfaz indica dónde se muestra. Hoy:
checkout.confirmationse muestra en la página de confirmación, después de un pago correcto;- todas las demás superficies (
page.block,checkout.step…) aparecen como un bloque, con el nombre de la extensión, en la última categoría del editor de página, que por ahora se llama OTHER.
Los ajustes del bloque
Sección titulada «Los ajustes del bloque»Existen dos tipos de bloques:
blocksreutiliza un bloque existente del editor de página, indicado enbaseComponent(por ejemploCard), con tus valores por defecto endescriptor.defaultProps. No se ejecuta código de terceros; los ajustes son los del bloque original.uiExtensionsmuestra tu propia interfaz (el archivo indicado enentry).
Para una interfaz, los fields del descriptor se convierten en los ajustes del bloque en el editor de página. La description de cada campo sirve de etiqueta. Tipos reconocidos:
| Tipo | Ajuste que se muestra |
|---|---|
text (y cualquier tipo desconocido) |
Campo de texto. |
textarea |
Área de texto. |
number |
Campo numérico. |
boolean |
Elección Sí / No. |
color |
Selector de color. |
select, radio |
Lista de las options declaradas. |
array |
Lista de elementos cuyos subcampos se describen en arrayFields. |
event_ticket |
Lista de las entradas del evento. El valor es el identificador de la entrada. |
Los valores que introduce el organizador se envían a tu interfaz al arrancar (ver abajo). defaultProps da los valores por defecto.
Las columnas de participante
Sección titulada «Las columnas de participante»resourceFields añade columnas a los participantes del evento, que rellena tu interfaz:
"resourceFields": [ { "resource": "participant", "column": { "name": "seat", "type": "text", "required": true, "source": "ui", "unique": true } }]name: minúsculas, cifras y_, empezando por una letra.firstname,lastnameyemailestán reservados.type:text,number,date,booleanoselect(conoptions).source: "ui": el valor viene de tu interfaz, nunca del formulario de compra.unique: true: el valor solo puede pertenecer a un participante del evento (un asiento, una franja horaria). Sweescape rechaza un pedido cuyo valor ya está cogido o reservado por un carrito en curso.
Estas columnas aparecen en la lista de participantes mientras la extensión esté activa en el evento.
Comunicarse con la página
Sección titulada «Comunicarse con la página»Tu interfaz se ejecuta en un iframe sandbox="allow-scripts" con un origen aislado. No recibe ningún token y solo se comunica con la página mediante postMessage.
| Mensaje enviado por el iframe | Efecto |
|---|---|
{ type: "sweescape:ready" } |
Pide arrancar. La página responde sweescape:init con config (los ajustes del bloque) y context. |
{ type: "sweescape:resize", height } |
Ajusta la altura del iframe, en píxeles. |
{ type: "sweescape:set-field", field, value } |
Guarda un valor de columna de participante para la compra en curso. |
{ type: "sweescape:checkout", ticketId, fields } |
Abre la ventana de compra con esta entrada, cantidad 1, con esos valores de columnas. |
{ type: "sweescape:checkout", items: [ { ticketId, quantity, units } ] } |
Abre la ventana de compra con varias entradas. units da los valores de columnas de cada entrada. |
{ type: "sweescape:request", requestId, method, params } |
Llama a un método de la página, que responde { type: "sweescape:response", requestId, ok, data } o error. |
Añade closeOnBack: true a un mensaje sweescape:checkout para que el botón de volver de la ventana de compra la cierre en lugar de mostrar la selección de entradas.
Métodos disponibles con sweescape:request:
| Método | Devuelve |
|---|---|
context.get |
El evento (id, name, startDate, endDate, status, type, taxRate), las entradas a la venta (id, title, price sin impuestos, stock, minQuantity, maxQuantity) y las columnas de la extensión. |
column.takenValues |
Con params: { column }: la lista de valores ya cogidos de una de tus columnas unique. |
participant.current |
Los valores de columnas ya introducidos para la compra en curso. |
ticketCode.unlock |
Con params: { code }: aplica un código de acceso y devuelve las entradas desbloqueadas y el cupo restante. |
order.current |
Solo en la superficie checkout.confirmation: id, total, currency y ticketCount del pedido pagado. |
Las reglas
Sección titulada «Las reglas»rules describe una lógica sin código, evaluada por Sweescape. Una regla tiene un id, un label, un evento que la activa on (order.created, order.confirmed, participant.created…), unas branches evaluadas en orden (se aplica la primera cuya condición when es verdadera) y un else opcional.
Acciones posibles:
reject: rechaza el pedido con unmessage, antes de escribir nada;adjust_price: propone un ajuste de precio, que Sweescape recalcula y limita entrebounds.minCentsybounds.maxCents;set_field: escribe un valor en una columna de tu extensión;assign_ticket: elige la entrada asignada al participante;webhook: envía un POST a una URLhttps, solo con tus columnas y campos no personales del pedido (order_id,event_id,participant_id,ticket_id,total_amount,currency,status).
Las reglas se validan al guardar el manifiesto: una regla sin el permiso <recurso>:subscribe de su evento, o una acción sin su permiso, se rechaza.
Guardar y corregir los errores
Sección titulada «Guardar y corregir los errores»Haz clic en Guardar. El mensaje «Extensión guardada» confirma la validación. Si no:
| Mensaje | Causa |
|---|---|
| «El manifiesto no es un JSON válido» | Error de sintaxis JSON (coma de más, comilla que falta). |
| «El manifiesto no es válido» | Falta una clave o tiene un valor rechazado: id mal formado, version que no es semver, superficie o tipo desconocido, columna reservada… |
| «El manifiesto usa una capacidad que no declara en «scopes»» | Añade el permiso que exige una contribución. |
| «El “id” del manifiesto debe coincidir con el nombre del paquete» | El id es distinto del nombre del paquete indicado al crearla. |
| «Este nombre de paquete ya está en uso» | Al crearla: elige otro nombre de paquete. |
Probar la extensión
Sección titulada «Probar la extensión»-
Abre uno de tus eventos, pestaña Extensiones, y haz clic en Activar junto a tu extensión. Aparece aunque no esté publicada, en cuanto su manifiesto está guardado.
-
Abre el editor de página, arrastra el bloque desde la última categoría de la lista (OTHER) y rellena sus ajustes.
-
Comprueba el resultado con el botón Vista previa del editor y después en la página publicada.
Para modificar la extensión, haz clic en el icono de lápiz junto a ella en Mis extensiones: la ventana Editar extensión vuelve a abrir el manifiesto y los archivos. El nuevo manifiesto se aplica en cuanto se guarda, en todos los eventos donde la extensión está activa.
Publicar, despublicar, eliminar
Sección titulada «Publicar, despublicar, eliminar»- Estado. Una extensión nueva lleva la insignia Private: solo la ves tú. La publicación en el marketplace (insignia Published) la hace el equipo de Sweescape; el botón Publicar no aparece para las demás cuentas.
- Eliminar. El icono de papelera elimina la extensión y sus archivos, sin confirmación. Si aún está activa en algún evento, la ventana No se puede eliminar la extensión los lista: desactívala antes en cada uno.
