Saltar al contenido principal

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:

PropiedadQué es
statusEl estado HTTP con el que respondió el servicio
oktrue para 200–299, así que el caso habitual es una propiedad en lugar de una operación aritmética
bodyLo que respondió, como texto
truncatedtrue 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​

  1. 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.
  2. 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.
  3. Establezca el valor en este entorno: el punto de conexión, una dirección absoluta http:// o https://.
  4. Escriba el paso. En su paso de complemento o su API personalizada, llame a callService con 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:

LlamadaFasePor qué
Cobrar un pago, reservar existencias en otro sistemaPreOperationOcurre 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 sistemaPostOperationPara 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 402 de un proveedor de pagos significa que se rechazó la tarjeta: un resultado normal sobre el que usted decide. Su script lo recibe en answer.status y 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 mensajeQué es
toA quién va dirigido. Una dirección, varias separadas por comas o puntos y comas, o una lista
ccQuién recibe una copia, de la misma manera. Opcional
replyToAdónde va una respuesta, para que un cliente responda a la persona que escribió y no a una dirección de no responder. Opcional
subjectLa línea de asunto
bodyLo que dice
htmltrue 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​