Aller au contenu

Créer une extension

Cette page s’adresse aux développeurs. Une extension est décrite par un manifeste JSON : ce qu’elle déclare (permissions, colonnes, blocs, règles) est validé par Sweescape à l’enregistrement. Son interface est une page HTML que vous hébergez chez Sweescape et qui s’affiche dans un iframe isolé de la page de billetterie.

Tout compte peut créer des extensions et les utiliser sur ses propres événements. La publication sur la marketplace est réservée à l’équipe Sweescape.

  1. Ouvrez le menu de votre compte, cliquez sur Extensions, puis sur Créer une extension.

  2. Remplissez le formulaire :

    • Nom : le nom affiché dans vos listes et dans l’éditeur de page.
    • Nom du paquet : l’identifiant unique de l’extension, en notation DNS inversée et en minuscules, par exemple com.subsol.plan-salle. Il ne se modifie plus après la création et doit être libre sur tout Sweescape.
    • Description : facultative.
  3. Cliquez sur Créer. La fenêtre passe à l’étape Rédigez le manifeste, avec un exemple de manifeste pré-rempli.

Sous l’éditeur de manifeste, le champ Déposez le(s) fichier(s) d’interface, puis copiez leur URL dans le manifeste envoie vos fichiers chez Sweescape.

  • Formats acceptés : html, js, mjs, css, json, svg, png, jpg, jpeg, gif, webp, ico, woff, woff2, ttf, map, txt.
  • 5 Mo maximum par fichier, 50 fichiers maximum par envoi.
  • Chaque fichier déposé apparaît avec son URL publique, un bouton pour copier l’URL et une croix pour le supprimer.
Éditeur du manifeste de l'extension com.sweescape.subsol-seatmap (nom « Plan de salle Subsol », version 1.1.0, permissions ui:render, ticket:read et participant:write), zone Sélect. fichiers, deux fichiers seatmap.html et seatmap-1.1.0.html avec leur URL et un bouton de copie, boutons Annuler et Enregistrer

Un manifeste minimal qui affiche un bloc sur la page de billetterie :

{
"id": "com.subsol.plan-salle",
"apiVersion": 1,
"version": "1.0.0",
"name": "Plan de salle SUBSOL",
"description": "Choix de la place avant l'achat.",
"scopes": ["ui:render", "ticket:read"],
"contributes": {
"uiExtensions": [
{
"surface": "page.block",
"entry": "https://…/URL-copiée-du-fichier",
"sandbox": { "allowedDomains": [] },
"descriptor": {
"name": "SeatMap",
"category": "media",
"description": "Plan de salle",
"fields": {
"title": { "type": "text", "description": "Titre du bloc" },
"ticket": { "type": "event_ticket", "description": "Billet vendu" }
},
"defaultProps": { "title": "Choisissez votre place", "ticket": "" }
}
}
]
}
}
Clé Rôle
id Identique au nom du paquet.
apiVersion Version du contrat d’extension. Seule la valeur 1 est acceptée.
version Version de votre extension au format semver (1.2.0).
name, description Obligatoires.
scopes Les permissions déclarées.
contributes Ce que l’extension ajoute : resourceFields, blocks, uiExtensions, rules.
configSchema Facultatif : réglages décrits au niveau de l’extension.

Le champ author est rempli automatiquement avec le nom de votre compte : inutile de l’écrire.

Une permission s’écrit ressource:action. Les ressources sont event, ticket, participant, order, payment, ticket_code, audience, campaign, automation, contact, invitation, invoice, analytics, ticket_page, badge. Les actions sont read, write, create, act, subscribe. Deux permissions spéciales s’ajoutent : ui:render et net:fetch.

Chaque contribution exige sa permission, sinon l’enregistrement échoue :

Contribution Permission exigée
Un bloc (blocks) ou une interface (uiExtensions) ui:render
Une interface avec des allowedDomains net:fetch
Une colonne participant (resourceFields) participant:write
Une règle déclenchée par order.created (par exemple) order:subscribe
Une action adjust_price, reject ou assign_ticket order:act
Une action webhook net:fetch
Une action set_field sur une ressource ressource:write

La surface d’une interface dit où elle s’affiche. Aujourd’hui :

  • checkout.confirmation s’affiche sur la page de confirmation, après un paiement réussi ;
  • toutes les autres surfaces (page.block, checkout.step…) apparaissent comme un bloc, sous le nom de l’extension, dans la dernière catégorie de l’éditeur de page, affichée aujourd’hui sous le nom OTHER.

Deux sortes de blocs existent :

  • blocks réutilise un bloc existant de l’éditeur de page, désigné par baseComponent (par exemple Card), avec vos valeurs par défaut dans descriptor.defaultProps. Aucun code tiers ne s’exécute ; les réglages sont ceux du bloc d’origine.
  • uiExtensions affiche votre propre interface (le fichier indiqué dans entry).

Pour une interface, les fields du descriptor deviennent les réglages du bloc dans l’éditeur de page. La description de chaque champ sert de libellé. Types reconnus :

Type Réglage affiché
text (et tout type inconnu) Champ texte.
textarea Zone de texte.
number Champ numérique.
boolean Choix Oui / Non.
color Sélecteur de couleur.
select, radio Liste des options déclarées.
array Liste d’éléments dont les sous-champs sont décrits dans arrayFields.
event_ticket Liste des billets de l’événement. La valeur est l’identifiant du billet.

Les valeurs saisies par l’organisateur sont transmises à votre interface au démarrage (voir ci-dessous). defaultProps donne les valeurs par défaut.

