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 ?
Source : (cf. https://www.associations.gouv.fr/l-api-association.html). Disponibilité du connecteur pour utilisation de ces données dans Publik : novembre 2018.
cf. https://traitement-demarches.arles.fr/association/j-adhere-a-la-maison-de-la-vie-associative-mdva/
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.
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
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.
Récupérer les informations de l’association.
Récupérer un document de l’association.
Récupérer le plus récent document de l’association du type donné.
Récupérer les documents de l’association.
Récupérer les effectifs annuels d’une entreprise.
Récupérer les effectifs mensuels d’une entreprise.
Récupérer les informations de l’entreprise.
Récupérer les effectifs mensuels d’un établissement.
Récupérer les informations de l’établissement.
Récupérer les informations financières sur l’établissement (exercices).
Récupérer les données de l’entreprise (extrait RCS) auprès d’Infogreffe.
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.
Une API dans le style "REST" (GET/POST sur différentes URLs structurées) utilisant le format d'échange JSON.
Un seul mode d'authentification est supporté: HTTP Basic (https://fr.wikipedia.org/wiki/Authentification_HTTP#M%C3%A9thode_%C2%AB_Basic_%C2%BB)
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 |
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.
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>
La liaison a été créée ou elle existait déjà.
200 Ok Content-Type: application/json {"err": 0}
La liaison ne peut-être créée.
200 Ok Content-Type: application/json
{"err": 0, "err_desc": "identifiants inconnus"}
GET /links?NameID=<nameid> HTTP/1.1
200 Ok Content-Type: application/json
{
"err": 0,
"data": {
"links": [
"identifiant-débiteur-1",
"identifiant-débiteur-2",
]
}
}
404 Not found
{"err": 1, "err_desc": "aucune liaison"}
API via un POST sans contenu.
POST /unlink?NameID=<nameid> HTTP/1.1 <pas de contenu>
200 Ok Content-Type: application/json
{"err": 0}
Aucun retour non passant n'est possible, toutes les liaisons depuis le NameID précisé devront être supprimées.
GET /<base_path>/invoices/?NameID=<nameid> HTTP/1.1 Host: <base_host>
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
}
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 |
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"
}
GET /<base_path>/invoices/history/?NameID=<nameid> Host: <base_host>
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
}
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 |
GET /<base_path>/users/with-pending-invoices/ HTTP/1.1 Host: <base_host>
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": [{ ... }, ... ]}
}
}
}
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 |
GET /<base_path>/invoices/<identifiant_facture>/ HTTP/1.1 Host: <base_host>
<identifiant_facture>
: l'identifiant métier de la facture retourné dans le champ id
des APIs de listing
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
}
GET /<base_path>/invoice/<identifiant_facture>/pdf/ HTTP/1.1 Host: <base_host>
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 ....
Tout code non 200 ou dont le content-type n'est pas "application/pdf".
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"
}
Le paiement a bien été pris en compte.
200 Ok Content-Type: application/json
{
"err": 0
}
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
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
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.
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 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
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.
L'objectif du connecteur est de pouvoir créer une demande de travaux dans ATAL et de pouvoir en suivre l'évolution.
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.
Via le endpoint retrieve-etat-travaux.
On a possibilité d'enrichir une demande de travaux de :
Interne : voir aussi cette page
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.
Le paramétrage doit indiquer :
44
pour récupérer l'ensemble des adresses du département de Loire Atlantique44000,44100,44200, 44300
pour récupérer les adresses de la ville de Nantes44190
pour récupérer les rues de la commune de Clisson/addresses/
Retourne les adresses correspondant aux paramètres passés.
Retourne les villes correspondant aux paramètres passés.
Retourne les départements correspondant aux paramètres passés.
Retourne les régions correspondant aux paramètres passés.
Retourne l'adresse correspondant à la latitude et la longitude passées en paramètre.
Retourne la latitude, la longitude et l'adresse normalisée correspondant à la recherche passée en paramètre.
Retourne les rues correspondant au code postal passé en paramètre.
Document généralement obsolète.
Interro d'une sources de données
Modèle de base BaseDataSource : title, slug, description. Renvoie juste une exception NonImplementedError...
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.
Peut-être un modèle à ajouter : CacheDataSource avec un timeout en secondes, qui servirait de base à DistantCsvDataSource et autres.
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.
POST /post/<slug>/json[?...] <objet JSON> ou null
Retour :
{ data: ..., err: 0 }
Abonnement à une ressource.
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 }
Permet l'envoi d'un message à une cible (SMS, mail, ...)
Envoi :
POST /message/<slug>/ HTTP/1.0 { message: '...', from: '...', to: ['...', '...', ...] }
Retour :
{ data: { message: '4 message envoyés', }, err: 0 }
- origine / nom
- clé
- type de clé : apikey ou clé de signature portail-citoyen (hmac)
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.
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 :
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}}.
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.
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 |
Le connecteurs vient avec les sources de données ci dessous :
{"data": [{"text": "Monsieur", "id": "M"}, {"text": "Madame", "id": "Mme"}, {"text": "Mademoiselle", "id": "Mlle"}], "err": 0}
{"data": [{"text": "Homme", "id": "M"}, {"text": "Femme", "id": "F"}, {"text": "Autre", "id": "NA"}], "err": 0}
{"data": [{"text": "Internet", "id": "internet"}, {"text": "Guichet", "id": "guichet"}, {"text": "Courrier", "id": "courrier"}], "err": 0}
{"data": [{"text": "Reconnu", "id": "reconnu"}, {"text": "Auteur", "id": "auteur"}], "err": 0}
{"data": [{"text": "Naissance", "id": "NAI"}, {"text": "Mariage", "id": "MAR"}, {"text": "Décès", "id": "DEC"}], "err": 0}
{"data": [{"text": "Copie intégrale", "id": "CPI"}, {"text": "Extrait avec filiation", "id": "EXTAF"}, {"text": "Extrait sans filiation", "id": "EXTSF"}, {"text": "Extrait plurilingue", "id": "EXTPL"}], "err": 0}
host recette: passerelle.test.entrouvert.org
# rsync <host>:cityweb/*.zip <chemin_repertoire_local>
Connecteur générique pour la norme CMIS. Permet d'envoyer des fichiers vers une GED.
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 :{{passerelle_url}}cmis/ged-chezwam/uploadfile
{{ form_var_fichier_raw }}
(_raw pour obtenir le fichier et pas uniquement son nom)/GED/GRC
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)
Avec Alfresco, si les appels échouent en 401, vérifier coté Alfresco que alfresco.restApi.basicAuthScheme
est à true
(#51130#note-7)
~~
~~
~~
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 :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 |
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 |
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 |
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 |
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 |
/<connector>/<slug>/create/
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" } }
Dans le cas où le connecteur peut le permettre, l'URL de récupération du statut d'une demande sera comme suit :
/<connector>/<slug>/status/<demand_id>/
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" } }
/<connector>/<slug>/datasources/application-reasons/
{ "err" : 0, "data" : [ { "id" : "id-card", "text" : "Carte nationale d'identité" }, { "id" : "passport", "text" : "Passeport" }, { "id" : "citizenship-certificate", "text" : "Certificat de nationalité française" }, { "id" : "mariage", "text" : "Mariage" }, { "text" : "Pension", "id" : "pension" }, { "text" : "Procédure judiciaire", "id" : "judiciary" }, { "id" : "pacs", "text" : "Pacte civil de solidarité" }, { "id" : "notary-act", "text" : "Acte notaire" }, { "id" : "other", "text" : "Autre" } ] }
/<connector>/<slug>/datasources/applicant-status/
{ "data" : [ { "text" : "Son fils ou sa fille", "id" : "child" }, { "id" : "concerned", "text" : "La personne concernée par l'acte" }, { "text" : "Son grand-père ou sa grand-mère", "id" : "grand-parent" }, { "id" : "heir", "text" : "Son héritier" }, { "id" : "parent", "text" : "Son père ou sa mère" }, { "text" : "Son conjoint ou sa conjointe", "id" : "partner" }, { "id" : "grand-child", "text" : "Son petit-fils ou sa petite-fille" }, { "text" : "Son représentant légal", "id" : "representative" }, { "text" : "Autre", "id" : "other" } ], "err" : 0 }
{ "err" : 0, "data" : [ { "text" : "Naissance", "id" : "birth" }, { "text" : "Mariage", "id" : "mariage" }, { "id" : "death", "text" : "Décès" } ] }
{ "err" : 0, "data" : [ { "id" : "full", "text" : "Copie intégrale" }, { "id" : "with-filiation", "text" : "Extrait avec filiation" }, { "text" : "Extrait sans filiation", "id" : "without-filiation" }, { "id" : "multilingual", "text" : "Extrait plurilingue" } ] }
{ "data" : [ { "text" : "Monsieur", "id" : "mr" }, { "text" : "Madame", "id" : "ms" }, { "text" : "Autre", "id" : "mx" } ], "err" : 0 }
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.
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.
/family/link/?NameID=...&login=...&password=...
Le lien entre la famille est le NameID du citoyen est stocké du côté du connecteur.
Aucune valeur de retour n'est attendue.
/family/unlink/?NameID=...
Pas de valeur de retour attendue.
Une famille:
/family/?NameID=...
{ "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:
/family/adults/?NameID=...
, renvoie uniquement la liste des adultes:{ "data": [ { "id": "50107", "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", "post_code": "94120", "phone": "1122334455", "cellphone": "1122334455", "email": "foo@bar.org" ... (autres informations si le logiciel backend en donne) }, { ... } ], "err": 0 }
/family/children/?NameID=...
renvoie uniquement la liste des enfants:{ "data": [ { "id": "18177", "text": "Kevin McCallister", "first_name": "Kevin", "last_name": "McCallister", "birthdate": "24/09/1994", "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 }
Documentation existante dans la documentation Publik :
https://doc-publik.entrouvert.com/admin-fonctionnel/parametrage-avance/source-de-donnees-csv/
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.).
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
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.
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
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',)
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".
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/
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
}
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
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'}
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.
À 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.
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
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
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 .
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 =====================================
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 |
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 |
{ 'firstname': 'foo' 'lastname': 'bar', 'filenumber': '123456789' 'badgenumber': '123456789' 'cardnumber': '123456789' }
{ "err": 0 }
{ "err": 1, "code": "unknown-file", "msg": "Dossier inconnu" }
code
est un code intelligible simplifiémsg
est le message exact retourné par DPark si disponible, ou en cas d'erreur autre le code et le messageLa 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 |
Avec nameid
étant form_user_name_identifier_0
{ "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
{ "data": null, "err": 1, "err_desc": "Dossier inconnu" }
{ 'nameid': 'abcdefg' 'firstname': 'foo' 'lastname': 'bar', 'filenumber': '123456789' 'badgenumber': '123456789' 'cardnumber': '123456789' }
{ "err": 0 }
{ "err": 1, "code": "unknown-file", "msg": "Dossier inconnu" }
code
est un code intelligible simplifiémsg
est le message exact retourné par DPark si disponible, ou en cas d'erreur autre le code et le messageLa 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 |
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.
{ "data": True, "err": 0 }
{ "data": null, "err": 1, "err_desc": "No pairing exists" # exemple de description d'erreur }
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" }
identifiant | text |
---|---|
1 | Vide |
2 | BIS |
3 | TER |
4 | QUATER |
{ "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, }
{ "data": False, "desc": "Erreur extension" }
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 |
{ "data": True, "err": 0 }
{ "data": null, "err": 1, "err_desc": "Renouvellement hors délai" }
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é |
{ "data": True, "desc": "<message retour de D-PARK>", "err": 0 }
{ "data": False, "desc": "<message retour de D-PARK>", "err": 0 }
{ "err": 1, "err_desc": "<erreur d'utilisation du web-service>", }
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 |
{ "data": True, "desc": "<message retour de D-PARK>", "err": 0 }
{ "data": False, "desc": "<message retour de D-PARK>", "err": 0 }
{ "err": 1, "err_desc": "<erreur d'utilisation du web-service>", }
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 |
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 |
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 |
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 |
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 }
{ "data": { "numerodossier": "22334", "numerodemande": "59492" }, "err": 0 }
{ "err": 1, "err_desc": "Dossier incomplet" }
Il est possible de filtrer les données remontées par numero de dossier
.
GET /dpark/<slug>/payment-info/<nameid>/?filenumber=123456
{ "data": [ { "typepaiement_text": "Carte Bancaire via Internet", "numerodemande": 61718, "montant": 135, "numeroteledossierphase1": "E-8-N5UTAK6P", "typepaiement": 10 } ], "err": 0 }
{ "data": [], "err": 0 }
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' }
{ "data": True, "err": 0 }
{ "err_class": "passerelle.utils.jsonresponse.APIError", "err_desc": "Deja paye", "data": null, "err": 1 }
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 |
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 |
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" } }
{ "data": { "result": True, }, "err": 0 }
{ "data": null, "err": 1, "err_desc": "Numéro de demande introuvable" }
Les paquets Debian pour Passerelle fonctionnent sur Debian 7.x avec les sources backports activées (lire http://backports.debian.org/Instructions/)
# apt-get install -t wheezy-backports python-django
# apt-get install -t wheezy-eobuilder passerelle
postgres$ createuser passerelle postgres$ createdb -O passerelle passerelle
Modèle dans /usr/share/doc/passerelle/nginx-example.conf
à copier dans /etc/nginx/sites-available
puis éditer, puis restart de nginx.
(obsolète, supprimé)
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.
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.
Injection dans Littéralis :
Suivi :
Donnée de traitement « identifiant demande littéralis » pour stocker l’id_demande retournée par l’appel à /demandes-recues
Retourne « idDemande » et « status » (avec la valeur « A_TRAITER »).
Optionnel ; un PDF récapitulant la demande.
Optionnel ; documents annexes à la demande (transmis par l’usager).
Note : le workflow modèle n’intègre pas cet appel.
id_demande à passer en paramètre d’url.
Les codes suivants sont possibles :Bien que ce endpoint soit exposé, il n'est pas fonctionnel. Cela peut faire l'objet d'un développement complémentaire.
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.
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
{
"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 :
logitud_status_response_data_closed == True
logitud_status_response_data_imported == 'imported'
logitud_status_response_data_status == 'invalid'
logitud_status_response_data_status == 'in progress'
logitud_status_response_data_status == 'information needed'
logitud_status_response_data_status == 'accepted'
logitud_status_response_data_status == 'rejected'
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
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.
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
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 :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 :filename
et un files/0
:
filename
: un gabarit représentant le nom du fichier attendu en retourfiles/0
: un gabarit représentant un champ fichier, par exemple {{ form_var_premier_fichier }}files/1
: un gabarit représentant un champ fichier, par exemple {{ form_var_second_fichier }}files/n
: un gabarit représentant un champ fichier, par exemple {{ form_var_nieme_fichier }}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 :filename
, gabarit représentant le nom du fichier attendu en retourNote : 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
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 :filename
, un file
et un stamp
:
filename
: un gabarit représentant le nom du fichier attendu en retourfile
: un gabarit représentant un champ fichier, par exemple {{ form_var_fichier }}stamp
: un gabarit représentant un champ fichier, par exemple {{ form_var_filigrane }}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.
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.
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.
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.
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
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.
→ https://doc-publik.entrouvert.com/admin-fonctionnel/parametrage-avance/json-data-store/
cf la page dédiée sur le wiki de Nancy : https://dev.entrouvert.org/projects/nancy/wiki/Vivaticket
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