SelSup Developers

La plateforme SelSup · Les guides

Extensions et intégrations sur mesure

Construisez une page HTML/JavaScript régulière en utilisant n'importe quel framework. SelSup l'intègre dans un iframe; il n'exécute pas votre code React à l'intérieur du placard.

Sections: 11Guide du développeur
→

Construisez une page HTML/JavaScript régulière en utilisant n'importe quel framework. SelSup l'intègre dans un iframe; il n'exécute pas votre code React à l'intérieur du placard.

Des développeurs d'applications et des partenaires technologiques

1

Choisissez le type d'intégration

  1. 1

    Service de backend externe

    Le jeton reste sur votre serveur et les données se déplacent à travers API et les webhooks.

  2. 2

    Panneau de l'iframe de l"armoire

    Construisez une page HTML/JavaScript régulière en utilisant n'importe quel framework. SelSup l'intègre dans un iframe; il n'exécute pas votre code React à l'intérieur du placard.

  3. 3

    Module de rétroaction SelSup

    Requérée pour une intégration de marché ou de livraison approfondie participant à des processus partagés de fond SelSup.

i
Commencez par une tranche verticale mince

Mettre en œuvre un flux de travail complet et son observabilité d'abord. Ajouter des importations en vrac, UI et plus de types d'événements après la réconciliation est stable.

2

Architecture d'applications externes

Gardez le jeton dans un gestionnaire de secrets et appelez SelSup uniquement depuis votre backend.

Séparer l'adaptateur SelSup, la file d'attente et le modèle de domaine.

Utilisez une boîte de réception pour les événements entrants et une boite de sortie pour les changements sortants.

Flux de données · Text
SelSup webhook → inbox → domain worker → ERP/WMS
ERP/WMS change → outbox → SelSup API → reconciliation

3

Panneau de l'iframe de l"armoire

Construisez une page HTML/JavaScript régulière en utilisant n'importe quel framework. SelSup l'intègre dans un iframe; il n'exécute pas votre code React à l'intérieur du placard.

Accueillez le panneau sur un site HTTPS séparé qui ne partage pas un domaine de cookie avec l'armoire. Ouvrez les intégrations → Mes extensions → Ajouter l'extension et sélectionnez un nom, une icône, une URL, une section de menu et une position. Enregistrer un panneil privé sans autorisations, puis activer uniquement les autorisations dont il a besoin. La publication du magasin nécessite une révision SelSup.

4

Module d'intégration côté serveur

Une intégration de marché couvre généralement des jetons, des cartes, des prix, des stocks, des commandes et des mises à jour de l'état des antécédents.

Ce module modifie le backend principal SelSup et suit son processus d'examen, de test, de localisation et de sortie.

Convertir les défaillances externes API en valeurs stables d'ApplicationError et les jetons externes annulés ou invalides en AccessException selon les règles du projet backend.

i
Compatibilité des données partagées

Ne pas ajouter de champs spécifiques au marché aux entités partagées.

5

Libération et exploitation

  1. 1

    Créer un compte de test

    Les données de production des clients doivent être fournies par des tests séparés, des entrepôts, des produits et des commandes.

  2. 2

    Ajouter l'observabilité

    Suivez le retard de la file d'attente, les erreurs par code, les recensements et les divergences de réconciliation.

  3. 3

    Plan de migration par contrat

    Soutenir les anciens champs pendant une transition et déployer les consommateurs avant de désactiver l'ancien format.

  4. 4

    Déconnexion du document

    Les utilisateurs doivent savoir comment révoquer un jeton, supprimer un webhook et arrêter la synchronisation sans perdre de données.

6

Les onglets produits et commandes

Choisissez une page de menu (MENU_PAGE), un onglet de carte de produit (PRODUCT_TAB) ou un ongleton de commande (ORDER_TAB). La section de menu et la position s'appliquent uniquement à MENU_PAGE. Les onglets nécessitent une entité enregistrée avec une ID.

7

Context et autorisations

Seuls les champs de contexte accordés sont partagés. Utilisateur fournit user.id et user.locale; CLIENT fournit client.id; ORGANIZATION fournit un identifiant et un nom d'organisation accessibles. PRODUCT accorde séparément product.modelId sur une carte produit; ORDER accorde order.id sur une commande. Les enregistrements complets, contacts, mots de passe et jetons sont exclus. Ce sont des identifiants de la page déjà ouverte, pas une preuve d'accès pour votre backend.

Context v1 · JSON
{
  "type": "selsup.extension.context",
  "version": 1,
  "context": {
    "version": 1,
    "extensionId": "example-extension-id",
    "placement": "MENU_PAGE",
    "user": {"id": 101, "locale": "ru"},
    "client": {"id": 202},
    "organizations": [{"id": 303, "name": "Demo"}]
  }
}
Context de l'onglet v1 · JSON
[
  {
    "version": 1,
    "extensionId": "example",
    "placement": "PRODUCT_TAB",
    "apiMethods": [],
    "product": {
      "modelId": 404
    }
  },
  {
    "version": 1,
    "extensionId": "example",
    "placement": "ORDER_TAB",
    "apiMethods": [],
    "order": {
      "id": 505
    }
  }
]

8

messages v1 post

Vérifiez l'événement exact.origine, événement.source === window.parent, type de message, version et structure. Envoyez prêt sur la connexion et le contexte de demande pour être rafraîchi. SelSup vérifie l'accès et fusionne les demandes fréquentes. Ne jamais passer des jetons dans les URL, le panneau localStorage ou les messages.

