Pular para o conteúdo principal

Referência rápida do Signer

O essencial do Lacuna Signer em uma página, com links para as páginas completas.

Para que serve​

O Lacuna Signer é um gerenciador de documentos e assinaturas: sua aplicação faz upload de um arquivo e define um fluxo de participantes (signatários e aprovadores, em sequência ou em paralelo), e o Signer os notifica, coleta as assinaturas digitais ou eletrônicas deles e devolve o arquivo assinado. Ele funciona como SaaS em dropsigner.com ou como uma instância on-premises própria, e você integra pela API REST, pelas bibliotecas cliente usadas nos exemplos e por um widget de assinatura que pode ser embutido na sua página.

PrefiraQuando
Rest PKI CoreVocê quer assinaturas dentro da sua própria aplicação, sem um fluxo de documentos: sua aplicação cria uma sessão, envia o usuário para uma página hospedada pelo Rest PKI Core e recebe o resultado de volta. Ele também valida assinaturas, aplica carimbos de tempo e verifica identidade biométrica.
PKI SDKSua aplicação é .NET e precisa criar ou validar assinaturas CMS/CAdES, PDF/PAdES ou XmlDSig/XAdES, ou validar certificados X.509, no próprio código.
PKI ExpressVocê precisa desses mesmos formatos de assinatura em praticamente qualquer linguagem, no seu próprio servidor Windows ou Linux, com um arquivo de licença.
Web PKISua página web precisa acessar os certificados do usuário por JavaScript (listá-los, lê-los, assinar dados) enquanto um SDK no servidor monta a assinatura. O próprio widget do Signer já depende de uma licença do Web PKI para o seu domínio.
Bulk SignerOs arquivos precisam ser assinados em lote na sua própria infraestrutura, com um certificado mantido pelo servidor, sem uma pessoa no processo. O Bulk Signer também pode encaminhar ao Signer os arquivos de um perfil de assinatura quando uma pessoa precisa assinar.

Instalação​

LinguagemPacoteVersão major atualRegistro
.NETLacuna.Signer.Client1 (1.24.0)NuGet
Javacom.lacunasoftware.signer:signer-client2 (2.14.0)Maven Central
Node.jssigner-node-client1 (1.1.0)npm
PHPlacuna/signer-client1 (1.4.10)Packagist
JavaScript (navegador), assinatura embutidalacuna-signer-widget0 (0.8.0)Script na CDN, npm

Instale com dotnet add package Lacuna.Signer.Client, Gradle implementation 'com.lacunasoftware.signer:signer-client:2.14.0', npm install signer-node-client ou composer require lacuna/signer-client. Veja Bibliotecas cliente.

Os exemplos fixam 1.17.0 (.NET), 2.13.0 (Java), ^1.1.0 (Node.js) e 1.4.10 (PHP), todas na versão major atual. Sem uma biblioteca cliente, chame a API REST diretamente, como fazem os Primeiros passos com curl.

Configuração e autenticação​

  • Chave de API. Toda requisição leva a chave no header X-Api-Key, no formato nome-da-aplicacao|<chave>. Se você tem permissão para criar aplicações na sua organização, crie uma em Aplicações e gere a chave com o botão Chaves dela; caso contrário, peça uma chave ao administrador da sua instância. A chave é exibida uma única vez e só enxerga e cria documentos daquela organização. Veja Primeiros passos e o Guia de Integração.
  • Chaves de administração e de monitoramento. As APIs de administração (usuários e organizações) exigem uma chave de uma aplicação da organização Sys Admin; as APIs de monitoramento de consumo exigem uma com o papel Monitor. Veja APIs de Administração e Monitoramento de consumo.
  • Referência da API. Swagger e a cópia do OpenAPI em https://docs.lacunasoftware.com/openapi/signer.json, com o título "Dropsigner", versão 2.16.1.
AmbienteURL base
Produção, em nuvem (Dropsigner SaaS)https://www.dropsigner.com
Produção, on-premisesA URL da sua instância, como https://signer.suaempresa.com.br
Sandbox, para desenvolvimento e testeshttps://signer-lac.azurewebsites.net

O cliente recebe a URL da instância e a chave de API; troque as duas juntas ao passar para produção.

use Lacuna\Signer\PhpClient\SignerClient;
$this->endPoint = "https://signer-lac.azurewebsites.net/";
$this->apiKey = "your-application|0000000000000000000000000000000000000000000000000000000000000000";
$this->signerClient = new SignerClient($this->endPoint, $this->apiKey);

TODO(docs): as páginas da documentação do Signer não mencionam o sandbox (só os exemplos o mencionam), nem como obter uma organização e uma chave de API nele.

Operações principais​

