> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ejemplo de procesamiento manual

> Revise un ejemplo de la API de ABBYY FlexiCapture que agrega una etapa de servicio personalizada para revisar tareas, aceptar o rechazar documentos y adjuntar una firma digital.

Este ejemplo muestra cómo crear una etapa adicional de procesamiento manual de datos. Por ejemplo, el departamento de seguridad de su empresa puede utilizar esta etapa para verificar y confirmar el envío de los documentos que cumplan determinadas condiciones para su posterior procesamiento, y rechazar los documentos que no cumplan esas condiciones.

Cada documento confirmado va acompañado de un conjunto de bytes que simulan una firma digital.

<div id="what-the-example-does">
  ## Qué hace el ejemplo
</div>

El ejemplo realiza los siguientes pasos:

* Configura la conexión
* Empieza a trabajar con el proyecto
* Obtiene y procesa la lista de tareas
* Procesa cada tarea en la etapa de servicio
* Carga el archivo en el servidor
* Cierra la sesión

<div id="run-the-example">
  ## Ejecutar el ejemplo
</div>

<Steps>
  <Step title="Abra la solución en Visual Studio">
    Abra `UserStageExample.sln` en Visual Studio 2013 o en una versión posterior.
  </Step>

  <Step title="Introduzca la URL del Servidor de aplicaciones">
    Introduzca la URL del Servidor de aplicaciones.
  </Step>

  <Step title="Seleccione un tipo de autenticación">
    Seleccione un tipo de autenticación.
  </Step>

  <Step title="Inicie sesión">
    Haga clic en **Login**.
  </Step>
</Steps>

<div id="configure-the-connection">
  ## Configurar la conexión
</div>

```csharp theme={null}
private const string FlexiHandlerPath = "/FlexiCapture12/Server/{0}API/v1/Soap"; // Ruta a la API de FlexiCapture
private const string FlexiCaptureAuthPart = "FCAuth/"; // Ruta para autenticar FlexiCapture
private const string UserStageProjectName = "UserStageExample"; // El nombre del proyecto utilizado en este ejemplo
private const string UserStageName = "Service"; // El nombre de la etapa de servicio
// Creación de un nuevo enlace
var binding = new BasicHttpBinding();
// El tamaño del mensaje es demasiado pequeño para FlexiCapture y es necesario aumentarlo
binding.MaxReceivedMessageSize = MessageSize;
// Selección del modo de seguridad de conexión según el protocolo
binding.Security.Mode = serverUri.Scheme == Uri.UriSchemeHttps
   ? BasicHttpSecurityMode.Transport
   : BasicHttpSecurityMode.TransportCredentialOnly;
// Selección del método de autenticación
binding.Security.Transport.ClientCredentialType = windowsAuth
   ? HttpClientCredentialType.Windows
   : HttpClientCredentialType.Basic;
// Selección de la ruta a la API según el método de autenticación
var externalSuffix = windowsAuth ? string.Empty : FlexiCaptureAuthPart;
var remoteAddress = new EndpointAddress(new Uri(serverUri, string.Format(FlexiHandlerPath, externalSuffix)));
// Creación de un cliente SOAP
_client = new FlexiCapture.FlexiCaptureWebServiceSoapClient(binding, remoteAddress);
// Para autenticar FlexiCapture, especifique un nombre de usuario y una contraseña
if (_client.ClientCredentials != null && !windowsAuth)
{
   _client.ClientCredentials.UserName.UserName = login;
   _client.ClientCredentials.UserName.Password = password;
}
```

<div id="start-working-with-the-project">
  ## Empezar a trabajar con el proyecto
</div>

```csharp theme={null}
// Abrir la sesión
_sessionId = _client.OpenSession(RoleType, WorkstationType);
var projectGuid = string.Empty;
// Buscar el proyecto necesario
foreach (var project in _client.GetProjects())
{
   if (project.Name == UserStageProjectName)
   {
      projectGuid = project.Guid;
   }
}
if (string.IsNullOrEmpty(projectGuid))
{
   MessageBox.Show("The server does not contain the UserStageExample project which is needed for this example");
}
// Abrir el proyecto
_projectId = _client.OpenProject(_sessionId, projectGuid);
// Buscar y guardar el identificador de la etapa de servicio
var stages = _client.GetProcessingStages(_projectId, 0, 0, UserStageName);
if (stages.Count != 1) throw new Exception("Invalid project");
   _serviceStageId = stages[0].Id;
// Buscar y guardar el ID externo de la etapa de excepciones
stages = _client.GetProcessingStages(_projectId, 0, ExceptionStageType, string.Empty);
if (stages.Count != 1) throw new Exception("Invalid project");
   _exceptionsStageId = stages[0].ExternalId;
```

