Aller au contenu principal

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
statusLe statut HTTP de la réponse du service
oktrue pour 200–299 : le cas courant tient ainsi en une propriété plutôt qu’en un calcul
bodyLe contenu de la réponse, sous forme de texte
truncatedtrue 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​

  1. 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.
  2. 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.
  3. Définissez la valeur dans cet environnement — le point de terminaison, une adresse absolue en http:// ou https://.
  4. Écrivez l’étape. Dans votre étape de plug-in ou votre API personnalisée, appelez callService avec 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 :

AppelPhasePourquoi
Encaisser un paiement, réserver du stock dans un autre systèmePreOperationIl 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èmePostOperationL’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 402 d’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 dans answer.status et 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 messageCe que c’est
toLe destinataire. Une adresse, plusieurs séparées par des virgules ou des points-virgules, ou une liste
ccQui reçoit une copie, de la même façon. Facultatif
replyToOù va une réponse, pour qu’un client réponde à la personne qui a écrit plutôt qu’à une adresse no-reply. Facultatif
subjectLa ligne d’objet
bodyLe contenu
htmltrue 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​