resourceFields ajoute des colonnes aux participants de l’événement, que votre interface remplit :

"resourceFields": [
{
"resource": "participant",
"column": { "name": "seat", "type": "text", "required": true, "source": "ui", "unique": true }
}
]
  • name : minuscules, chiffres et _, commence par une lettre. firstname, lastname et email sont réservés.
  • type : text, number, date, boolean ou select (avec options).
  • source: "ui" : la valeur vient de votre interface, jamais du formulaire d’achat.
  • unique: true : la valeur ne peut appartenir qu’à un seul participant de l’événement (une place, un créneau). Sweescape refuse une commande dont la valeur est déjà prise ou réservée par un panier en cours.

Ces colonnes s’affichent dans la liste des participants tant que l’extension est active sur l’événement.

Votre interface tourne dans un iframe sandbox="allow-scripts" à l’origine isolée. Elle ne reçoit aucun jeton et communique avec la page uniquement par postMessage.

Message envoyé par l’iframe Effet
{ type: "sweescape:ready" } Demande le démarrage. La page répond sweescape:init avec config (les réglages du bloc) et context.
{ type: "sweescape:resize", height } Ajuste la hauteur de l’iframe, en pixels.
{ type: "sweescape:set-field", field, value } Enregistre une valeur de colonne participant pour l’achat en cours.
{ type: "sweescape:checkout", ticketId, fields } Ouvre la fenêtre d’achat sur ce billet, quantité 1, avec ces valeurs de colonnes.
{ type: "sweescape:checkout", items: [ { ticketId, quantity, units } ] } Ouvre la fenêtre d’achat sur plusieurs billets. units donne les valeurs de colonnes de chaque billet.
{ type: "sweescape:request", requestId, method, params } Appelle une méthode de la page, qui répond { type: "sweescape:response", requestId, ok, data } ou error.

Ajoutez closeOnBack: true à un message sweescape:checkout pour que le bouton retour de la fenêtre d’achat la ferme au lieu d’afficher le choix des billets.

Les méthodes disponibles avec sweescape:request :

Méthode Renvoie
context.get L’événement (id, name, startDate, endDate, status, type, taxRate), les billets en vente (id, title, price hors taxes, stock, minQuantity, maxQuantity) et les colonnes de l’extension.
column.takenValues Avec params: { column } : la liste des valeurs déjà prises d’une de vos colonnes unique.
participant.current Les valeurs de colonnes déjà saisies pour l’achat en cours.
ticketCode.unlock Avec params: { code } : applique un code d’accès et renvoie les billets débloqués et le quota restant.
order.current Sur la surface checkout.confirmation seulement : id, total, currency et ticketCount de la commande payée.

rules décrit une logique sans code, évaluée par Sweescape. Une règle a un id, un label, un événement déclencheur on (order.created, order.confirmed, participant.created…), des branches évaluées dans l’ordre (la première dont la condition when est vraie s’applique) et un else facultatif.

Les actions possibles :

  • reject : refuse la commande avec un message, avant toute écriture ;
  • adjust_price : propose un ajustement de prix, que Sweescape recalcule et borne entre bounds.minCents et bounds.maxCents ;
  • set_field : écrit une valeur dans une colonne de votre extension ;
  • assign_ticket : choisit le billet attribué au participant ;
  • webhook : envoie un POST vers une URL https, avec seulement vos colonnes et des champs de commande non personnels (order_id, event_id, participant_id, ticket_id, total_amount, currency, status).

Les règles d’un manifeste sont validées à l’enregistrement : une règle sans la permission <ressource>:subscribe de son événement, ou une action sans sa permission, est refusée.

Cliquez sur Enregistrer. Le message « Extension enregistrée » confirme la validation. Sinon :

Message Cause
« Le manifeste n’est pas un JSON valide » Erreur de syntaxe JSON (virgule en trop, guillemet manquant).
« Le manifeste est invalide » Une clé manque ou a une valeur refusée : id mal formé, version non semver, surface ou type inconnu, colonne réservée…
« Le manifeste utilise une capacité qu’il ne déclare pas dans « scopes » » Ajoutez la permission exigée par une contribution.
« Le “id” du manifeste doit correspondre au nom du paquet » L’id diffère du nom du paquet saisi à la création.
« Ce nom de paquet est déjà utilisé » À la création : choisissez un autre nom de paquet.
  1. Ouvrez un de vos événements, onglet Extensions, et cliquez sur Activer à côté de votre extension. Elle y figure même si elle n’est pas publiée, dès que son manifeste est enregistré.

  2. Ouvrez l’éditeur de page, glissez le bloc depuis la dernière catégorie de la liste (OTHER) et remplissez ses réglages.

  3. Vérifiez le rendu avec le bouton Aperçu de l’éditeur, puis sur la page publiée.

Pour modifier l’extension, cliquez sur l’icône crayon à côté d’elle dans Mes extensions : la fenêtre Modifier l’extension rouvre le manifeste et les fichiers. Le nouveau manifeste s’applique dès l’enregistrement sur tous les événements où l’extension est active.

  • Statut. Une extension créée porte le badge Private : elle n’est visible que par vous. La publication sur la marketplace (badge Published) est faite par l’équipe Sweescape ; le bouton Publier n’apparaît pas pour les autres comptes.
  • Supprimer. L’icône corbeille supprime l’extension et ses fichiers, sans confirmation. Si elle est encore active sur des événements, la fenêtre Impossible de supprimer l’extension les liste : désactivez-la d’abord sur chacun.