<div id="get-and-process-tasks-pending-at-the-service-stage">
  ## Obtener y procesar tareas pendientes en la etapa de servicio
</div>

```csharp theme={null}
// Obtención de la lista de tareas
var tasks = _client.GetAvailableTasksByStageId(_sessionId, _projectId,
new FlexiCapture.stageIds() { _serviceStageId }, false);
var result = new Dictionary<int, Task>();
if (tasks == null || tasks.Count == 0) return result;
foreach (var task in tasks)
{
   // Para cada tarea se crea un objeto del tipo Task
   var item = new Task
   {
      Id = task.Id,
      BatchId = task.BatchId
   };
   // Obtención de la lista de documentos de la tarea
   var documents = _client.GetTaskDocuments(task.Id);
   if (documents == null || documents.Count == 0) continue;
   foreach (var document in documents)
   {
      // Carga del XML de la tarea
      var file = _client.LoadDocumentResult(_sessionId, document.BatchId, document.Id, "DocumentBody"); // "DocumentBody" - el nombre del archivo que contiene los datos reconocidos
      if (file == null || file.Bytes == null) continue;
      // Descomposición del XML
      var doc = new Document(document.Id, XDocument.Load(new MemoryStream(file.Bytes)));
      // Guardado de la lista de documentos descompuesta
      item.Documents.Add(document.Id, doc);
   }
   result.Add(item.Id, item);
}
```

<div id="send-the-task-for-further-processing">
  ## Enviar la tarea para su procesamiento posterior
</div>

```csharp theme={null}
var ids = new FlexiCapture.docIds();
foreach (var rejectedDocument in rejectedDocuments)
{
   ids.Add(rejectedDocument.Id);
}
if (ids.Count > 0)
{
   _client.CreateTask(_sessionId, batchId, _exceptionsStageId, 0, "Rejection reason", 0, ids, false);
}
_client.OpenBatch(_sessionId, batchId);
var hasDocuments = false;
try
{
   var uri = _client.Endpoint.Address.Uri.OriginalString.Replace("/API/v1/Soap", "/FileService/v1");
   foreach (var document in acceptedDocuments)
   {
      hasDocuments = true;
      var buffer = new byte[SignatureSize]; // El tamaño de la firma digital añadida a los documentos: 1024
      _rng.GetBytes(buffer);
      //DocumentAttachment: El tipo de adjunto (9 - adjunto de documento)
      _client.SaveAttachment(_sessionId, DocumentAttachment, document.Id, batchId, _projectId, new FlexiCapture.File
      {
         Bytes = buffer,
         Name = "Signature.dat"
      });
      document.CreateStamp();
      UploadTextFileToServer(new Uri(uri),
         _client.ClientCredentials.UserName.UserName,
         _client.ClientCredentials.UserName.Password,
         document.GetXml(), 0, _sessionId, _projectId,
         batchId, 0, document.Id, 0, "DocumentBody"
      ).Wait();
   }
};
```

<div id="upload-the-file-to-the-server">
  ## Cargar el archivo al servidor
</div>

```csharp theme={null}
private static async Task<string> UploadTextFileToServer(Uri server, string login, string password,
        string stream, int objectType, int sessionId, int projectId, int batchId, int parentId,
        int objectId, int version, string streamName)
{
        var creds = CredentialCache.DefaultNetworkCredentials;
        if (!string.IsNullOrEmpty(login)) creds = new NetworkCredential(login, password);
        using (var handler = new HttpClientHandler { Credentials = creds })
        using (var client = new HttpClient(handler))
        {
                var encodedStreamName = Convert.ToBase64String(Encoding.Unicode.GetBytes(streamName));
                var content = new MultipartFormDataContent
                {
                        {new StringContent("Save"), "Action"},
                        {new StringContent(objectType.ToString()), "objectType"},
                        {new StringContent(sessionId.ToString()), "sessionId"},
                        {new StringContent(projectId.ToString()), "projectId"},
                        {new StringContent(batchId.ToString()), "batchId"},
                        {new StringContent(parentId.ToString()), "parentId"},
                        {new StringContent(objectId.ToString()), "objectId"},
                        {new StringContent(version.ToString()), "version"},
                        {new StringContent(encodedStreamName), "streamName"},
                        {new ByteArrayContent(Encoding.Unicode.GetBytes(stream)), "blob", "data.txt"}
                };
                var msg = client.PostAsync(server, content).Result;
                return await msg.Content.ReadAsStringAsync();
        }
}
```

<div id="close-the-session">
  ## Cerrar la sesión
</div>

```csharp theme={null}
_client.CloseProject(_sessionId, _projectId);
   _client.CloseSession(_sessionId);
```
