Appeler un service externe depuis un script
Objectif
Faire appeler par un script côté serveur quelque chose d’extérieur à la plateforme — encaisser un paiement, signaler à un autre système qu’un enregistrement a changé, envoyer un e-mail à quelqu’un — et faire en sorte que l’adresse appelée soit un paramètre contrôlé par un administrateur plutôt qu’une ligne de votre script.
Les deux fonctions
Toutes deux sont disponibles dans une étape de plug-in serveur et dans une API personnalisée.
var answer = callService('par_payment_service', '{"reference":"ORD-1","amount":25}');
var sent = sendEmail('par_mail_service', { to: 'buyer@example.test', subject: 'Your order is paid', body: 'Thank you.' });
Le corps peut être du texte, comme ci-dessus, ou un objet ou une liste, envoyé en JSON : callService('par_payment_service', { reference: 'ORD-1', amount: 25 }) envoie la même chose.
callService renvoie un objet :
| Propriété | Ce que c’est |
|---|---|
status | Le statut HTTP de la réponse du service |
ok | true pour 200–299 : le cas courant tient ainsi en une propriété plutôt qu’en un calcul |
body | Le contenu de la réponse, sous forme de texte |
truncated | true si la réponse était trop volumineuse pour être lue en entier |
Le premier argument est un nom de service, pas une adresse
C’est la partie qui surprend, et c’est toute la conception.
'par_payment_service' est le nom logique d’une variable d’environnement. Vous la déclarez
dans votre solution ; un administrateur en définit la valeur — le point de terminaison — dans
chaque environnement. Ainsi :
- votre script dit ce qu’il appelle, jamais où ;
- Dev pointe vers un bac à sable et Production vers le vrai prestataire, sans aucune modification de la solution ;
- un environnement qui n’a rien configuré n’atteint rien.
Il n’existe délibérément aucune fonction qui prenne une URL. Une telle fonction permettrait à n’importe quel script de n’importe quel locataire d’ouvrir une connexion vers n’importe où, et aucune relecture des solutions après coup ne pourrait revenir là-dessus.
Mise en place
- Déclarez le service. Dans le Centre de contrôle d’administration, ouvrez Variables
d’environnement et créez-en une —
par_payment_service, de type Texte. Donnez-lui une description qui dit à quoi elle sert ; la personne qui la définira en Production n’est peut-être pas vous. - Ajoutez-la à votre solution, pour qu’elle voyage. La déclaration d’une variable voyage ; sa valeur, non — c’est ce qui tient les paramètres de Dev à l’écart de la Production.
- Définissez la valeur dans cet environnement — le point de terminaison, une adresse absolue
en
http://ouhttps://. - Écrivez l’étape. Dans votre étape de plug-in ou votre API personnalisée, appelez
callServiceavec ce nom.
De quel côté de l’enregistrement appeler
Une étape de plug-in serveur s’exécute soit avant l’écriture de l’enregistrement, soit après, et les appels sortants se placent d’un côté ou de l’autre selon leur nature :
| Appel | Phase | Pourquoi |
|---|---|---|
| Encaisser un paiement, réserver du stock dans un autre système | PreOperation | Il a lieu dans la transaction de l’enregistrement : si l’enregistrement échoue ensuite, rien ne reste à prétendre que l’argent a été encaissé |
| Envoyer une confirmation, notifier un autre système | PostOperation | L’enregistrement existe déjà : une panne du service de messagerie retarde un message au lieu d’annuler l’enregistrement |
Un appel avant l’enregistrement dispose de dix secondes. Il maintient l’enregistrement ouvert pendant son attente, et une personne regarde un indicateur de chargement. Si le service appelé a besoin de plus de temps, rendez l’étape asynchrone — elle s’exécute alors après l’enregistrement, de manière autonome, et peut prendre tout le temps nécessaire.
Ce qui compte comme un échec
La distinction mérite d’être apprise une fois pour toutes, car elle détermine quelle part de votre script vous devez écrire :
- Un statut choisi par le service est une réponse. Un
402d’un prestataire de paiement signifie que la carte a été refusée — un résultat ordinaire sur lequel vous statuez. Votre script le reçoit dansanswer.statuset continue. - L’absence de réponse est un échec, et elle arrête l’étape d’elle-même : service inexistant, aucun point de terminaison défini dans cet environnement, point de terminaison qui n’est pas une adresse web, ou service qui n’a jamais répondu. Un script ne peut rien y faire, et continuer reviendrait à agir comme si l’intégration avait eu lieu.
La plupart des étapes ont donc cette forme :
var answer = callService('par_payment_service', body);
if (answer.ok) {
setValue('par_payment_reference', answer.body);
} else {
throwValidationError(`The payment service refused this order (${answer.status}).`);
}
Envoyer un e-mail
sendEmail prend le nom du service et un message, et le transmet à ce service. Le format du
message est celui de la plateforme : un déploiement configure donc un seul adaptateur de
messagerie, et non un par script qui envoie un jour un message.
| Dans le message | Ce que c’est |
|---|---|
to | Le destinataire. Une adresse, plusieurs séparées par des virgules ou des points-virgules, ou une liste |
cc | Qui reçoit une copie, de la même façon. Facultatif |
replyTo | Où va une réponse, pour qu’un client réponde à la personne qui a écrit plutôt qu’à une adresse no-reply. Facultatif |
subject | La ligne d’objet |
body | Le contenu |
html | true si le corps est en HTML. Facultatif ; texte brut sinon |
sendEmail n’arrête jamais votre script. Il renvoie { ok, error }. Lorsque l’e-mail n’est
pas parti — parce que personne n’a configuré de service de messagerie ici, que l’adresse a été
refusée ou que le service était indisponible — ok vaut false et error explique pourquoi, en
des termes qui indiquent qui peut y remédier. Un script peut ainsi consigner l’échec et réessayer
plus tard, et c’est de cette façon que Parsware Sales marque un e-mail comme Échec. Si
l’enregistrement doit plutôt s’arrêter, dites-le :
if (!sent.ok) { throwValidationError(sent.error); }
Un script écrit auparavant passait quatre arguments (sendEmail(service, to, subject, body)). Il
doit adopter la forme de message ci-dessus.
La plateforme ne parle pas SMTP. Elle envoie une requête à ce que nomme l’environnement, ce que propose chaque fournisseur de messagerie ; un déploiement dont le seul chemin est un relais SMTP place un petit point de terminaison HTTP devant celui-ci.
Essayer
Importez la solution d’exemple business-rules-outbound-calls. Elle contient une table
Commandes, deux services déclarés comme variables d’environnement sans aucune valeur, et deux
étapes — l’une qui encaisse le paiement avant l’enregistrement, l’autre qui envoie la confirmation
par e-mail après. Son README explique comment faire pointer les services vers un point de
terminaison qui répond 200, puis vers un autre qui répond 402, et observer l’enregistrement
refusé sans que rien ne soit stocké.
Voir aussi
- Écrire un fichier dans le stockage depuis un script — l’autre chose qu’un script peut atteindre en dehors de la base de données.
- Publier une API personnalisée — le contrat par lequel un système externe vous appelle.