Os blocos abaixo são em PHP, a linguagem com mais exemplos no catálogo; Experimente traz as mesmas tarefas em C#, Java e Node.js, quando existem.

Fazer upload de um arquivo​

Envie o arquivo primeiro; o id de upload da resposta é o que o documento referencia. POST /api/uploads/bytes recebe os bytes em Base64, em JSON (o mais simples), e POST /api/uploads recebe multipart/form-data (melhor para arquivos grandes); em PHP, uploadFile. Veja Criar documentos.

$filePath = "resources/sample.pdf";
$fileName = basename($filePath);
$file = fopen($filePath, "r");
$uploadModel = new UploadModel($this->signerClient->uploadFile($fileName, $file, "application/pdf"));
fclose($file);

Criar um documento com um fluxo​

Crie o documento a partir do upload e defina quem age e em que ordem: cada item de flowActions tem um type (Signer, Approver, SignRule ou ApproverRule), um step (ações no mesmo step acontecem em paralelo, e um step maior acontece depois) e um user (name, identifier, email). POST /api/documents; em PHP, createDocument. A resposta traz um par uploadId e documentId por arquivo. O Signer envia e-mail aos participantes do primeiro passo imediatamente, a menos que você envie disablePendingActionNotifications: true. Veja Criar documentos.

$fileUploadModelBuilder = new FileUploadBuilder($uploadModel);
$fileUploadModelBuilder->setDisplayName("One Signer Sample");
$user = new UsersParticipantUserModel();
$user->setName("Jack Bauer");
$user->setEmail("jack.bauer@mailinator.com");
$user->setIdentifier("75502846369");
$flowActionCreateModel = new FlowActionsFlowActionCreateModel();
$flowActionCreateModel->setType(FlowActionType::SIGNER);
$flowActionCreateModel->setUser($user);
$documentRequest = new DocumentsCreateDocumentRequest();
$documentRequest->setFiles(array($fileUploadModelBuilder->toModel()));
$documentRequest->setFlowActions(array($flowActionCreateModel));
$docResult = $this->signerClient->createDocument($documentRequest)[0];

Obter a URL de assinatura (assinatura embutida)​

Para que o participante assine dentro da sua aplicação em vez de pelo e-mail, peça a URL de ação dele, identificando o participante por identifier (a documentação também envia emailAddress): POST /api/documents/{id}/action-url; em PHP, getActionUrl. A resposta traz url, para redirecionar o usuário à página de assinatura do Signer, e embedUrl, que você passa ao método render do LacunaSignerWidget na sua página. Combine com disablePendingActionNotifications: true na criação. O widget exige que o Signer esteja configurado com uma licença do Web PKI para o domínio da sua página. Veja Assinatura Embutida.

$actionUrlRequest = new DocumentsActionUrlRequest();
$actionUrlRequest->setIdentifier($user->getIdentifier());
$actionUrlResponse = new DocumentsActionUrlResponse($this->signerClient->getActionUrl($docResult->getDocumentId(), $actionUrlRequest));
echo ($actionUrlResponse->getEmbedUrl());

Verificar o status do documento​

GET /api/documents/{id}; em PHP, getDocumentDetails. O documento está finalizado quando status é Concluded (os demais são Pending, FlowConcluded, Refused, Canceled e Expired), e um participante concluiu a ação dele quando o item correspondente em flowActions tem status Completed. Em produção, use webhooks em vez de polling. Veja Acompanhar documentos.

$documentDetails = new DocumentsDocumentModel($this->signerClient->getDocumentDetails($document->getDocumentId()));
if ($documentDetails->getIsConcluded()) {
echo "Document concluded";
}
foreach ($documentDetails->getFlowActions() as $item) {
if ($item["status"] == ActionStatus::PENDING) {
$user = new UsersParticipantUserModel($item["user"]);
echo "The status of User " . $user->getName() . " is Pending\n";
}
}

Baixar o arquivo assinado​

GET /api/documents/{id}/content?type=...; em PHP, getDocumentContent. Signatures é o arquivo assinado (o PDF com as assinaturas embutidas, ou um .p7s para CAdES), PrinterFriendlyVersion é um PDF com o manifesto de assinaturas e Original é o arquivo enviado. Documentos cancelados, expirados ou recusados só podem ser baixados como Original e PrinterFriendlyVersion, e um documento que ninguém assinou ainda não tem Signatures nem PrinterFriendlyVersion: verifique hasSignature e status antes. GET /api/documents/{id}/content-b64 devolve os bytes em Base64, em JSON. Veja Baixar e listar.

