Index par titre

Actesweb

De #57516

En parcourant vos connecteurs, je vois qu'une interface réussi à été mise en œuvre à Dreux avec Mélodie ?

Oui mais pas avec un Mélodie à jour mais avec le logiciel précédent : ActesWeb qui était précédemment diffusé par Arpège et que la Ville de Dreux continue à utiliser

Pouvez-vous décrire rapidement le cas d'usage qui est couvert par cette interface SVP ?


Analyse fonctionnelle

Source : (cf. https://www.associations.gouv.fr/l-api-association.html). Disponibilité du connecteur pour utilisation de ces données dans Publik : novembre 2018.

Les données à récupérer (demande Arles), sur base d'un SIRET

cf. https://traitement-demarches.arles.fr/association/j-adhere-a-la-maison-de-la-vie-associative-mdva/

Pièces justificatives (fichiers)

API Entreprise

Le connecteur API Entreprise permet d'interroger un certains nombres d'endpoints de la base d'entreprises et d'associations sur entreprise.api.gouv.fr. Il est nécessaire d'obtenir un token pour utiliser le connecteur. Lors de la demande du connecteur, il est nécessaire de préciser à quels endpoints le token doit accéder.

Paramétrage

Le paramétrage doit indiquer :

V3 à venir en 2022

Tableau de correspondance : https://entreprise.api.gouv.fr/developpeurs/guide-migration/#table-de-correspondance-v-2-v-3
Guide de migration : https://entreprise.api.gouv.fr/developpeurs/guide-migration

Avec : Et aussi :

Nota : au 25/02/2022, la V3 n'étant pas complètement terminée, les différentes fonctionnalités arriveront au fur et à mesure, notamment les codes d'erreurs qui seront intégrés à la documentation progressivement.

Endpoints

associations

Récupérer les informations de l’association.

document

Récupérer un document de l’association.

document_association

Récupérer le plus récent document de l’association du type donné.

documents_associations

Récupérer les documents de l’association.

effectifs_annuels_acoss_covid

Récupérer les effectifs annuels d’une entreprise.

entreprise_effectifs_mensuels_acoss_covid

Récupérer les effectifs mensuels d’une entreprise.

entreprises

Récupérer les informations de l’entreprise.

etablissement_effectifs_mensuels_acoss_covid

Récupérer les effectifs mensuels d’un établissement.

etablissements

Récupérer les informations de l’établissement.

exercices

Récupérer les informations financières sur l’établissement (exercices).

extraits_rcs

Récupérer les données de l’entreprise (extrait RCS) auprès d’Infogreffe.


API factures pour logiciels métiers

Cette API doit être implémentée par tout logiciel générant des factures (chez nous chaque instance d'un tel service se nomme une régie) et qui souhaite que celles-ci puissent être payées dans le portail Publik, il permet à Publik de :

Publik gère la relation avec le prestataire de paiement et présente les interfaces aux usager pour le paiement des factures.

La ville et le prestataire du logiciel doivent mettre en place un moyen d'identification des débiteurs (codes sur les factures papiers ou envoyés par mail, ou tout autre moyen de communication).

On appellera dans le reste de ce texte "débiteur" l'usager qui a des factures à payer.

Style de l'API

Une API dans le style "REST" (GET/POST sur différentes URLs structurées) utilisant le format d'échange JSON.

Authentification de Publik sur les web-services du logiciel métier

Un seul mode d'authentification est supporté: HTTP Basic (https://fr.wikipedia.org/wiki/Authentification_HTTP#M%C3%A9thode_%C2%AB_Basic_%C2%BB)

Variables

Ces variables sont susceptibles d'apparaître dans la description des web-services.

Nom Description
<base_url> l'URL de base des web-services (ex.: https://logiciel-metier.maville.fr/api/factures/)
<base_path> le chemin de base des web-services (ex.: /api/factures/)
<base_host> le nom de domaine de base des web-services (ex.: logiciel-metier.maville.fr)
<name_id> l'identifiant de fédération avec l'application métier (ou sub OpenID connect si l'application métier propose la fédération de son portail web avec Publik via le protocole OpenID Connect), généré par le portail/la GRU Publik

Appairage / Identification des débiteurs

Il est nécessaire de faire correspondre l'identifiant de l'utilisateur au sein du portail Publik avec l'identifiant du débiteur dans le logiciel métier. Pour cela il sera remis des identifiants aux utilisateurs, la forme de ces identifiants dépend du cas d'usage/logiciel métier.

Création d'une liaison

Cette API est en partie définie par l'éditeur, en effet il devra préciser en plus du paramètre obligatoires la définition des paramètre nécessaire à l'identification d'un débiteur.

POST /link?NameID=<nameid>&<other_parameters> HTTP/1.1

<pas de contenu>

Un exemple d'autres paramètres pourrait être code_famille et code_secret par exemple pour une logiciel de gestion pour les services enfance/petite enfance.

POST /link?NameID=<nameid>&codeFamille=12345&codeSecret=XYZ HTTP/1.1

<pas de contenu>

Retour passant

La liaison a été créée ou elle existait déjà.

200 Ok
Content-Type: application/json

{"err": 0}

Retour non passant

La liaison ne peut-être créée.

200 Ok
Content-Type: application/json

{"err": 0, "err_desc": "identifiants inconnus"}

Listing des liaisons

GET /links?NameID=<nameid> HTTP/1.1

Retour passant

200 Ok
Content-Type: application/json

{
    "err": 0,
    "data": {
        "links": [
           "identifiant-débiteur-1",
           "identifiant-débiteur-2",
        ]
    }
}

Retour non-passant

404 Not found

{"err": 1, "err_desc": "aucune liaison"}

Suppression des liaisons

API via un POST sans contenu.

POST /unlink?NameID=<nameid> HTTP/1.1

<pas de contenu>

Retour passant

200 Ok
Content-Type: application/json

{"err": 0}

Retour non-passant

Aucun retour non passant n'est possible, toutes les liaisons depuis le NameID précisé devront être supprimées.

Remontée de la liste des factures à payer pour une régie donnée:

GET /<base_path>/invoices/?NameID=<nameid> HTTP/1.1
Host: <base_host>

Retour passant

200 Ok
Content-Type: application/json

{
  "data": [
        {
            "id": "934395",
            "label": "restauration août 2015",
            "amount": "37.26",
            "total_amount": "37.26",
            "online_payment": true,
            "created": "2015-08-01",
            "pay_limit_date": "2015-09-29",
            "has_pdf": true,
            "paid": false,
            "no_online_payment_reason": "litigation",
             ... (autres informations si le logiciel backend en donne) 
        },
        {
            "id": "93439XX",
            "label": "vacances scolaires novembre 2015",
            "amount": "33.26",
            "total_amount": "33. 26",
            "online_payment": false,
            "created": "2015-08-01",
            "pay_limit_date": "2015-09-29",
            "has_pdf": true,
            "paid": false,
            "no_online_payment_reason": "autobilling",
             ... (autres informations si le logiciel backend en donne) 
        },

        { ... }
  ],
  "err": 0
}

Détail des champs

Identifiant Description Type JSON
id l'identifiant de la facture dans le logiciel métier string
label l'intitulé de la facture string
amount le reste à payer si paiement partiel par ailleurs (Publik lui même ne permet pas les paiements partiels) string, nombre décimal, le point est le séparateur décimal
total_amount le montant total de la facture initiale idem amount
online_payment false si la facture est à payer par tout autre moyen de paiement que en ligne(prélèvement automatique, contentieux). booléen
no_online_payment_reason contient un "slug" du motif de l'impossibilité de non paiement en ligne, par exemple: autobilling (paiement par prélèvement bancaire), litigation (il y a un souci avec cette facture) string
has_pdf un PDF de la facture est disponible booléen
paid facture payée oui/non booléen
created, pay_limit_date dates de création et limite de paiement (date inclue, i.e. si 2015-09-29 alors le paiement ne sera plus possible le 30 septembre), string, date au format YYYY-MM-DD, dit ISO8601

Retour non-passant

Tout code HTTP non-200 ou "err": 1 ou si le content-type n'est pas application/json. On signalera la source de l'erreur dans "err_desc" :

{
   "err": 1,
   "err_desc": "aucune liaison pour cet identifiant Publik" 
}

Remontée des factures passées(payées):

GET /<base_path>/invoices/history/?NameID=<nameid>
Host: <base_host>

Retour passant

200 Ok
Content-Type: application/json

{
  "data": [
        {
            "id": "934395",
            "label": "restauration août 2015",
            "amount": "37.26",
            "total_amount": "37.26",
            "online_payment": false,
            "created": "2015-08-01",
            "pay_limit_date": "2015-09-29",
            "payment_date": "2015-09-19T00:00:00",
            "has_pdf": true,
            "paid": "true",
                        ... (autres informations si le logiciel backend en donne) 
        },
        {
            "id": "9343xx",
            "label": "vacances scolaires novembre 2015",
            "amount": "32.64",
            "total_amount": "32.64",
            "online_payment": false,
            "created": "2015-08-01",
            "pay_limit_date": "2015-09-29",
            "payment_date": "2015-09-19T00:00:00",
            "has_pdf": true,
            "paid": "true",
                        ...
        },

        { ... }
  ],
  "err": 0
}

Détail des champs

Identifiant Description Type JSON
payment_date donnée optionnelle, mais qui pourrait être utile string, date/heure au format YYYY-MM-DDTHH:MM:SS, dit ISO8601

Remontée des utilisateurs ayant des factures à payer:

GET /<base_path>/users/with-pending-invoices/ HTTP/1.1
Host: <base_host>

Retour passant

Retourne les nameId des comptes, et si possible la lise des factures à payer

200 Ok
Content-Type: application/json

{
   "err": 0,
   "data" : { 
       "uuid1": {
           "invoices": [{ ... }, ... ]
       },
       "uuid2": { 
           "invoices": [{ ... }, ... ]}
       }
   }
}

Détail des champs

Identifiant Description Type JSON
"<uuid>X" le NameID (identifiant Publik) de l'utilisateur concerné string
invoices peut-être une liste vide s'il n'est pas possible à ce moment de donner la liste des factures à payer tableau/liste d'objets/dictionnaires

Détails d'une facture:

GET /<base_path>/invoices/<identifiant_facture>/ HTTP/1.1
Host: <base_host>

Détail des champs

<identifiant_facture>: l'identifiant métier de la facture retourné dans le champ id des APIs de listing

Retour passant

200 Ok
Content-Type: application/json

{
  "data": {
            "id": "934395",
            "label": "restauration août 2015",
            "amount": "37.26",
            "total_amount": "37.26",
            "online_payment": true,
            "payable": true,
            "created": "2015-08-01",
            "pay_limit_date": "2015-09-29",
            "payment_date": "2015-09-19",
            "has_pdf": true,
                        ... (autres informations si le logiciel backend en donne) 
        },
  "err": 0
}

Récuperation du PDF d'une facture:

GET /<base_path>/invoice/<identifiant_facture>/pdf/ HTTP/1.1
Host: <base_host>

Retour passant

Le fichier PDF de la facture (réponse HTTP 200, Content-Type: application/pdf, pas d'encapsulation dans du JSON ou autre).

200 Ok
Content-Type: application/pdf

....

Retour non passant

Tout code non 200 ou dont le content-type n'est pas "application/pdf".

Signaler le paiement d'une facture:

POST /<base_path>/invoice/<identifiant_facture>/pay/?NameID=<nameid>
Host: <base_host>
Content-Type: application/json

{
    "transaction_id": "<identifiant_transaction>",
    "transaction_date": "2016-01-05T12:00:00" 
}

Retour passant

Le paiement a bien été pris en compte.

200 Ok
Content-Type: application/json

{
  "err": 0
}

Retour non passant

Le paiement n'a pas été pris en compte, recommencer, tout code non-200 ou contenu avec "err"=1 sera considéré comme non-passant.

500 Internal Server Error
Content-Type: application/json

{
  "err": 1
}

API Impôt particulier est l'API servie par la DGFIP qui peut être interrogée "via le dispositif FranceConnect ou directement hors FranceConnect". Documentation DGFIP disponible en pièces jointes.

Accès à un bac à sable à compter de novembre 2020, accès demandé par la Ville d'Arles (cf. #48667). Test effectué par Entr'ouvert : https://dev.entrouvert.org/projects/franceconnect/wiki/Utilisation_de_API_Imp%C3%B4ts_Particuliers


ArcGIS

Plus qu'un logiciel unique, ArcGIS est une suite logicielle : https://fr.wikipedia.org/wiki/ArcGIS
La documentation est... complète : https://developers.arcgis.com/documentation/ (elle est en fait gigantesque;-)
Il y a des API REST exposées : https://developers.arcgis.com/rest/location-based-services/
et plus spécifiquement des "ArcGIS Services" : https://developers.arcgis.com/rest/services-reference/map-service.htm

Description fonctionnelle

Le connecteur Publik (dans Passerelle) permet d'interroger certaines API REST proposées par ArcGIS :

En fonction des objets exposés par ArcGIS, les requêtes peuvent remplir tout type d'usage.

Attention : le connecteur ne permet pas de parcourir "librement" les données exposées : il faut connaître à l'avance ce qui est proposé par le serveur ArcGIS en terme de services, layers, folders, etc.
Astuce : en l'absence d'un accès complet aux backoffices ArcGIS, le logiciel QGIS avec son connecteur ArcGIS peut aider à parcourir les possibilités exposées.


Descriptif fonctionnel

La liaison Publik <> Espace Citoyens Premium (ECP) consiste en

Soit parce que Arpège en parle ainsi, soit parce que les collectivités discutent entre elles avec ce discours, ce connecteur est souvent vu comme un connecteur Publik <> Concerto (le logiciel famille d'Arpège) ; ce n'est pas cela !
Ce "connecteur" n'a été mis en place qu'à Orléans (situation à octobre 2020) et la ville d'Orléans a commandé auprès d'Arpège un portail famille. Le portail famille d'Arpège n'est en fait que l'Espace Citoyens Premium dont est retiré les démarches généralistes.


AstreGS

AstreGS est le nom du progiciel vendu par GFI. ASTREGF pour la gestion financière - ASTREGS pour la gestion des subventions (et ASTREGI pour les immobilisations ou encore ASTRERH pour les ressources humaines)

Version de AstreGS supportée par le connecteur : V8.05.005

Périmètre fonctionnel du raccordement

Ce raccordement permet la mise en oeuvre d'un portail usager dédié aux subventions. Le portail est porté par Publik et a pour objectif de permettre à l'usager de déposer des demandes de subvention pour des organismes. Les organismes et les demandes de subventions sont stockées dans AstreGS. Les demandes de subventions sont instruites dans AstreGS.

Un organisme peut être une association, une commune, un groupement de commune ou autre (organisme privé). Un organisme est appelé Tiers dans AstreGS.

Dans la version standard, l'organisme doit obligatoirement avoir un SIRET.

La demande de subvention, via un formulaire unique permet de gérer les subventions des domaines suivants :

Une demande de subvention est appelé Dossier dans AstreGS.

Il est possible dans un second temps, en extension du périmètre du raccordement standard, de pouvoir gérer des TIERS sans SIRET en utilisant l'IBAN comme identifiant. D'autres types de subventions comme les subventions exceptionnelles COVID, les bourses collèges, etc. peuvent être mises en oeuvre.

Les WS sont unitaires : CRUD sur Tiers, Documents, Contacts, RIB, Dossier, ce qui permet une grande souplesse (Attention le CRUD n'est pas encore tout à fait complet).

Voici le détail de la couverture du raccordement standard.


Atal

L'objectif du connecteur est de pouvoir créer une demande de travaux dans ATAL et de pouvoir en suivre l'évolution.

Création d'une demande de travaux

La création d'une demande se fait via le endpoint insert-demande-complet-by-type.
Aucune information obligatoire pour pouvoir créer une demande, une simple description peut suffire.
Une adresse, des coordonnées, des codes d'équipements ATAL peuvent également être utilisés pour affiner la demande.

Suivi de l'évolution d'une demande

Via le endpoint retrieve-etat-travaux.

Enrichissement d'une demande

On a possibilité d'enrichir une demande de travaux de :

Interne : voir aussi cette page


Base Adresse

Le connecteur Base Adresse permet d'interroger la Base Adresse Nationale (BAN). Il n'y a pas besoin de token.

Les API de géocodage sont une vue partielle de l’API de Nominatim https://wiki.openstreetmap.org/wiki/Nominatim ; elles ne prennent pour le moment pas en charge tous les paramètres et sont limitées au format JSON. Les API sur les villes, départements et régions sont basées sur API Géo https://api.gouv.fr/api/api-geo.html.

Paramétrage

Le paramétrage doit indiquer :

Endpoints

Liste d’adresses /addresses/

Retourne les adresses correspondant aux paramètres passés.

Liste des villes

Retourne les villes correspondant aux paramètres passés.

Liste des départements

Retourne les départements correspondant aux paramètres passés.

Liste des régions

Retourne les régions correspondant aux paramètres passés.

Géocodage inversé

Retourne l'adresse correspondant à la latitude et la longitude passées en paramètre.

Géocodage (API Nominatim)

Retourne la latitude, la longitude et l'adresse normalisée correspondant à la recherche passée en paramètre.

Rues d’un code postal

Retourne les rues correspondant au code postal passé en paramètre.


Document généralement obsolète.


Familles d'API Passerelle

datasources

Interro d'une sources de données

Modèle de base BaseDataSource : title, slug, description. Renvoie juste une exception NonImplementedError...

api

Requête :

GET /data/<slug>/json[?q=...] HTTP/1.0

Retour :

{
    data: [ { id: "14114", text: "BESSIN" }, ... ],
    err: 0
}

Même interrogration possible avec /jsonp à la place de /json dans la requête, le retour est alors en jsonp.

modèle dérivés

Peut-être un modèle à ajouter : CacheDataSource avec un timeout en secondes, qui servirait de base à DistantCsvDataSource et autres.

repost

Techniques génériques pour effectuer un POST vers une URL distante

Modèle de base BasePost : title, slug, description, url, timeout. Il reposte directement les données reçues dans l'URL indiquée.

api

POST /post/<slug>/json[?...]

<objet JSON> ou null

Retour :

{
    data: ...,
    err: 0
}

modèles dérivés

register

Abonnement à une ressource.

api

Demande la liste des ressources auxquelles on peut s'abonner, et via quel transport (mail, sms, rss, ...).

Si un utilisateur (user) est précisé dans l'URL, l'api indique pour chaque ressource par quels transports il y est abonné.

Note : le "user" indiqué permet à Passerelle de renvoyer l'info nécessaire au «vrai» système d'abonnement, on peut par exemple imaginer user=benji@trouvert.org;0612345678 pour un système qui propose mail et sms.

Requête :

GET /register/<slug>/[?user=...] HTTP/1.0

Retour :

{
    data: [  # liste de ressources
        {
            name: '...', # nom de la ressource, si possible de type "id" utilisable dans une URL REST
            description: '...', # optionnel, description de la ressource
            url: '...', # optionnel, page "plus d'information" 
            rss: '...', # optionnel
            transports: {
                available: ['mail', 'rss', 'sms', ...],
                defined: ['mail', 'rss'],  # abonnement du user, si spécifié
            }
        }, ...
    ],
    err: 0
}

Mise à jour des abonnements de user à une ou plusieurs ressources :

Requête :

POST /register/<slug>/?user=... HTTP/1.0

[ # liste de ressources
    {
        name: '...',
        transports: ['mail', 'rss']  # mode d'abonnements choisis
    }, ...
]

Retour :

{
    data: {
        message: 'Vous êtes bien abonné à ...',
    },
    err: 0
}

message

Permet l'envoi d'un message à une cible (SMS, mail, ...)

api

Envoi :

POST /message/<slug>/ HTTP/1.0

{
   message: '...',
   from: '...',
   to: ['...', '...', ...]
}

Retour :

{
    data: {
       message: '4 message envoyés',
    },
    err: 0
}

Contrôle d'accès

Pour chaque point d'accès :

Cart@DS CS

Connecteur développé dans #27144.

Note 20/07/2023 : Aujourd'hui ce connecteur est déprécié et n'est plus utilisé. La mise en place d'une connexion SSO au service Cart@DS est à privilégier pour simplifier le parcours usager.

Nous avons pu échanger avec GFi (éditeur de la solution) qui nous a donné accès aux documentations fonctionnelles et techniques de leur application. Nous allons développer le connecteur avec Publik conformément à ce qui suit.

Description fonctionnelle

Ce connecteur permettra de déverser dans Cart@ds les demandes des usagers et de leur offrir le suivi de celles-ci. Le recours au pdf interactif sera malgré tout obligatoire puisque c'est le mode de fonctionnement adopté par cette application. La demande référence donc les informations principales (demandeur, adresse...) mais le contenu de la demande elle-même sera stockée dans le pdf interactif.

Les fonctionnalités envisagées pour cette interface sont les suivantes :

Déroulé d'une demande

Sources de données

Avec ces sources on peut créer une page unique, avec les listes qui se rafraichiront selon les choix, pour créer une démarche de téléchargement de CERFA, en retirant la page de validation et mettant derrière un workflow qui fasse juste redirection vers {{form_var_cerfa_url}}.

Appels webservice

Pour le dépôt de dossier, une première page pareil, avec communes/types de deossier/objets de la demande, puis une deuxième page pour permettre à l'usager de transmettre les pièces.

Cela se passe via un gabarit dédié, à attacher à un champ commentaire (template-pieces-cartads en classes CSS). Ce gabarit assurera la présentation de l'interface de transmission des pièces, en transférant celles-ci directement à Cart@DS, sans stockage dans des fichiers côtés w.c.s.

Ce gabarit utilise ces deux appels, à définir :

Ensuite, pour la validation des données, en condition de sortie de page, webservice.cartds_check_pieces['result'] is True.

Pour la transmission de la demande, appel webservice depuis le workflow, vers send, en GET, avec dans l'URL :

En lui mettant comme identifiant "cartads", on reçoit cartads_response_dossier_id avec le numéro de dossier (interne passerelle).

Pour le suivi du dossier, appel en GET vers status, en GET, avec dans l'URL :

En retour, les clés status_id et status_label.

Debug côté Cart@DS CS


Schema des flux

autonumber
participant WCS
participant Passerelle
participant RepertoireDeDepot
participant CityWeb

WCS->Passerelle: Envoie de la demande
Passerelle->RepertoireDeDepot: Depot de la demande au format zip
RepertoireDeDepot->CityWeb: Récuperation de la demande et intégration dans CityWeb

Variables à envoyer au connecteur en payload JSON

Nom Obligatoire Valeurs possibles Commentaires
applicant_address_city non ville de l'adresse du demandeur
applicant_address_complement non complément d'adresse du demandeur
applicant_address_country non pays de l'adresse du demandeur
applicant_address_county non département de l'adresse du demandeur
applicant_address_email non email du demandeur
applicant_address_phone non numéro de teléphone du demandeur
applicant_address_street non rue de l'adresse du demandeur
applicant_address_zipcode non code postal de l'adresse du demandeur
applicant_firstnames oui prénoms du demandeur
applicant_lastname oui nom du demandeur
applicant_usual_name non nom d'usage du demandeur
applicant_status oui qualité du demandeur
applicant_title non M,Mme,Mlle identifiant titre du demandeur
applicant_title_label non titre du demanduer
application_id oui (N ou M ou D) + année sur 4 + mois sur 2 + numéro de séquence.XML (exemple N20170800764.xml)
application_origin non internet, guichet, courier origine de la demande
application_reason non motif de la demande
application_time oui [receipt_time] Date de reception de la demande dans WCS
certificate_type oui NAI, MAR, REC, DEC identifiant du type de certificat
certificate_type_label non type de certificat
concerned_birth_city non ville de naissance de la personne concernée
concerned_birth_country non pays de naissance de la personne concernée
concerned_birth_county non département de naissance de la personne concernée
concerned_birth_date non date de naissance de la personne concernée
concerned_firstnames oui prénoms de la personne concernée
concerned_lastname oui nom de la personne concernée
concerned_usual_name non nom d'usage de la personne concernée
concerned_parent1_firstnames non prénoms du 1er parent de la personne concernée
concerned_parent1_lastname non nom du 1er parent de la personne concernée
concerned_parent1_name_usage non nom d'usage du 1er parent de la personne concernée
concerned_parent1_title non identifiant titre du 1er parent de la personne concernée
concerned_parent1_title_label non titre du 1er parent de la personne concernée
concerned_parent1_sex non sexe du 1er parent de la personne concernée
concerned_parent2_firstnames non prénoms du 2e parent de la personne concernée
concerned_parent2_lastname non nom du 2e parent de la personne concernée
concerned_parent2_name_usage non nom d'usage du 2e parent de la personne concernée
concerned_parent2_title non identifiant titre du 2e parent de la personne concernée
concerned_parent2_title_label non titre du 2e parent de la personne concernée
concerned_parent2_sex non sexe du 2e parent de la personne concernée
concerned_sex non M, F, NA identifiant sexe de la personne concernée
concerned_sex_label non libelé du sexe de la personne concernée
concerned_title non M,Mme,Mlle identifiant titre de la personne concernée
concerned_title_label non titre de la personne concernée
document_copies oui nombre d'exemplaire
document_type oui CPI, EXTAF, EXTSF, EXTPL identifiqnt du type de document
document_type_label non type de document(Copie intégrale, Extrait avec filiation, Extrait sans filiation, ...)
event_city non ville de tenu de l'évènement
event_date_end non date de fin de l'évènement dans le cas ou il y'en a
event_date_start oui date de l'évènement ou date de début de l'évènement
partner_birth_city non ville de naissance du partenaire de la personne concernée
partner_birth_country non pays de naissance du partenaire de la personne concernée
partner_birth_county non département de naissance du partenaire de la personne concernée
partner_birth_date non date de naissance du partenaire de la personne concernée
partner_firstnames non prénoms du partenaire de la personne concernée
partner_lastname non nom du partenaire de la personne concernée
partner_usual_name non nom d'usage du partenaire de la personne concernée
partner_parent1_firstnames non prénoms du 1er parent du partenaire de la personne concernée
partner_parent1_lastname non nom du 1er parent du partenaire de la personne concernée
partner_parent1_name_usage non nom d'usage du 1er parent du partenaire de la personne concernée
partner_parent1_title non identifiant titre du 1er parent du partenaire de la personne concernée
partner_parent1_title_label non titre du 1er parent du partenaire de la personne concernée
partner_parent1_sex non sexe du 1er parent du partenaire de la personne concernée
partner_parent2_firstnames non prénoms du 2e parent du partenaire de la personne concernée
partner_parent2_lastname non nom du 2e parent du partenaire de la personne concernée
partner_parent2_name_usage non nom d'usage du 2e parent du partenaire de la personne concernée
partner_parent2_title non identifiant titre du 2e parent du partenaire de la personne concernée
partner_parent2_title_label non titre du 2e parent du partenaire de la personne concernée
partner_parent2_sex non sexe du 2e parent du partenaire de la personne concernée
partner_sex non M, F, NA identifiant sexe du partenaire de la personne concernée
partner_sex_label non libelé du sexe du partenaire de la personne concernée
partner_title non M,Mme,Mlle identifiant du partenaire de la personne concernée
partner_title_label non titre du partenaire de la personne concernée

Sources de données

Le connecteurs vient avec les sources de données ci dessous :

Récupération des archives des demandes

host recette: passerelle.test.entrouvert.org

# rsync <host>:cityweb/*.zip <chemin_repertoire_local>


Cmis

Connecteur générique pour la norme CMIS. Permet d'envoyer des fichiers vers une GED.

Utilisation avec Alfresco

Alfresco doit être paramétré pour recevoir les documents : besoin d'un utilisateur dédié et d'un mot de passe, plus les droits d'accès lecture/écriture sur les dossiers destinataires.

Côté Publik, le paramétrage doit indiquer :

Utilisation dans un workflow

Une action webservice doit être ajoutée. L'url doit appeler le connecteur, par exemple :
{{passerelle_url}}cmis/ged-chezwam/uploadfile

La requête doit être envoyée en POST. Les paramètres à inclure sont :

A noter

Il n'est pas possible de renommer les fichiers envoyés.
L'écrasement des fichiers déjà présents (nommés de la même manière) peut poser problème (la GED refuse l'écrasement). Un contournement peut être la création à la volée d'un dossier portant le nom de l'usager. Dans ce cas, path va prendre une valeur du genre :

/GED/GRC/RH/{{form_var_nom|slugify|upper}}_{{form_var_prenom|slugify|upper}}

=> il est nécessaire d'envoyer un seul doc par webservice (nécessaire d’enchaîner plusieurs webservices si plusieurs documents à envoyer)
=> content est un paramètre optionnel, même s'il est marqué d'un * (trompeur)

Problèmes connus

Avec Alfresco, si les appels échouent en 401, vérifier coté Alfresco que alfresco.restApi.basicAuthScheme est à true (#51130#note-7)


Connecteur CSV

Définition des noms de colonnes

Les filtres


~~

Idée abandonnée avec #16768.

~~

~~

Connecteur État Civil

Cette page décrit l'interface commune qui doit être utilisée par tous les connecteurs type État Civil dans Passerelle.

Déclinaison mise en place sur instance de test d'Orléans :

Les variables

Nom Type Obligatoire Valeurs possibles Commentaires
application_id string oui (display_id)
application_time string oui (receipt_time)
certificate_type string oui birth, marriage, death, other
certificate_type_label string non e.g Acte de Naissance
document_type string oui full, multilingual, with-filiation, without-filiation
document_type_label string non e.g Copie intégrale, plurilingue, extrait avec filiation, extrait sans filiation
document_copies integer non
event_city string non
event_date_start date non format ISO
event_date_end date non format ISO
application_reason string non motif de la demande
application_comment string non commentaire sur la demande
application_city string non nom de la ville à qui la demande est adressée
application_city_inseecode string non code INSEE de la ville à qui la demande est adressée
application_city_zipcode string non code postal de la ville à qui la demande est adressée
applicant_is_concerned boolean non true,false définit si le demandeur est aussi le titulaire de l'acte
application_priority string non définit la priorité de la demande

Variables relatives au demandeur

Nom Type Obligatoire Valeurs possibles Commentaires
applicant_title string non mr, ms, mx
applicant_title_label string non
applicant_lastname string oui
applicant_firstnames string oui
applicant_usual_name string non
applicant_email string non
applicant_phone string non
applicant_type string non mairie, avocat, notaire, administration, particulier, ...
applicant_status string oui concerned, partner, parent, child, grand-parent, grand-child, heir, representative, other personne concernée, conjoint(e), parent, enfant, grand-père ou grand-mère, petit(e) fils/fille, héritier, représentant légal
applicant_status_label string non
applicant_address_street_number string non numéro de la voie
applicant_address_street_type string non type de la voie
applicant_address_street string non
applicant_address_complement string non
applicant_address_city string non
applicant_address_zipcode string non
applicant_address_country string non Code ISO ou nom du pays en fonction du connecteur

Variables relatives à l'intéressé

Nom Type Obligatoire Valeurs possibles Commentaires
concerned_title string non mr, ms, mx
concerned_title_label string non e.g monsieur, madame, neutre
concerned_firstnames string oui
concerned_lastname string oui
concerned_usual_name string non
concerned_birthdate date non format ISO
concerned_birthcountry string non Code ISO ou nom du pays en fonction du connecteur
concerned_birthcity string non
concerned_birthcounty string non Département
concerned_sex string non m, f, o Homme, femme ou autre
concerned_citizenship string non

Variables relatives au partenaire de l'intéressé

Nom Type Obligatoire Valeurs possibles Commentaires
partner_title string non mr, ms, mx
partner_title_label string non e.g monsieur, madame, neutre
partner_firstnames string non
partner_lastname string non
partner_usual_name string non
partner_birthdate date non format ISO
partner_birthcountry string non
partner_birthcity string non
partner_birthcounty string non Département
partner_sex string non m, f, o Homme, femme ou autre
partner_citizenship string non

Variables relatives aux parents de l'intéréssé ou de son/sa partenaire

Nom Type Obligatoire Valeurs possibles Commentaires
{concerned,partner}_{parent1,parent2}_title string non mr, ms, mx monsieur, madame, neutre
{concerned,partner}_{parent1,parent2}_firstnames string non
{concerned,partner}_{parent1,parent2}_lastname string non
{concerned,partner}_{parent1,parent2}_sex string non m, f, o Homme, femme ou autre

Les URL

Création d'une demande

Avec le payload json:

{
  "display_id": 123, 
  "receipt_time": "2017-07-01T00:00:00",
  "certificate_type": "Acte de Mariage",
  "certificate_type_raw": "MAR",
  "document_type": "Extrait avec filiation",
  "document_type_raw": "EF",
  "document_copies": 3,
  "concerned_firstnames": "Johnny Jumper",
  "concerned_lastname": "Doe",
  "concerned_birthdate": "1980-07-07",
  "concerned_birthcity": "Nantes",
  "concerned_birthcountry": "France",
  "applicant_firstnames": "Kevin",
  "applicant_lastname": "Troll",
  "applicant_address_street": "27 Blvd Henry Orion",
  "applicant_address_city": "Nantes",
  "applicant_address_zipcode": 44000,
  "concerned_parent2_firstnames": "Kim",
  "concerned_parent2_lastname": "Sung-Ho",
  "partner_firstnames": "Chelsea Ruth",
  "partner_lastname": "Whatever",
  "event_date": "2014-05-07" 
}

Le retour attendu est un json contenant la clé demand_id i.e. :

{
 "err": 0,
 "data": {
     "demand_id": "123-MAR-0" 
 }
}

Récupération du statut d'une demande

Dans le cas où le connecteur peut le permettre, l'URL de récupération du statut d'une demande sera comme suit :

La réponse renvoyée doit au minimum avoir les clés status et closed (Boolean).

{
  "err": 0,
  "data":{
   "status": "rejected", 
   "closed": true, 
   "comment": "Invalid demand" 
  }
}

Sources de données


Connecteur famille

Ici on definit une interface commune pour tous les connecteurs famille(Agora+, Teamnet, Concerto,...) dans Passerelle afin d'uniformiser l'usage des données dans nos applications.
Cela sous-entend les urls ainsi que le format des données que chaque connecteur doit définir.

Gestion/remontée des familles

Liaison avec une famille

Pour la liaison avec une famille existante le citoyen dispose d'un identifiant et un mot de passe qui lui est fourni par un moyen quelconque.

Url du webservice

Le lien entre la famille est le NameID du citoyen est stocké du côté du connecteur.
Aucune valeur de retour n'est attendue.

Deliaison d'une famille

Url du webservice

Pas de valeur de retour attendue.

Listing des informations d'une famille.

Une famille:

Url du webservice
Format des données attendues:
{
  "data": {
    "id": "12345",
    "keywords": ["monoparentale", "famille-nombreuse"],
    "address": "14, RUE FERNAND LEGER, 94120 FONTENAY SOUS BOIS",
    "city": "FONTENAY SOUS BOIS",
    "zipcode": "94120",
    ... (autres informations si le logiciel backend en donne)
    "adults": [
         {
               "id": "50107",
               "keywords": ["revenus-a-declarer", "celibataire"],
               "text": "Foo Bar",
               "first_name": "Foo",
               "last_name": "Bar",
               "birthdate": "22/04/1957",
               "sex": "M",
               "address": "14, RUE FERNAND LEGER, 94120 FONTENAY SOUS BOIS",
               "city": "FONTENAY SOUS BOIS",
               "zipcode": "94120",
               "phone": "1122334455",
               "cellphone": "1122334455",
               "email": "foo@bar.org",
               ... (autres informations si le logiciel backend en donne)
         },
         { ... }
    ],
    "children": [
        {
               "id": "18177",
               "keywords": ["3-ans", "petite-enfance", "non-inscrit-petite-enfance"],
               "text": "Kevin McCallister",
               "first_name": "Kevin",
               "last_name": "McCallister",
               "birthdate": "02/04/2012",
               "sex": "M",
               "address": "14, RUE FERNAND LEGER, 94120 FONTENAY SOUS BOIS",
               "city": "FONTENAY SOUS BOIS",
               "post_code": "94120",
               "phone": "22344556677",
               "cellphone": "2234455677",
               "email": "kevin@bar.org" 
               ... (autres informations si le logiciel backend en donne)
         },
        { ... }
     ]          
  },
  "err": 0
}

Les autres champs, présents dans la reponse, sont auxiliaires.

Si aucune famille rattachée au NameID, renvoyer null

Possibilité de filtrer les informations de la famille:


Documentation existante dans la documentation Publik :
https://doc-publik.entrouvert.com/admin-fonctionnel/parametrage-avance/source-de-donnees-csv/


Développement d’un connecteur avec Passerelle

Passerelle est le module en charge de l'interconnexion de Publik vers les API d'autres applications; cette documentation concerne le développement d'un connecteur en utilisant Passerelle et s'appuie pour cela sur l'installation d'un environnement de développement local.

⚠ Passerelle n'est pas l'unique possibilité d'interconnexion de Publik vers les autres applications, tous les échanges de Publik se font en HTTPS, cela permet à toute application tierce, en exploitant les actions, formats et API de Publik, d'interopérer directement avec celui-ci, sans connecteur particulier, ou à travers d'un module indépendant (ESB, proxy d'API externe, etc.).

Démarrage

Il faut d'abord créer un répertoire qui contiendra le connecteur, appelons ce répertoire "passerelle-test" (mkdir passerelle-test).

Dans ce répertoire (cd passerelle-test), il faut créer le module Python qui correspondra au connecteur, ici les tirets ne sont pas autorisés dans les noms, appelons-le donc "passerelle_test", un module Python est un simple répertoire (mkdir passerelle_test) contenant un fichier __init__.py, qui peut être vide (touch passerelle_test/__init__.py).

On a alors cette arborescence de fichier :

passerelle-test/
passerelle-test/passerelle_test/
passerelle-test/passerelle_test/__init__.py   # fichier vide

Code du connecteur

Le code du connecteur se crée dans le fichier passerelle-test/passerelle_test/models.py :

passerelle-test/
passerelle-test/passerelle_test/
passerelle-test/passerelle_test/__init__.py
passerelle-test/passerelle_test/models.py      # code du connecteur

Ce fichier models.py décrit un modèle Django, dans Passerelle on le fait hériter du modèle "BaseResource" qui contient déjà tout ce qui structure un connecteur :

from passerelle.base.models import BaseResource

class TestConnector(BaseResource):
    category = 'Divers'

    class Meta:
        verbose_name = 'Connecteur de test'

La catégorie où se range le connecteur se définit dans l'attribut category et le nom du connecteur va lui dans les métadonnées du modèle.

Très clairement ce connecteur ne fait encore rien mais il y a désormais assez de code pour l'instancier ; mais avant cela, il faut qu'il puisse être installé sur le système.

Installation du connecteur

Pour que le connecteur puisse être installé, il faut créer un fichier setup.py à la racine du projet (i.e. directement dans le répertoire passerelle_test/); son contenu peut être minimal :

#! /usr/bin/env python

from setuptools import setup, find_packages

setup(
    name='passerelle-test',
    author='John Doe',
    author_email='john.doe@example.net',
    url='http://example.net/',
    packages=find_packages(),
)

Le code d'installation exige la présence d'un fichier de documentation README, il doit donc être créé pour l'occasion (il peut très bien être vide, touch README).

À ce stade, l'arborescence du projet est donc celle-ci :

passerelle-test/
passerelle-test/README
passerelle-test/setup.py
passerelle-test/passerelle_test/
passerelle-test/passerelle_test/__init__.py
passerelle-test/passerelle_test/models.py

Il est maintenant possible de lancer l'installation, en mode développement pour permettre à nos modifications ultérieures d'être prises en compte sans demander à chaque fois une réinstallation (/home/utilisateur/envs/publik-env-py3/bin/python setup.py develop@).

$ /home/utilisateur/envs/publik-env-py3/bin/python setup.py develop
running develop
running egg_info
writing passerelle_test.egg-info/PKG-INFO
writing top-level names to passerelle_test.egg-info/top_level.txt
writing dependency_links to passerelle_test.egg-info/dependency_links.txt
reading manifest file 'passerelle_test.egg-info/SOURCES.txt'
writing manifest file 'passerelle_test.egg-info/SOURCES.txt'
running build_ext
Creating /home/utilisateur/envs/publik-env-py3/lib/python3.7/site-packages/dist-packages/passerelle-test.egg-link (link to .)
Adding passerelle-test 0.0.0 to easy-install.pth file

Installed /home/test/passerelle-test
Processing dependencies for passerelle-test==0.0.0
Finished processing dependencies for passerelle-test==0.0.0

Activation du connecteur

Le connecteur a désormais tout le nécessaire pour être activé, il reste juste à le déclarer dans la configuration, pour cela il faut créer un fichier /home/utilisateur/.config/publik/settings/passerelle/settings.d/connecteur.py (ou tout autre nom en .py), avec ces deux lignes :

INSTALLED_APPS += ('passerelle_test',)
TENANT_APPS += ('passerelle_test',)

Migration initiale

Django dispose d'un système automatique de migration des données des différents modèles, qui facilite grandement les mises à jour. Dans la majorité des cas ce système est automatique, il est temps de l'initialiser en créant une première migration :

$ /home/utilisateur/envs/publik-env-py3/bin/passerelle-manage --forceuser makemigrations passerelle_test
Migrations for 'passerelle_test':
  0001_initial.py:
    - Create model TestConnector

Si cette commande échoue sur un problème d'accès, vérifiez que votre utilisateur est bien dans le groupe "passerelle".

Instanciation du connecteur

Passerelle peut désormais être rédémarré, sudo supervisorctl restart passerelle. Et voilà, il est maintenant possible de naviguer, le nouveau connecteur apparaîtra dans la liste des connecteurs disponibles. Créons-le et donnons-lui le nom de "démo", sa première instance devient disponible : https://passerelle.dev.publik.love/passerelle-test/demo/

Endpoints

C'est ici que tout commence car bien sûr un connecteur vide n'a aucun intérêt, il faut désormais lui ajouter le code qui le rendra utile, sous forme de "endpoints", les URL qui seront utilisées pour exposer les webservices.

Il faut importer le code permettant de déclarer les endpoints from passerelle.utils.api import endpoint en haut du fichier models.py, et ensuite, dans le modèle TestConnector créé plus haut, nous pouvons alors déclarer un premier endpoint,

class TestConnector(BaseResource):
    []

    @endpoint()
    def info(self, request):
        return {'hello': 'world'}

Redémarrons Passerelle pour que le code soit pris en compte (sudo supervisorctl restart passerelle) et voilà, accéder à l'URL du endpoint, https://passerelle.dev.publik.love/passerelle-test/demo/info retourne la donnée au format JSON :

{
  "hello": "world" 
}

Il est aussi possible pour un endpoint d'attendre des paramètres, déclarons donc un deuxième endpoint, faisant l'addition de nombres entiers et retournant le résultat :

class TestConnector(BaseResource):
    []

    @endpoint()
    def addition(self, request, a, b):
        return {'total': int(a) + int(b)}

Visiter https://passerelle.dev.publik.love/passerelle-test/demo/addition?a=2&b=3 retournera au format JSON :

{
  "total": 5
}

Journalisation

Passerelle suit la configuration de la journalisation établie au niveau de Django (cf Journalisation dans la documentation officielle de Django) et ajoute à celle-ci une journalisation interne, consultable depuis la page de visualisation du connecteur.

L'objet logger d'un connecteur dispose des méthodes standards de log (debug, info, warning, critical, error, fatal); ainsi un connecteur opérant une division pourrait logguer au niveau "debug" toutes les demandes et logguer au niveau "error" les divisions par zéro :

class TestConnector(BaseResource):
    []

    @endpoint()
    def division(self, request, a, b):
        self.logger.debug('division de %s par %s', a, b)
        try:
            return {'result': int(a) / int(b)}
        except ZeroDivisionError:
            self.logger.error('division par zéro')
            raise

Autorisations d'accès

Par défaut les endpoints ajoutés sont privés, limités à une permission can_access, un tableau de gestion des autorisations d'accès est automatiquement inclus à la page de gestion du connecteur.

can_access est le nom par défaut utilisé pour limiter l'accès mais il est possible d'augmenter la granularité des autorisations, on pourrait ainsi avoir un autre endpoint dont l'accès serait différencié :

class TestConnector(BaseResource):
    []

    _can_compute_description = 'Accès aux fonctions de calcul'

    @endpoint(perm='can_compute')
    def addition(self, request, a, b):
        return {'total': int(a) + int(b)}

À noter également l'ajout dans la classe d'un attribut _can_compute_description, qui servira au niveau de l'interface à fournir une description pour cette autorisation d'accès.

Il est possible de créer des accès ouverts, en passant OPEN comme permission d’accès :

class TestConnector(BaseResource):
    []

    @endpoint(perm='OPEN')
    def info(self, request):
        return {'hello': 'world'}

Documentation

Pour renforcer l'utilité de la page d'information d'un connecteur il est important de documenter le connecteur et ses différents endpoints. Le connecteur en lui-même peut être décrit en ajoutant un attribut api_description. Pour les endpoints, cela passe par l'ajout de paramètres à la déclaration @endpoint :

class TestConnector(BaseResource):
    []
    api_description = "Ce connecteur propose quelques opération arithmétiques élémentaires." 

    @endpoint(description='Addition de deux nombres entiers',
              parameters={
                'a': {'description': 'Un premier nombre', 'example_value': '7'},
                'b': {'description': 'Un second nombre', 'example_value': '2'}
              })
    def addition(self, request, a, b):
        return {'total': int(a) + int(b)}

Dans description se place donc une description général de l'endpoint et dans parameters se place les informations sur les différents paramètres autorisés par l'appel, pour chacun d'eux une description et une valeur qui sera reprise en exemple peuvent être fournies.

Paramétrages supplémentaires

À l'instanciation d'un connecteur quelques paramètres sont demandés, un titre et une description, ainsi que le niveau de journalisation souhaité. Il est possible d'ajouter d'autres paramètres, il faut pour cela ajouter de nouveaux attributs à la classe du connecteur. Comme noté en début de document cette classe correspond à un modèle Django, il s'agit ainsi d'y ajouter des champs.

Comme exemple, créons un connecteur dont le rôle sera de nous renseigner sur le bon état de fonctionnement, ou pas, d'une adresse, en faisant en sorte que cette adresse soit un paramètre supplémentaire du connecteur.

Il faut donc ajouter un attribut au modèle, url = models.URLField(...) et cette information sera par la suite disponible dans self.url :

import requests
from passerelle.base.models import BaseResource

class TestConnector(BaseResource):
    category = 'Divers'
    url = models.URLField('URL', default='http://www.example.net')

    class Meta:
        verbose_name = 'Connecteur de test'

    @endpoint(description='Teste une adresse')
    def up(self, request):
        try:
            response = self.requests.get(self.url)
            response.raise_for_status()
        except requests.RequestException:
            return {'result': '%s est en panne' % self.url}
        return {'result': '%s est ok' % self.url}

Comme le modèle se trouve modifié, il est nécessaire de prévoir pour la base de données une migration qui ajoutera une colonne pour ce champ url, /home/utilisateur/envs/publik-env-py3/bin/passerelle-manage --forceuser makemigrations passerelle_test. Cette migration sera exécutée automatiquement au redémarrage de Passerelle, qui est donc nécessaire à cette étape.

Note : self.requests utilisé ici est un wrapper léger au-dessus du module Requests, qui ajoute une journalisation et une expiration automatique des appels.

Exécution de tâches planifiées (cron)

Un connecteur peut souhaiter exécuter des tâches de manière régulière, comme par exemple lancer une synchronisation avec un référentiel externe. Passerelle prend en charge quatre fréquences, une tâche peut être planifiée pour s'exécuter toutes les heures, tous les jours, toutes les semaines ou tous les mois. Pour ce faire il faut définir dans le connecteur une fonction avec la tâche à exécuter et la nommer selon la fréquence (hourly / daily / weekly / monthly).

from passerelle.base.models import BaseResource

class TestConnector(BaseResource):
    []

    def hourly(self):
        pass  # code exécuté toutes les heures

⚠ Les tâches planifiées sont lancées automatiquement dans un environnement de production debian mais pas dans un environnement de développement local.

Pour lancer manuellement une tâche planifiée dans un environnement de développement local (remplacer hourly pas daily / weekly / monthly selon le cas) :

/home/utilisateur/envs/publik-env-py3/bin/passerelle-manage tenant_command cron -d passerelle.dev.publik.love hourly

Suivi de la disponibilité

Dans le prolongement des tâches planifiées se trouve le suivi de la disponibilité. Un connecteur peut régulièrement (toutes les cinq minutes) interroger le service distant pour s'assurer de sa disponibilité et marquer celui-ci si jamais ce n'était pas le cas.

Il suffit pour assurer cela de définir une méthode check_status, le service sera considéré indisponible quand la méthode lèvera une exception.

from passerelle.base.models import BaseResource

class TestConnector(BaseResource):
    []

    def check_status(self):
        response = self.requests.get('http://example.net')
        response.raise_for_status()

⚠ Le suivi de disponibilité est lancé automatiquement dans un environnement de production debian mais pas dans un environnement de développement local.

Pour lancer manuellement le suivi de disponibilité dans un environnement de développement local :

/home/utilisateur/envs/publik-env-py3/bin/passerelle-manage tenant_command cron -d passerelle.dev.publik.love availability

Tâches asynchrones

Les tâches planifiées s'exécutent de manière régulière, il peut également être utile d'exécuter des tâches de manière ponctuelle, par exemple pour transférer en tâche de fond un fichier important. La méthode add_job permet d'ajouter une tâche de fond, qui sera exécutée après la requête.

class TestConnector(BaseResource):
    []

    @endpoint(description='Transfert de données',
              parameters={
                  'src': {'description': 'Source'},
                  'dst': {'description': 'Destination'},
              })
    def transfert(self, request, src, dst):
        self.add_job('execution_transfert', src=src, dst=dst)
        return {'msg': 'Transfert planifié', 'err': 0}

    def execution_transfert(self, src, dst):
        # ici obtenir les données depuis la source puis les transférer à destination
        pass

La méthode add_job prend comme paramètres le nom de la méthode à exécuter puis une série libre de paramètres nommés, qui seront utilisés lors de l'exécution.

Quand des tâches existent, la page du connecteur les reprend dans un tableau.

⚠ Dans un environnement de développement local, les tâche asynchrones ne sont exécutées que si passerelle utilise le serveur UWSGI .

Tests unitaires

Ils sont indispensables pour dormir tranquille, ils se créent dans un nouveau répertoire, tests et utilisent les modules pytest, pytest-django et django-webtest (ces trois modules doivent donc être installés).

Il y a d'abord à définir un fichier tests/settings.py particulier, qui assurera la présence du connecteur :

INSTALLED_APPS += ('passerelle_test',)

Puis ensuite créer un fichier pour les tests en eux-mêmes, ça peut être tests/test_connecteur.py, il commencera par les imports des modules souhaités puis la définition des objets qui seront ensuite utiles.

# -*- coding: utf-8 -*-

import pytest
import django_webtest

from django.contrib.contenttypes.models import ContentType
from passerelle_test.models import TestConnector
from passerelle.base.models import ApiUser, AccessRight

@pytest.fixture
def app(request):
    # création de l'application Django
    return django_webtest.DjangoTestApp()

@pytest.fixture
def connector(db):
    # création du connecteur et ouverture de la permission "can_access" sans authentification.
    connector = TestConnector.objects.create(slug='test')
    api = ApiUser.objects.create(username='all', keytype='', key='')
    obj_type = ContentType.objects.get_for_model(connector)
    AccessRight.objects.create(
            codename='can_access', apiuser=api,
            resource_type=obj_type, resource_pk=connector.pk)
    return connector

Vient alors enfin le temps de tester le connecteur, pour un test sur la fonction d'addition :

def test_addition(app, connector):
    resp = app.get('/passerelle-test/test/addition?a=5&b=3')
    assert resp.json.get('total') == 8

Les tests s'exécutent ensuite via la commande py.test, en pointant le fichier settings.py créé spécialement :

 $ DJANGO_SETTINGS_MODULE=passerelle.settings PASSERELLE_SETTINGS_FILE=tests/settings.py py.test 
======================================= test session starts =======================================
platform linux2 -- Python 2.7.14+, pytest-3.3.1, ...
cachedir: .cache
Django settings: passerelle.settings (from environment variable)
rootdir: ..., inifile:
plugins: ...
collected 1 item

tests/test_connecteur.py::test_addition PASSED                                              [100%]

==================================== 1 passed in 0.48 seconds =====================================

Au-delà


DPark

Variables

Abonnement

Label Description Obligatoire
firstnames Prénoms O
lastname Nom O
filenumber Numero de dossier O
badgenumber Numero de badge N
cardnumber Numero de carte N

Adresse

Label Description Obligatoire
address_complement1 Premier complément d'adresse N
address_complement2 Second complément d'adresse N
address_streetno Numero de rue N
address_streetext Extension numero de rue (BIS, TER, ...) N
address_streetname Nom de la rue N
address_sticode Code STI de l'adresse O
address_zipcode Code postal O
address_locality Localité O

Recherche de dossier

Requête

{
  'firstname': 'foo'
  'lastname': 'bar',
  'filenumber': '123456789'
  'badgenumber': '123456789'
  'cardnumber': '123456789' 
}

Réponse

Cas passant

{
    "err": 0
}

Cas non passant

{
   "err": 1, 
   "code": "unknown-file",
   "msg": "Dossier inconnu" 
}

La table des codes:

Code DPark Code WS
02 unknown-file
03 not-requester-file
04 support-number-unknown
05 badge-number-unknown
autre other-error

Récupération informations dossier

Requête

Avec nameid étant form_user_name_identifier_0

Réponse

Cas passant

{
    "data": [
        {
            "adresse_boitepostalelieudit": null, 
            "adresse_codepostal": "31000", 
            "adresse_codesti": "315553609666", 
            "adresse_etageescalierappartement": null, 
            "adresse_extension": 1, 
            "adresse_immeublebatimentresidence": null, 
            "adresse_localite": "TOULOUSE", 
            "adresse_nomvoie": "All\u00e9es Jean Jaur\u00e8s", 
            "adresse_numerovoie": 80, 
            "adresse_quartier": "PERI", 
            "demande_datedebutabo": "20180625", 
            "demande_datefinabo": "20190624", 
            "demande_delaiautorise": 30, 
            "demande_immatvehicule1": "CX453AD", 
            "demande_immatvehicule2": null, 
            "demande_marquevehicule1": "CITROEN", 
            "demande_marquevehicule2": null, 
            "demande_modelevehicule1": "GS", 
            "demande_modelevehicule2": null, 
            "demande_numerodossier": 22952, 
            "demandeur_civilite": 1, 
            "demandeur_email": "foo@bar.org", 
            "demandeur_nomusuel": "Mercier", 
            "demandeur_prenom": "Eric", 
            "demandeur_telephonefixe": "0611111111", 
            "demandeur_telephoneportable": null
        }, 
    ], 
    "err": 0

Cas non passant

{
  "data": null,
  "err": 1,
  "err_desc": "Dossier inconnu" 
}

Appairage

Requête

{
  'nameid': 'abcdefg'
  'firstname': 'foo'
  'lastname': 'bar',
  'filenumber': '123456789'
  'badgenumber': '123456789'
  'cardnumber': '123456789' 
}

Réponse

Cas passant

{
  "err": 0
}

Cas non passant

{
   "err": 1, 
   "code": "unknown-file",
   "msg": "Dossier inconnu" 
}

La table des codes:

Code DPark Code WS
02 unknown-file
03 not-requester-file
04 support-number-unknown
05 badge-number-unknown
autre other-error

Désappairage

Requête

Nom Obligatoire Valeurs possibles Description
nameid O Idientifiant publik de l'utilisateur
filenumber Numéro de dossier
{
  'nameid': 'abcdefg' 
}

Si filenumber présent, l'utilisateur sera désappairé que par rapport au numéro de dossier correspondant.

Réponse

Cas passant

{
  "data": True,
  "err": 0
}

Cas non passant

{
  "data": null,
  "err": 1,
  "err_desc": "No pairing exists" # exemple de description d'erreur
}

Vérification éligibilité adresse

Requête

Nom Obligatoire Valeurs possibles Description
address_sticode O Code STI
address_locality O Nom de la localité
address_zipcode O Code postal
address_complement1 Premier complement d'adresse: etage appartememt, escalier
address_complement2 Second complement d'adresse: immeuble, batiment, residence
address_streetno Numero de rue
address_streetext Numero d'extension de rue
address_streetname Nom de rue
{
  "address_complement1": "Apt 212",
  "address_complement2": "Batiment A",
  "address_streetno": "33",
  "address_streetext": "1", # (Vide, BIS, TER, QUATER)
  "address_streetname": "Rue du Cheval Blanc",
  "address_sticode": "37446",
  "address_zipcode": "44300",
  "address_locality": "Nantes" 
}

Les extensions d'adresse

identifiant text
1 Vide
2 BIS
3 TER
4 QUATER

Réponse

Cas passant

{
  "data": True,
  "address": {
    "address_zipcode": "31000", 
    "address_streetext": 1, 
    "address_complement2": null, 
    "address_complement1": null, 
    "address_locality": "Toulouse", 
    "address_streetno": 13, 
    "address_streetname": "Rue des Abeilles", 
    "address_sticode": "315550016038", 
    "address_place": null, 
    "address_district": "Dupuy" 
  },
  "desc": null,
  "err": 0,
}

Cas non passant

{
  "data": False,
  "desc": "Erreur extension" 
}

Vérification du délais d’autorisation de renouvellement

Requête

Nom Obligatoire Valeurs possibles Description
filenumber O Numéro de dossier
firstnames O Prénoms de l'abonné
lastname O Nom de l'abonne
badgenumber Numéro de badge
cardnumber Numéro de carte

Réponse

Cas passant

{
  "data": True,
  "err": 0
}

Cas non passant

{
  "data": null,
  "err": 1,
  "err_desc": "Renouvellement hors délai" 
}

Vérification d'un doublon de création

Requête

Nom Obligatoire Valeurs possibles Description
applicant_firstnames O Prénoms du demandeur
applicant_lastname O Nom du demandeur
address_complement1 N Premier complément d'adresse
address_complement2 N Second complément d'adresse
address_streetno N Numero de rue
address_streetext N Extension numero de rue (BIS, TER, ...)
address_streetname N Nom de la rue
address_sticode O Code STI de l'adresse
address_zipcode O Code postal
address_locality O Localité

Réponse

Cas passant

Cas non passant

{
  "err": 1,
  "err_desc": "<erreur d'utilisation du web-service>",
}

Vérification d’un doublon de renouvellement

Requête

Nom Obligatoire Valeurs possibles Description
filenumber O Numéro de dossier
firstnames O Prénoms de l'abonné
lastname O Nom de l'abonne
badgenumber Numéro de badge
cardnumber Numéro de carte

Réponse

Cas passant

Cas non passant

{
  "err": 1,
  "err_desc": "<erreur d'utilisation du web-service>",
}

Enregistrement d'une demande (renouvellement/inscription)

Variables relatives au demandeur

Nom Obligatoire Valeurs possibles Description
applicant_title O 1 ou 2 Civilité du demandeur. 1 pour Monsieur, 2 pour Madame
applicant_lastname O Nom du demandeur
applicant_firstnames O Prénoms du demandeur
applicant_phone Téléphone fixe du demandeur
applicant_mobilephone Téléphone mobile du demandeur
applicant_email O Courriel du demandeur

Variables relatives à l'adresse du demandeur

Nom Obligatoire Valeurs possibles Description
address_complement1 Etage, escalier ou numero d'appartement
address_complement2 Immeuble, batiment ou residence
address_streetno Numero de voie
address_streetext 1,2,3,4 Extension de rue avec 1 pour Vide, 2 pour BIS, 3 pour TER et 4 pour QUATER
address_streetname Nom de la voie
address_sticode O Code STI de l'adresse
address_place Boite postale, lieu-dit
address_zipcode O Code postal
address_locality O Localité
address_district O Quartier

Variables relatives à la demande

Nom Obligatoire Valeurs possibles Description
application_id O Numero de la demande
application_type O 1,2 Type de demande avec 1 pour Badge et 2 pour Carte
filenumber Numéro de dossier Dpark. Si renseigné, la demande est un renouvellement
application_car1_exemption O Cas d'éligibilité du véhicule 1 (cf cas éligibilité)
application_car1_model O Modele du véhicule 1
application_car1_brand O Marque du véhicule 1
application_car1_plate O Immatriculation du véhicule 1
application_car2_exemption Cas d'éligibilité du véhicule 2 (cf cas éligibilité)
application_car2_model Modele du véhicule 2
application_car2_brand Marque du véhicule 2
application_car2_plate Immatriculation du véhicule 2
application_thirdparty_subscription O un booléen Abonnement tiers, ne pas envoyer de chaîne "True" ou "true" ou "False" ou "false"
application_payment_type O 1,5,10 Type de paiement, avec 1 pour chèque, 5 pour prélèvement mensualisé et 10 pour carte bancaire via internet
application_bank_name Nom de la banque du demandeur
application_bank_address1 Ligne 1 de l'adresse de la banque
application_bank_address2 Ligne 2 de l'adresse de la banque
application_bank_zipcode Code postal de la banque
application_bank_city Ville ou se situe l'agence bancaire
application_bank_iban Numéro IBAN du compte bancaire
application_bank_bic Numéro d'identification de la banque

Cas d'éligibilité

Code Description
2 Cas 2: Véhicule location longue durée
6 Cas 1: Vehicule de fonction
8 Cas 0: Normal
10 Cas 5: véhicule préte longue durée
11 Cas 6: meme foyer fiscal + parents
17 Cas 7 : Plaisanciers Port St Sauveur

Requête

Exemple de payload

{
    "address_complement1": "",
    "address_complement2": "",
    "address_district": "PERI",
    "address_locality": "Toulouse",
    "address_sticode": "315553609651",
    "address_streetext": "1",
    "address_streetname": "",
    "address_streetno": "16",
    "address_zipcode": "31000",
    "applicant_email": "sh@eggs.org",
    "applicant_firstnames": "Spam Ham",
    "applicant_lastname": "EGGS",
    "applicant_mobilephone": "0655443322",
    "applicant_phone": "",
    "applicant_title": "1",
    "application_car1_brand": "Peugeot",
    "application_car1_exemption": "8",
    "application_car1_model": "206",
    "application_car1_plate": "AA777ZZ",
    "application_id": "12-4",
    "application_payment_type": "10",
    "application_thirdparty_subscription": false,
    "application_type": 1
}

Réponse

Cas passant

{
  "data": {
     "numerodossier": "22334",
     "numerodemande": "59492" 
  },
 "err": 0
}

Cas non passant

{
  "err": 1,
  "err_desc": "Dossier incomplet" 
}

Recuperation des infos de paiement

Requête

Il est possible de filtrer les données remontées par numero de dossier.

GET /dpark/<slug>/payment-info/<nameid>/?filenumber=123456

Réponse

Cas passant

{
 "data": [
   {
     "typepaiement_text": "Carte Bancaire via Internet",
     "numerodemande": 61718,
     "montant": 135,
     "numeroteledossierphase1": "E-8-N5UTAK6P",
     "typepaiement": 10
   }
 ],
 "err": 0
}

Cas non passant

{
  "data": [],
  "err": 0
}

Notification de paiement

Requête

Nom Obligatoire Valeurs possible Description
application_external_id O Numero de teledossier
application_id O Numero de demande
filenumer O Numero de dossier
nameid O Identifiant de l'utilisateur
total_amount O Montant total
transaction_datetime O Date et heure de la transaction
transaction_id O Numero de transaction

exemple de payload

{
 'application_external_id': 'E-8-N5UTAK6P',
 'application_id': '61718',
 'filenumber': '23644',
 'nameid': '6ec77aa7b2a04acf9339da553f16d91c',
 'total_amount': '135',
 'transaction_datetime': '2018-07-16T10:23',
 'transaction_id': '987654321'
}

Réponse

Cas passant

{
  "data": True,
  "err": 0
}

Cas non passant

{
  "err_class": "passerelle.utils.jsonresponse.APIError", 
  "err_desc": "Deja paye", 
  "data": null, 
  "err": 1
}

Envoi de fichiers

Codification des pièces justificatives

Identifiant Code Description
justif_domicile 2 Justificatif de domicile (<3 mois)
assurance 4 Attestation d'assurance (Conducteur principal)
cartegrise 6 Carte grise
carte_medecin 8 Carte d'ordre des medecins
immat_artisanat_d1 9 Immatriculation Chambre Métiers et de l'Artisanat ( D1 )
agrement 10 Agrément : Assoc ou Entreprise
attest_employeur 11 Attestation employeur (Usage privé et pro )
taxe_habitat 13 Taxe d'Habitation ou Bail ou Acte notarié
abt_transport 14 Abt Annuel transport en commun ( Tisséo, SNCF actif pro)
contrat_locvehicule 16 Contrat de location (Véhicule)
impot_revenu 17 Impôt sur le revenu
carteverte 18 Attestation d'Assurance (Carte Verte)
decla_impot 19 Déclaration Impôt revenu (Enfant rattaché)
assurance_pro 20 Attestation d'Assurance (Usage Professionnel)
cotis_urssaf 21 Cotisation à l’URSSAF
ordonnance 22 Ordonnance (Attest sur l'honneur Médecin)
attest_employeurpro 25 Attestation Employeur (Usage Pro du Véhicule Perso)
attest_honneur 26 Attestation sur l'honneur (Professionnel de l’Urgence)
attest_cpam 27 Attestation CPAM avec le numéro de conventionnement (TAP)
cartegrise_qe 28 Carte grise avec mention de la qualité électrique
contrat_livraison 29 Contrat de livraison entre le pro et le commerce ou attest livraison régulière (signature du pro et du commerçant)
immat_artisanat 30 Immatriculation au registre des métiers et de l'artisanat ou au registre du commerce
immat_artisanat_ape 31 Immatriculation au registre des métiers et de l'artisanat ou au registre du commerce (avec mention code APE)
contrat_amarrage 32 Le contrat de location d'un poste d'amarrage
facture_amarrage 33 Facture de paiement pour l'amarrage et charge

Explication sur la nomenclature des variables

Les variables de fichiers se construisent comme tel:

Avec identifiant déterminant le type de fichier. La ,<suffixe> est optionnel et permet de différencier les fichiers d'un même type et peut être n'importe quoi, la virgule est importante, elle sépare le type du suffixe.
Cela signifie que si l'on veut envoyer un justificatif de domicile et plusieurs carte grise, on aura la configuration suivante dans le workflow:

Nom Valeur Type
cartegrise,vehicule1 form_var_vehicule1_carte_grise_raw python
cartegrise,vehicule2 form_var_vehicule2_carte_grise_raw python
justif_domicile form_var_justif_domicile_raw python

Requête

Nom Obligatoire Valeurs possibles Description
application_external_id O Numéro de télédossier reçu lors de l'enregistrement de la demande e.g E-8-0AA666BB
application_id O Numéro de demande e.g 59492
doctype,whatever variable raw du champ fichier
anotherdoctype,whatever variable raw du champ fichier

NB: Le nombre de fichier à envoyer est calculé par le connecteur.

{
  "application_external_id": "E-8-0AA666BB",
  "application_id": "59492",
  "justif_domicile,whocares": {
      "content": "dGhpcyBpcyBteSBzZWNvbmQgcHJvb2Ygb2YgYWRkcmVzcw==", 
      "content_type": "application/pdf", 
      "filename": "address_proof.pdf" 
  }
}

Réponse

Cas passant

{
  "data": {
    "result": True, 
  },
  "err": 0
}

Cas non passant

{
  "data": null,
  "err": 1, 
  "err_desc": "Numéro de demande introuvable" 
}

Installation sur Debian 7.x

Les paquets Debian pour Passerelle fonctionnent sur Debian 7.x avec les sources backports activées (lire http://backports.debian.org/Instructions/)

Installation de Django 1.7

# apt-get install -t wheezy-backports python-django

Version de développement eobuilder

# apt-get install -t wheezy-eobuilder passerelle

Démarrage

Création d'une base PostgreSQL

postgres$ createuser passerelle
postgres$ createdb -O passerelle passerelle

Installation de nginx

Modèle dans /usr/share/doc/passerelle/nginx-example.conf à copier dans /etc/nginx/sites-available puis éditer, puis restart de nginx.


IParapheur

(obsolète, supprimé)


Les connecteurs

Apps

Contrib

Autres

Analysés (pas de connecteur développé)

Connecteurs non portés par Passerelle


Littéralis

Avant-propos

Côté sécurisation, chaque commune utilise un couple login/mot de passe différent.
Coté Publik, il faut créer autant d'instance de connecteurs que de communes concernées, et dans le workflow, faire en sorte d’appeler l'instance de connecteur appropriée.

Installation

  1. Configurer le ou les connecteurs.
  2. Importer le workflow.
  3. Créer le formulaire.

Connecteur

Informations à demander au client :

Chaque client du fournisseur doit également avoir un identifiant et un nom unique pour pouvoir les différencier. Cela permet de discriminer plusieurs collectivités qui utiliseraient le même fournisseur. Les champs titre et identifiant servent à cela.

Dans le paramétrage, laisser coché « Vérification des certificats » sauf si vous savez ce que vous faites.

Endpoints

Injection dans Littéralis :

Suivi :

Workflow

Donnée de traitement « identifiant demande littéralis » pour stocker l’id_demande retournée par l’appel à /demandes-recues

Injection de la demande dans Littéralis (/demandes-recues)

Retourne « idDemande » et « status » (avec la valeur « A_TRAITER »).

Injection de fichier (/upload)

Optionnel ; un PDF récapitulant la demande.

Injection de l’annexe (/annexes)

Optionnel ; documents annexes à la demande (transmis par l’usager).

Note : le workflow modèle n’intègre pas cet appel.

Récupération du statut (/demandes-recues-reponses)

id_demande à passer en paramètre d’url.

Les codes suivants sont possibles :

Récupération de l’acte (/demandes-recues-arrete)

Bien que ce endpoint soit exposé, il n'est pas fonctionnel. Cela peut faire l'objet d'un développement complémentaire.

Formulaire

Littéralis a besoin de coordonnées géographiques (champs obligatoires à l’injection). Il faut donc prévoir une carte ou résoudre les coordonnées par l’adresse.


Logitud

Schéma des échanges WCS - Passerelle - Logitud

autonumber
participant WCS
participant Passerelle
participant InputDir
participant OutputDir
participant Logitud

==Initialisation==
WCS->Passerelle: Envoie de la demande
Passerelle->InputDir: Depot de la demande au format zip
Logitud->InputDir: Récuperation de la demande

==Traitement==
loop
activate Logitud
Logitud-->Logitud: Traitement demande et MAJ statut demande
Logitud->OutputDir: Dépot demande avec nouveau statut
deactivate Logitud
WCS->Passerelle: Vérification statut demande
Passerelle->OutputDir: Récupération statut de la demande
Passerelle->WCS: Remonté du statut de la demande

alt cloture demande
activate Logitud
Logitud-->Logitud: Cloture demande
Logitud->OutputDir: Dépot demande avec statut __clos__
deactivate Logitud
WCS->Passerelle: Vérification statut demande
Passerelle->OutputDir: Récupération statut de la demande
Passerelle->WCS: Remonté du statut de la demande
activate WCS
WCS->WCS: Cloture de la demande
[<-WCS
deactivate WCS
end
end


MDEL

http://telechargement.modernisation.gouv.fr/EspaceDocumentaireMSP/particuliers/demarches-en-ligne/index.html

Workflows

Appel Webservice de création de demande

Réponse du Webservice

{
    "data": {
        "demand_id": "15-9-AEC-LA" 
    },
    "err": 0

} 

demand_id représente l'identifiant de la demande dans Passerelle

logitud_create_response_data_demand_id

Appel Webservice de récupération de status d'une demande

{
  "data": 
    {
      "status": "accepted", 
      "comment": "Dossier trait\xe9.", 
      "closed": true
    },
  "err": 0
}

Soit logitud_status_response la réponse de l'appel ws récupérant le statut d'une demande. Pour vérifier qu'une demande est dans le statut :

Pour savoir si une demande est à la fois dans le statut désiré (acceptée, refusée, non recevable ...) et cloturée par exemple rejetée et cloturée

 logitud_status_response_data_status == 'rejected' and logitud_status_response_data_closed == True

On peut récupérer le commentaire lié au statut de la demande de la manière suivante :

 logitud_status_response_data_comment

Interne : voir aussi cette page

Formulaires

Inscription sur Liste Electorale

Acte d'Etat Civil

Recensement Citoyen Obligatoire


OpenGIS

OpenGIS n'est pas un logiciel mais un standard promu par l'Open Geospatial Consortium (https://fr.wikipedia.org/wiki/OpenGIS).
Conformes à ces standards, ont été développés des logiciels tel GeoServer (https://fr.wikipedia.org/wiki/GeoServer), qui est un serveur de données géographiques qui peut exposer

Dans le cadre de nos projets Publik, c'est essentiellement (uniquement ?) des échanges en lecture, nous utilisons donc des ressources disponibles dans GeoServer (https://docs.geoserver.org/latest/en/user/services/index.html), c'est le cas à Lyon ou Grenoble, ou dans des logiciels respectant ces protocoles, tel OpenDataSoft à Toulouse.


Ovh

Connecteur pour envoyer des SMS avec la plateforme d'OVH (télécom).
La documentation générale, également pour nos clients, pour paramétrer le connecteur est là : https://doc-publik.entrouvert.com/admin-fonctionnel/les-tutos/configuration-envoi-sms/
Notre documentation, interne, notamment pour gestion de la facturation est là : https://dev.entrouvert.org/projects/interne/wiki/Ajouter_un_compte_SMS_OVH


Le «connecteur» PDF

Ce connecteur est en fait une interface d'accès à un logiciel de traitement des fichiers PDF, pdftk : https://gitlab.com/pdftk-java/pdftk

Le logiciel pdftk est installé sur la même machine que Passerelle, et on peut l'appeler par webservice pour :

Assemblage de PDF

Le webservice « /assemble » reçoit un dictionnaire de cette forme :

{
  "filename": "output.pdf",
  "files/0": {
    "filename": "example-1.pdf",
    "content_type": "application/pdf",
    "content": "JVBERi0xL...(base64 PDF)..." 
  },
  "files/1": {
    "filename": "example-2.pdf",
    "content_type": "application/pdf",
    "content": "//4lUERGL...(base64 PDF)..." 
  },
  "files/2": ...
}

Il retourne en réponse un document PDF, assemblage de files/0 + files/1 + files/2 + ...

La traduction dans le workflow d'une démarche sera de faire une action webservice :

Remplissage de formulaire PDF (fill-form)

Le webservice « fill-form » permet de remplir les champs d'un fichier PDF de type « formulaire PDF » (acroform), par exemple tel que celui visible sur https://www.service-public.fr/particuliers/vosdroits/R1492 (cerfa 10072-02, Déclaration d'intention d'aliéner ou demande d'acquisition d'un bien soumis à un droit de préemption / formulaire 10072*02)

Le connecteur dispose du fichier PDF formulaire au niveau de sa configuration, dans « Fichier formulaire PDF »

Un bouton « Remplissage de formulaire: éditer les correspondances de champ » est accessible sur le connecteur, qui présente tous les champs disponibles dans une vue du fichier PDF. Pour chacun, il faut écrire un gabarit ou une condition, en Django. Les gabarits pour les champs textes, et les conditions pour les cases à cocher.

Ces gabarits et conditions vont recevoir toutes les données envoyées lors de l'appel au webservice « fill-form ».

Le webservice « fill-form » doit donc recevoir un dictionnaire JSON, lequel sera envoyé aux gabarits et conditions pour le calcul de chacun des champs à remplir. Le webservice peut donc éventuellement recevoir « toutes les données du formulaires » depuis une action appel webservice (case « Envoyer les données du formulaire »)

La traduction dans le workflow d'une démarche sera de faire une action webservice :

Note : le format du dictionnaire envoyé par la case à cocher « Envoyer les données du formulaire » est documenté sur https://doc-publik.entrouvert.com/dev/wcs/api-webservices/recuperation-des-donnees-d-un-formulaire/#mode-pull

Ajout de filigrane (watermark)

Le webservice « /watermark » reçoit un dictionnaire de cette forme :

{
  "filename": "output.pdf",
  "file": {
    "filename": "example-1.pdf",
    "content_type": "application/pdf",
    "content": "JVBERi0xL...(base64 PDF)..." 
  },
  "stamp": {
    "filename": "filigrane.pdf",
    "content_type": "application/pdf",
    "content": "//4lUERGL...(base64 PDF)..." 
  }
}

Il retourne en réponse un document PDF, qui est le fichier "file" avec en filigrane "stamp".

La traduction dans le workflow d'une démarche sera de faire une action webservice :

Le connecteur développé dans Passerelle permet d'exposer dans Publik des informations relatives à la réservation de salles, salles quant à elles gérées dans Planitech ; le connecteur ne prend pas en charge la gestion des ressources annexes aux salles, à ce jour.

Scénario fonctionnel

Le connecteur a été développé pour répondre au scénario suivant :

QRCode signés

Aussi :

Le principe

Le connecteur aura pour objectif de produire des QRcode contenant une donnée signée électroniquement (un certificat électronique), lié ou non via un identifiant unique à un enregistrement en base pour permettre de valider l'origine de la donnée et d'éventuellement l'augmenter. Cette partie sera appelé le backend. Le connecteur fournira aussi une application Web style one-page application permettant la lecture, la validation, le pointage et l'augmentation des donnés d'un QRcode. Cette partie aura pour nom le fronted et visera une utilisation sur tablette et smartphone, i.e. la compatibilité minimale visée est Chrome Android et Safari iOS.

Fonctionnalités du backend

Fonctionnalités du front

Cas d'usage

ZFE

ZFE = Zone à faible émission, les collectivités émettent des autorisations particulières par exemple pour des artisans ayant de vieux véhicule polluant. On créera un certificat avec la plaque d'immatriculation et le date limite de validité, on conservera en base nom/prénom/téléphone/adresse de la personne.

Un jeton unique de lecture sera transmis à la police municipale, le lien vers le frontend sera transforme en QRcode URL et transmis aux agents (par mail, courrier, whatever) ils n'auront qu'à le lire avec leur téléphone/tablette.

La police municipale sera à même de valider le certificat et si en ligne de lire les informations supplémentaires qui ne seront pas publiquement dans les QRcode.

Contrôle d'accès à un évènement

Pour chaque billet vendu on créera un certificat avec le numéro de la place, zone d'accès, etc.. Des jetons seront produits pour chaque agent de sécurité et un lien vers le frontend contenant ce jeton fournit sous forme de QRcode à lire par le smartphone de l'agent.

Chaque smartphone à la validation d'un QRcode remontera l'évènement de pointage au backend, évènement qui redescendra dans les autres smartphones pout empêcher le double pointage.

Choix techniques

Modèle de donnée du connecteur

skinparam linetype ortho
skinparam class {
  BackgroundColor<<bloc de champs>> PaleGreen
  BackgroundColor<<workflow>> Red
}

title Modèle de donnée connecteur QRcode

ressource "1" -- "*" certificat
ressource "1" -- "*" lecteur
certificat "1" -- "*" "évènement"
"évènement" "*" -- "1" lecteur 

Class ressource {
  cles : list of nacl keys
}

Class certificat {
  guid : uuid
  not_after : datetime or null
  not_before : datetime or null
  data : json
  metadata : json
}

Class lecteur {
  guid : uuid
  not_after : datetime or null
  not_before : datetime or null
  metadata : json -- {'identifier': 'john.doe@example.com' or 'tel:00336343434' or 'Évènement X - Agent de sécurité 1'},
  pointage : bool
  metadata_access : list of metadata keys
}

Class "évènement" {
  date : datetime
  type : string -- "vu"
  lecteur : lecteur
  certificat : certificat
}

Prototype

Backend en ligne de commande limité à produire les QRcodes signés, frontend qui ne fait que lire.

https://git.entrouvert.org/entrouvert/misc-bdauvergne/src/branch/main/qrcode-certificate/v1

Plan développement :

Pour le 17 Novembre en recette, implémenter le cas d'usage "ZFE". i.e création d'un connecteur "qrcode" avec les endpoints suivants :

Le calendrier & les spécifications précises pour le pointage viendront après.


SOLIS

APA

Périmètre fonctionnel du connecteur

Endpoints

RSA

Périmètre fonctionnel du connecteur

Endpoints


https://doc-publik.entrouvert.com/admin-fonctionnel/parametrage-avance/json-data-store/


Technocarte


Vivaticket

cf la page dédiée sur le wiki de Nancy : https://dev.entrouvert.org/projects/nancy/wiki/Vivaticket


Passerelle

Les connecteurs

Les connecteurs

Notes techniques

Pour commencer

git clone http://repos.entrouvert.org/passerelle.git
cd passerelle
virtualenv venv
. venv/bin/activate
pip install -r requirements.txt
./manage.py syncdb
./manage.py runserver

Documentation développeurs