Cómo funcionan las devoluciones de llamadas asíncronas de Servicios externos
Las operaciones asíncronas de Servicios externos se describen en una especificación compatible de OpenAPI 3.x con una operación de devolución de llamada. El sistema registra las operaciones asíncronas como un tipo especial de acción invocable que permite tener tiempos de respuesta más largos. En contraste, las operaciones síncronas de Servicios externos agotan el tiempo de espera después de 120 segundos. Con las operaciones asíncronas, utiliza Apex para definir la devolución de llamada y el tiempo de espera para la respuesta asíncrona demorada.
Ediciones necesarias
| Disponible en: Lightning Experience |
| Disponible en: Enterprise Edition, Performance Edition, Unlimited Edition y Developer Edition |
Especificación de API de ejemplo con operación de devolución de llamada
Esta especificación de API de ejemplo presenta una operación de devolución de llamada dentro de un proceso de solicitud de hipoteca para la compañía ficticia "Acme Mortgages". Las definiciones relacionadas con las llamadas están en negrita. Volveremos a este ejemplo en otros temas de esta sección.
{
"openapi": "3.0.0",
"servers": [{
"url": "/"
}],
"info": {
"version": "1.0",
"title": "Acme Mortgages",
"description": "Acme Mortgages"
},
"paths": {
"/applications": {
"post": {
"operationId": "SubmitApplication",
"description": "Submit a new mortgage application",
"parameters": [{
"name": "callbackUrlForErrorCases",
"in": "query",
"schema": {
"type": "string"
}
}],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"applicant": {
"$ref": "#/components/schemas/Contact"
},
"callbackUrlForOutcomes": {
"type": "object",
"properties": {
"approved": {
"type": "string"
},
"rejected": {
"type": "string"
}
}
}
}
}
}
}
},
"responses": {
"201": {
"description": "Mortgage loan application submission initial response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"applicationNumber": {
"type": "string"
}
}
}
}
}
}
},
"callbacks": {
"applicationOutcomeApproved": {
"$ref": "#/components/callbacks/ApplicationApproved"
},
"applicationOutcomeRejected": {
"$ref": "#/components/callbacks/ApplicationRejected"
},
"applicationError": {
"{$request.query.callbackUrlForErrorCases}": {
"post": {
"parameters": [{
"in": "header",
"name": "applicationNumber",
"schema": {
"type": "string"
}
}],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MortgageApplicationError"
}
}
}
},
"responses": {
"200": {
"description": "Mortgage application callback error accepted"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"MortgageApplication": {
"required": [
"applicationNumber",
"status"
],
"properties": {
"applicationNumber": {
"type": "string"
},
"status": {
"description": "One of pending, approved, rejected",
"type": "string"
},
"approvedAmount": {
"type": "number"
}
}
},
"Contact": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"address": {
"type": "string"
}
}
},
"MortgageApplicationError": {
"properties": {
"errorMessage": {
"type": "string"
},
"applicationNumber": {
"type": "string"
}
}
}
},
"callbacks": {
"ApplicationApproved": {
"{$request.body#/callbackUrlForOutcomes/approved}": {
"post": {
"description": "Application has been approved.",
"operationId": "approvedCallback",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MortgageApplication"
}
}
}
},
"responses": {
"200": {
"description": "Approved application callback result has been retrieved successfully."
}
}
}
}
},
"ApplicationRejected": {
"{$request.body#/callbackUrlForOutcomes/rejected}": {
"post": {
"description": "Application is rejected",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MortgageApplicationError"
}
}
}
},
"responses": {
"200": {
"description": "Rejected application callback result has been retrieved successfully."
}
}
}
}
}
}
}
}
Interfaz de Apex de ejemplo con operaciones asíncronas
Cuando se registra, el servicio externo AcmeMortgages se muestra automáticamente en Apex por Servicios externos. La interfaz Apex para AcmeMortgages aparece en la página Clases Apex en Configuración como se muestra aquí. El contenido adicional que define las operaciones asíncronas está en negrita. No se muestran los objetos de Apex dinámicos que representan tipos de datos de objeto de esquema iguales que las acciones invocables.
Cada devolución de llamada está propiedad de su operación asíncrona principal. Una URL de devolución de llamada única de solo lectura es determinada por Salesforce (en la primera llamada).
global class AcmeMortgages {
// Acme Mortgages SubmitApplication asynchronous operation
global SubmitApplication_Response SubmitApplication(
SubmitApplication_Request input,
SubmitApplication_Callback callback,
DateTime callbackTimeout
) {...}
global class SubmitApplication_Request {
global AcmeMortgages_SubmitApplication_IN_body body {get; set;}
// [REQUEST] Callback URL for asynchronous operation: callbackUrlForErrorCases
global String callbackUrlForErrorCases {get;}
}
// Synchronous response - here getting the application docket number
global class SubmitApplication_Response {
global Integer responseCode {get; set;}
global AcmeMortgages_SubmitApplication_OUT_201 Code201 {get; set;}
// Get invocation ID for this asynchronous response to query callback status
global String invocationId {get;}
}
global class SubmitApplication_ResponseException {
global Integer responseCode {get; set;}
global String defaultResponse {get; set;}
}
// Asynchronous response callback handler for SubmitApplication.
// Each method corresponds to the schema's declared callback key.
// Default implementations throws an exception alerting that a non-implemented callback was called.
global virtual class SubmitApplication_Callback {
global virtual void applicationOutcomeApproved(
List<SubmitApplication_applicationOutcomeApproved_Callback> callbacks) {
throw new SubmitApplication_ResponseException(404,
'Callback not handled: applicationOutcomeApproved');
}
global virtual void applicationOutcomeRejected(List<SubmitApplication_applicationOutcomeRejected_Callback> callbacks) {...}
global virtual void applicationError(List<SubmitApplication_applicationError_Callback> callbacks) {...}
}
// Asynchronous callback response payloads for callback applicationOutcomeApproved
global class SubmitApplication_applicationOutcomeApproved_Callback {
global SubmitApplication_Request request {get; set;}
global DateTime submitTime {get; set;}
global DateTime callbackTimeout {get; set;}
global CallbackStatus callbackStatus {get; set;}
global SubmitApplication_applicationOutcomeApproved_CallbackResponse response {get; set;}
}
global class SubmitApplication_applicationOutcomeApproved_CallbackResponse {
global AcmeMortgages_MortgageApplication body {get; set;}
}
global class SubmitApplication_applicationOutcomeRejected_Callback {...}
global class SubmitApplication_applicationOutcomeRejected_CallbackResponse {...}
global class SubmitApplication_applicationError_Callback {...}
global class SubmitApplication_applicationError_CallbackResponse {...}
}
Flujo de datos de devolución de llamada de ejemplo
En este ejemplo, un desarrollador de Salesforce Apex utiliza Servicios externos para registrar la especificación de API de solicitud de hipoteca de un banco. La especificación contiene operaciones de devolución de llamada, como se espera un retraso de hasta un día entre el envío de la solicitud y la aceptación.
El desarrollador de Apex escribe un cliente de Apex con un controlador de devolución de llamadas. El cliente de Apex especifica que después de que Salesforce reciba la respuesta demorada del sistema externo, Salesforce utiliza la lista resultante de nombres y otra información de la solicitud de hipoteca para crear de forma automática Contactos.
Este diagrama de secuencia demuestra el flujo de datos funcional entre el código de Apex del desarrollador ("Cliente / Controlador de Apex" en el diagrama), Salesforce, y el extremo de API de aplicación de hipoteca del banco ("Servicio Web externo" en el diagrama).
Existen dos respuestas del servicio web externo. El primero es síncrono y es la respuesta típica de ACK inicial. El segundo es la respuesta asíncrona demorada (técnicamente una solicitud) que incluye la carga de resultado en el cuerpo de la solicitud.
En primer lugar, el desarrollador de Apex envía una solicitud HTTP (una llamada) al servidor bancario (un servicio externo) con el cliente de Apex.
El servicio Web externo envía de inmediato una respuesta HTTP confirmando la recepción de la solicitud. Este primer reconocimiento agota el tiempo de espera después de 120 segundos. El desarrollador de Salesforce monitorea el estado de la solicitud utilizando la página Operaciones en segundo plano o el registro Depuración de Apex.
El banco inicia su proceso interno para ingresar la solicitud de hipoteca, aprobarla o denegarla, y actualmente preparar un resultado final (en el diagrama como "Async Delay").
En el plazo de un día, el banco envía de nuevo el resultado completado al desarrollador de Apex como una solicitud HTTP. Los datos de resultado (cantidad aprobada, estado, etc) para la solicitud de hipoteca están contenidos en el cuerpo de la solicitud. Salesforce recibe el resultado y lo procesa de acuerdo con la implementación del controlador de devolución de llamadas de Apex.
Salesforce devuelve una confirmación de respuesta HTTP al servicio Web externo. Si Salesforce procesa los datos correctamente (en este caso, para crear contactos), envía una respuesta al servicio web externo con un código de estado 200 y un mensaje de operación correcta.
Si Salesforce encuentra un error, envía un código de estado 404, 408 o 500 al servicio web externo con un mensaje de error genérico. El desarrollador de Apex puede ver más detalles de mensajes de error utilizando la página Operaciones en segundo plano o con el registro Depuración de Apex.