$signed = $this->signerClient->getDocumentContent($documentId, DocumentDownloadTypes::SIGNATURES);
file_put_contents("./resources/downloaded-signed.pdf", $signed);
$printerFriendly = $this->signerClient->getDocumentContent($documentId, DocumentDownloadTypes::PRINTER_FRIENDLY_VERSION);
file_put_contents("./resources/downloaded-printer-friendly.pdf", $printerFriendly);

Receber webhooks​

Cadastre a sua URL na tela da Organização, seção Integração, ou com POST /api/organizations/{orgId}/webhooks (url, authType, token). O Signer passa então a enviar um POST com { "type": "...", "data": { ... } } para DocumentsCreated, DocumentSigned, DocumentApproved, DocumentRefused, DocumentConcluded, DocumentCanceled, DocumentExpired e DocumentDeleted. Ele não assina o corpo: verifique o header que você escolheu, como Authorization: Bearer <token>, responda 2xx imediatamente (qualquer outra resposta gera novas tentativas, por padrão até 10), torne o processamento idempotente e consulte o documento de novo, porque os eventos podem chegar fora de ordem. Veja Webhooks.

if (!hash_equals(self::EXPECTED_AUTHORIZATION, $_SERVER['HTTP_AUTHORIZATION'] ?? '')) {
http_response_code(401);
return;
}
$body = file_get_contents('php://input');
$webhook = json_decode($body, true);
if (($webhook['type'] ?? null) === WebhookTypes::DOCUMENT_CONCLUDED) {
$document = new DocumentsDocumentModel($this->signerClient->getDocumentDetails($webhook['data']['id']));
if ($document->getStatus() !== DocumentStatus::CONCLUDED) {
return;
}
}

Cancelar, recusar ou excluir um documento​

POST /api/documents/{id}/cancellation e POST /api/documents/{id}/refusal, cada um com um reason, e DELETE /api/documents/{id}; em PHP, cancelDocument, refuseDocument e deleteDocument. Chame a operação de que você precisa. Veja Ciclo de vida do documento.

$cancelDocument = new DocumentsCancelDocumentRequest();
$cancelDocument->setReason("This is a document cancellation");
$this->signerClient->cancelDocument($documentId, $cancelDocument);
$refuseDocument = new RefusalRefusalRequest();
$refuseDocument->setReason("This is a document refusal");
$this->signerClient->refuseDocument($documentId, $refuseDocument);
$this->signerClient->deleteDocument($documentId);

Erros​

A API responde com um código de status HTTP: 400 para um erro de sintaxe, como um campo obrigatório que não foi enviado; 401 quando a chave de API não foi enviada ou é inválida; 403 quando a chave é válida, mas a aplicação não tem permissão para a operação; e 422 para um erro da API, cujo corpo JSON (ErrorModel) tem code, message e details. Um id de entidade que não é encontrado também gera 422. Teste o code, e não a mensagem. Veja Respostas de erro.

Os primeiros que um integrador encontra:

  • 401 ou 403 na primeira chamada: a chave é inválida, foi revogada ou pertence a outra organização.
  • DocumentNotFound e InvalidFlowAction, entre os principais códigos que a referência da API lista (a lista não é completa, e novos códigos podem surgir).
  • DocumentHasNoSignatures (422): baixar Signatures ou PrinterFriendlyVersion de um documento que ninguém assinou ainda.
  • MaxWebhooksLimitReached (mais webhooks que o limite MaxWebhooksPerOrganization, 5 por padrão) e OperationNotSupportedInPersonalOrganizations ao cadastrar um webhook.

Em PHP, as chamadas do cliente lançam uma exceção cuja mensagem traz a exceção interna inteira, mas getDocumentContent não lança exceção em erros HTTP: ele devolve o corpo JSON do erro, então verifique os detalhes do documento antes de salvar o conteúdo como arquivo.

Certificados e credenciais de teste​

  • Certificados de teste: a ICP de testes da Lacuna Software. O cenário de assinatura pública dos exemplos assina no sandbox com um deles, o certificado do CPF 56072386105.
  • Sandbox https://signer-lac.azurewebsites.net: os exemplos rodam nele com uma chave de exemplo compartilhada; para usar a sua própria organização, troque-a por uma chave sua. Cada execução cria documentos reais e o Signer envia e-mail aos participantes, por isso os exemplos usam endereços @mailinator.com fictícios.
  • Assinatura em nuvem no widget: o exemplo online usa o certificado de teste do BirdID (CPF 026.102.470-10), pareado por um QR code no aplicativo BirdID. Veja Assinatura Embutida.
  • Por padrão, uma instância do Signer aceita só certificados ICP-Brasil; a página TrustArbitrator mostra como aceitar outras ACs raiz.
  • TODO(docs): quais certificados de teste o Dropsigner e o sandbox aceitam.

Experimente​

Demonstrações online e os exemplos de cada linguagem:

Ver em Markdown