Llamar a un servicio externo desde un script
Objetivo
Hacer que un script del servidor llame a algo externo a la plataforma (cobrar un pago, avisar a otro sistema de que ha cambiado un registro, enviar un correo electrónico a alguien) y que la dirección a la que llama sea un ajuste que controla un administrador, no una línea de su script.
Las dos funciones
Ambas están disponibles en un paso de complemento de servidor y en una API personalizada.
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.' });
El cuerpo puede ser texto, como arriba, o un objeto o una lista, que se envía como JSON: callService('par_payment_service', { reference: 'ORD-1', amount: 25 }) envía lo mismo.
callService devuelve un objeto:
| Propiedad | Qué es |
|---|---|
status | El estado HTTP con el que respondió el servicio |
ok | true para 200–299, así que el caso habitual es una propiedad en lugar de una operación aritmética |
body | Lo que respondió, como texto |
truncated | true si la respuesta era demasiado grande para leerla entera |
El primer argumento es el nombre de un servicio, no una dirección
Esta es la parte que sorprende a la gente, y es todo el diseño.
'par_payment_service' es el nombre lógico de una variable de entorno. Usted la declara en
su solución; un administrador establece su valor (el punto de conexión) en cada entorno. Así:
- su script dice a qué llama, nunca dónde;
- Desarrollo apunta a un entorno de pruebas y Producción al proveedor real, sin ningún cambio en la solución;
- un entorno que no ha configurado nada no llega a ninguna parte.
Deliberadamente, no hay ninguna función que reciba una URL. Una función así permitiría que cualquier script de cualquier inquilino abriera una conexión a cualquier sitio, y ninguna revisión posterior de las soluciones podría deshacerlo.
Configurarlo
- Declare el servicio. En el Centro de control de administración, abra Variables de
entorno y cree una:
par_payment_service, de tipo Texto. Dele una descripción que diga para qué sirve; puede que quien la establezca en Producción no sea usted. - Agréguela a su solución, para que viaje. La declaración de una variable viaja; su valor no, y eso es lo que mantiene los ajustes de Desarrollo fuera de Producción.
- Establezca el valor en este entorno: el punto de conexión, una dirección absoluta
http://ohttps://. - Escriba el paso. En su paso de complemento o su API personalizada, llame a
callServicecon ese nombre.
Desde qué lado del guardado llamar
Un paso de complemento de servidor se ejecuta antes o después de escribir el registro, y las llamadas salientes van en un lado u otro según lo que sean:
| Llamada | Fase | Por qué |
|---|---|---|
| Cobrar un pago, reservar existencias en otro sistema | PreOperation | Ocurre dentro de la transacción del guardado, así que si después el registro no se guarda, no queda nada que afirme que se cobró ese dinero |
| Enviar una confirmación, avisar a otro sistema | PostOperation | Para entonces el registro ya existe, así que si el servicio de correo está caído se retrasa un mensaje en lugar de deshacerse el registro |
Una llamada antes del guardado tiene diez segundos. Mantiene el guardado abierto mientras espera, y hay una persona mirando un indicador de carga. Si el servicio al que llama necesita más tiempo, haga el paso asíncrono: entonces se ejecuta después del guardado, por su cuenta, y puede tardar lo que necesite.
Qué se considera un error
Merece la pena aprender la distinción una vez, porque decide cuánto de su script tiene que escribir:
- Un estado que eligió el servicio es una respuesta. El
402de un proveedor de pagos significa que se rechazó la tarjeta: un resultado normal sobre el que usted decide. Su script lo recibe enanswer.statusy continúa. - La ausencia de respuesta es un error, y detiene el paso por sí sola: no existe ese servicio, no hay un punto de conexión establecido en este entorno, el punto de conexión no es una dirección web o el servicio nunca respondió. Un script no puede hacer nada con ninguno de esos casos, y continuar significaría actuar como si se hubiera integrado con algo.
Así que la forma de la mayoría de los pasos es:
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}).`);
}
Enviar correo electrónico
sendEmail recibe el nombre del servicio y un mensaje, y lo envía a ese servicio. El mensaje
tiene el formato de la plataforma, así que una implementación configura un adaptador de correo
en lugar de uno por cada script que envíe un mensaje.
| En el mensaje | Qué es |
|---|---|
to | A quién va dirigido. Una dirección, varias separadas por comas o puntos y comas, o una lista |
cc | Quién recibe una copia, de la misma manera. Opcional |
replyTo | Adónde va una respuesta, para que un cliente responda a la persona que escribió y no a una dirección de no responder. Opcional |
subject | La línea de asunto |
body | Lo que dice |
html | true si el cuerpo es HTML. Opcional; si no, texto sin formato |
sendEmail nunca detiene su script. Devuelve { ok, error }. Cuando el correo no se envió
(porque nadie configuró aquí un servicio de correo, se rechazó la dirección o el servicio de
correo estaba caído), ok es false y error explica por qué, con palabras que indican quién
puede solucionarlo. Eso permite que un script registre el error y lo vuelva a intentar más tarde,
que es como Parsware Sales marca un correo como Error. Cuando lo que debe ocurrir es que se
detenga el guardado, dígalo:
if (!sent.ok) { throwValidationError(sent.error); }
Un script escrito antes de este cambio pasaba cuatro argumentos
(sendEmail(service, to, subject, body)). Necesita la forma con mensaje de arriba.
La plataforma no habla SMTP. Envía los datos a lo que nombre el entorno, algo que ofrecen todos los proveedores de correo; una implementación cuya única vía sea un relé SMTP pone delante un pequeño punto de conexión HTTP.
Pruébelo
Importe la solución de ejemplo business-rules-outbound-calls. Tiene una tabla de pedidos,
dos servicios declarados como variables de entorno sin ningún valor establecido y dos pasos: uno
que cobra el pago antes del guardado y otro que envía por correo la confirmación después. Su
README explica cómo apuntar los servicios a un punto de conexión que responde 200, después a uno
que responde 402, y ver cómo se rechaza el guardado sin que se guarde nada.
Consulte también
- Escribir un archivo en el almacenamiento desde un script: la otra cosa fuera de la base de datos a la que puede llegar un script.
- Publicar una API personalizada: el contrato a través del cual un sistema externo le llama a usted.