pont hôte / extension · JavaScript
const allowedOrigins = new Set(['https://your-cabinet.example.com']);
window.addEventListener('message', (event) => {
  if (event.source !== window.parent || !allowedOrigins.has(event.origin)) return;
  const message = event.data;
  if (!message || message.type !== 'selsup.extension.context' || message.version !== 1) return;
  const context = message.context;
  if (!context || context.version !== 1 || !['MENU_PAGE', 'PRODUCT_TAB', 'ORDER_TAB'].includes(context.placement)) return;
  // The complete sample also validates fields and strips unknown properties.
  document.querySelector('#context').textContent = JSON.stringify(context, null, 2);
});
for (const origin of allowedOrigins) {
  window.parent.postMessage({type: 'selsup.extension.ready', version: 1}, origin);
}
// Refresh after connecting: use the validated origin, never "*".
window.parent.postMessage({type: 'selsup.extension.request-context', version: 1},
  'https://your-cabinet.example.com');

9

API à travers le pont iframe

L'auteur déclare les méthodes requises dans les paramètres d'extension. Chaque client d'installation accorde explicitement des méthodes de cette déclaration. API accès par défaut à aucune, y compris les installations existantes. Modifier la liste demandée nécessite une autre révision; les copies installées ne reçoivent jamais de nouvelles autorisations automatiquement.

L'hôte ne fait appel que aux méthodes ci-dessous via les services SelSupFront avec les autorisations des employés actuels. Les contrôles d'accès au serveur existants s'appliquent toujours. ClientService et authService sont totalement interdits; toutes les méthodes en dehors de cette liste sont également interdites. Les applications ne peuvent pas fournir d'URL, d'en-têtes, de jetons ou de configuration arbitraire d'Axios. Le serveur vérifie l'installation actuelle et ses subventions sur la demande API réelle.

Les subventions API sont indépendantes des autorisations de contexte. context.apiMethods énumère les méthodes accordées. Une subvention s'applique à la méthode dans l'ensemble du cabinet dans l’accès du salarié, plutôt que uniquement à l’entité dans l\'onglet courant. Les résultats ne contiennent que les champs documentés, jamais les objets ou les informations d’identification Axios.

Une demande en vol et au plus une démarrage par seconde. Les 256 dernières ID de demande sont protégées contre les duplicates. Erreurs hôtes: ACCESS_DENIED, INVALID_REQUEST, ERATE_LIMITED, DUPLICATE_REQUEST, EREQUEST_FAILED. Erreur SDK comprennent également NOT_CONNECTED, DISCONNECTED et TIMEOUT (20 secondes). Ne jamais réessayer des mutations automatiquement: une error, une échéance ou une fermeture d'iframe ne signifie pas que l'opération a été rallée.

Métodes autorisées v1 · Text
tagService.findTags              {query?, page?, limit?}   => {rows: [{id, name}]}
tagService.createTag             {name}                   => {id, name}
tagService.updateTag             {id, name}               => {id, name}
tagService.deleteTag             {id}                     => null
productService.updateFavourite   {id, favourite}          => null

id: positive safe integer; updateFavourite.id = product.modelId
favourite: boolean
name: 1..100 characters (trimmed); query: 0..100 characters
page: 1..10000, default 1; limit: 1..100, default 30
Requête · JSON
{
  "type": "selsup.extension.api-request",
  "version": 1,
  "requestId": "request-1",
  "method": "tagService.createTag",
  "params": {
    "name": "Demo"
  }
}
Réponse · JSON
{
  "type": "selsup.extension.api-response",
  "version": 1,
  "requestId": "request-1",
  "ok": true,
  "result": {
    "id": 1,
    "name": "Demo"
  }
}
Prenons l'exemple du SDK: après que le contexte.apiMethods soit reçu · JavaScript
// connection = connectExtension(...) from selsup-extension.js
// Run from a button click after receiving context.apiMethods.
const tag = await connection.callApi('tagService.createTag', {name: 'Demo'});
console.log(tag.id, tag.name);

10

Exemple d'application et d'hébergement

L'échantillon peut être copié dans un référentiel GitHub indépendant. Avec Node.js 22+, test npm et npm démarrer les tests et un cabinet mock local sans clés API ou données réelles. Configurez config.js et déployez cinq fichiers statiques à HTTPS hébergement. Téléchargez l'archivage lié ci-dessous et copiez son contenu dans votre référencement GitHub.

Démo locale · Shell
cd selsup-extension-example
npm test
npm start
# Mock host: http://localhost:4174/
# Panel: http://127.0.0.1:4173/
Titres de réponse HTTPS · HTTP
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; connect-src 'none'; form-action 'none'; base-uri 'none'; frame-ancestors https://your-cabinet.example.com
Referrer-Policy: no-referrer
X-Content-Type-Options: nosniff
Précédent prêt pour ZIP / GitHub · URL
https://api.selsup.ru/assets/examples/selsup-extension-example.zip

11

Les limites de sécurité

La boîte à sable bloque les formulaires, les fenêtres contextuelles, les téléchargements, la navigation supérieure et les API de navigateur sensibles. L'origine du panneau est affichée au-dessus de l'iframe. Une extension ne doit jamais demander un mot de passe SelSup. Son site peut toujours voir l'IP du visiteur et conserver ou rediriger les données qui lui sont accordées.

SelSup lui-même autorise les appels de pont iframe; les cookies et les jetons n'atteignent jamais l'application. Votre propre backend a toujours besoin de sa propre authentification: le contexte ne prouve pas d'identité. Gardez uniquement les jeton SelSup de longue durée sur votre serveur.