Pular para o conteúdo principal

Integração com Assinatura embutida

Introdução​

A integração com Assinatura embutida permite assinar/aprovar documentos submetidos no Signer dentro de qualquer aplicação por meio do componente LacunaSignerWidget.

observação

O Signer deve ser configurado com uma licença do Web PKI que tenha o domínio no qual o componente será carregado.

Instalação​

Primeiro, inclua na sua página o arquivo lacuna-signer-widget.js mais recente:

<script type="text/javascript" src="https://cdn.lacunasoftware.com/libs/signer/lacuna-signer-widget-0.8.0.min.js"
integrity="sha256-kS96fv3kyz1iJOP3crrI/2dvBzAgEHu4dZF9ecS/f0I="
crossorigin="anonymous"></script>

Em seguida, instancie a classe LacunaSignerWidget:

var widget = new LacunaSignerWidget();

Chame então o método on() passando o tipo de evento que quer escutar e uma função de callback que será chamada quando o usuário assinar/aprovar o documento:

//assinatura
widget.on(widget.events.documentSigned, function (e) {
// ...
//alert('Documento ' + e.id + ' assinado');
});
//aprovação
widget.on(widget.events.documentApproved, function (e) {
// ...
//alert('Documento ' + e.id + ' aprovado');
});

Se preferir use o método listen() para escutar todos eventos com apenas um callback:

widget.listen(function (e) {
if (e.type === widget.events.documentSigned) {
// ...
//alert('Documento ' + e.id + ' assinado');
} else if (e.type === widget.events.documentApproved) {
// ...
//alert('Documento ' + e.id + ' aprovado');
}
});
observação

Sempre verifique no backend se o documento foi de fato concluído, dado que os callbacks podem ser acionados por outros arquivos javascript.

Por fim, carregue o iFrame utilizando o método render(), que recebe duas entradas obrigatórias:

  • embedUrl: a URL para ação que deseja ser realizada. Corresponde ao parâmetro embedUrl retornado pela API Action URL
  • elementId: id do elemento no qual será exibido o componente de assinatura.

E duas entradas opcionais:

  • page: numero da página na qual o documento será aberto em sua inicialização (para abrir a última página de qualquer documento, não importando o tamanho dele, atribui-se o número '-1').
  • scale: a porcentagem que definirá em qual escala o documento será aberto. Pode ser definido através de um simples string '100' ou através do widget.scaleOptions.S100
widget.render(embedUrl, 'embed-container', page, scale);

Caso prefira, pode ser fornecido o elemento DOM diretamente:

widget.renderElement(embedUrl, document.getElementById('embed-container'), page, scale);

Exemplo online​

Para experimentar, abra Assinatura embutida no site de demonstração, que embute a página de assinatura do Dropsigner com este widget. A versão em Markdown lista todas as chamadas que ele faz.

A página abaixo é o lado do navegador de uma assinatura embutida. O botão pede uma URL de embed ao seu próprio backend, e o seu backend, que mantém a chave de API longe do navegador:

  1. Envia o PDF (POST /api/uploads) e cria o documento com o signatário como participante e com disablePendingActionNotifications: true, para que ninguém receba e-mail (POST /api/documents).
  2. Pede a URL de ação desse participante (POST /api/documents/{id}/action-url) e devolve o embedUrl dela.

Veja Assinatura na sua própria aplicação para as duas chamadas. O script chama o backend com o $.post do jQuery, então carregue o jQuery na página ou use fetch no lugar.

cuidado

Na rota POST /api/documents/{id}/action-url, o {id} é o ID do documento, e não o ID da ação do participante (flowActionId). Com o ID da ação na rota, a API responde com o erro DocumentNotFound. Envie o flowActionId no corpo da requisição, e só quando o participante tem mais de uma ação pendente no documento. Os IDs das ações ficam em flowActions[].id, na resposta de GET /api/documents/{id}.

<script src="https://cdn.lacunasoftware.com/libs/signer/lacuna-signer-widget-0.8.0.min.js"></script>
<div style="text-align: center;">
<h1>
Signer embedded signature
</h1>
<button type="button" onclick="startSignature(this)">
Start Signature for Alan Turing (560.723.861-05)
</button>
</div>

<div id="embed-container" class="frame-container">

</div>
.frame-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}

.frame-responsive {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
border: none;
}
function sign(embedUrl) {
var widget = new LacunaSignerWidget();

widget.on(widget.events.documentSigned, function (e) {
// ...
alert('Document ' + e.id + ' signed');
});

widget.render(embedUrl, 'embed-container');
}

// Substitua pela sua própria chamada: o seu backend cria o documento e devolve a URL de embed
function startSignature(elem) {
elem.innerHTML = 'Loading ...';

$.post("/seu-backend/assinatura-embutida", {}).
done(function (data) {
if (data) {
sign(data);
elem.style.visibility = "hidden";
} else {
elem.innerHTML = 'Error';
}
}).fail(function () {
elem.innerHTML = 'Error';
});
}

Assine com o certificado de teste da Lacuna de Alan Turing (CPF 560.723.861-05), da página Certificados de teste, numa instância que confie na ICP de testes da Lacuna. Se o Web PKI não estiver instalado, o widget leva o usuário à página de instalação, que o traz de volta à sua aplicação no fim.

Exemplo online de assinatura em nuvem​

Para este exemplo é utilizado o certificado de teste do BirdID (CPF 026.102.470-10, veja abaixo as instruções para pareamento).

A página é a mesma do exemplo online, com outro título e outro botão; o backend cria o documento para o usuário de teste do BirdID, que assina com um certificado em nuvem.

<script src="https://cdn.lacunasoftware.com/libs/signer/lacuna-signer-widget-0.8.0.min.js"></script>
<div style="text-align: center;">
<h1>
Signer embedded Cloud signature
</h1>
<button type="button" onclick="startSignature(this)">
Start Signature for Usuario Teste BIRDID (026.102.470-10)
</button>
</div>

<div id="embed-container" class="frame-container">

</div>
function sign(embedUrl) {
var widget = new LacunaSignerWidget();

widget.on(widget.events.documentSigned, function (e) {
// ...
alert('Document ' + e.id + ' signed');
});

widget.render(embedUrl, 'embed-container');
}

// O seu backend cria o documento para o usuário de teste do BirdID e devolve a URL de embed
function startSignature(elem) {
elem.innerHTML = 'Loading ...';

$.post("/seu-backend/assinatura-embutida?nuvem=true", {}).
done(function (data) {
if (data) {
sign(data);
elem.style.visibility = "hidden";
} else {
elem.innerHTML = 'Error';
}
}).fail(function () {
elem.innerHTML = 'Error';
});
}

Para assinar como o usuário de teste do ambiente de homologação do BirdID, leia o QR code abaixo no aplicativo BirdID:

BirdID HML credentials

Configurações adicionais​

Na instanciação da classe LacunaSignerWidget você pode passar um objeto com uma ou mais das configurações listadas abaixo:

AtributoTipoDescrição
enableNotificationsbooleanNotificações não são enviadas após a conclusão da assinatura/aprovação embutida. Defina como true para enviá-las. Pode ser definido após a instanciação com método setEnableNotifications.
disableDocumentPreviewbooleanSe true, esconde a pré-visualização do documento. Nesse caso, será exibido apenas o botão de assinatura e dados do assinante/aprovador. Pode ser definido após a instanciação com método setDisableDocumentPreview.
enableRefusalbooleanSe true, exibirá a opção para recusar uma assinatura. Pode ser definido após a instanciação com método setEnableRefusal.
culturestringDefine o idioma utilizado, as opções disponíveis são "pt"(português), "en"(inglês) e "es"(espanhol)
themestringDefine o tema do widget, use o código de 3 caracteres de cada tema (ex: amazon-cornell-red: "acr"), os temas disponíveis estão na página de temas

Exemplo:

var widget = new LacunaSignerWidget({ disableDocumentPreview: true });
var widget = new LacunaSignerWidget();

widget.setDisableDocumentPreview(true);

Exemplo online de assinatura sem pré-visualização​

A mesma página do exemplo online, com disableDocumentPreview: true e o widget num contêiner de no máximo 600 pixels de largura.

<script src="https://cdn.lacunasoftware.com/libs/signer/lacuna-signer-widget-0.8.0.min.js"></script>
<div style="text-align: center;">
<h1>
Signer embedded signature without Preview
</h1>
<button type="button" onclick="startSignature(this)">
Start Signature for Alan Turing (560.723.861-05)
</button>
</div>

<div class="container">
<div id="embed-container" class="frame-container">

</div>
</div>
.container {
max-width: 600px;
height: 100%;
margin-left: auto;
margin-right: auto;
}
function sign(embedUrl) {
var widget = new LacunaSignerWidget({ disableDocumentPreview: true });

widget.on(widget.events.documentSigned, function (e) {
// ...
alert('Document ' + e.id + ' signed');
});

widget.render(embedUrl, 'embed-container');
}

// Substitua pela sua própria chamada: o seu backend cria o documento e devolve a URL de embed
function startSignature(elem) {
elem.innerHTML = 'Loading ...';

$.post("/seu-backend/assinatura-embutida", {}).
done(function (data) {
if (data) {
sign(data);
elem.style.visibility = "hidden";
} else {
elem.innerHTML = 'Error';
}
}).fail(function () {
elem.innerHTML = 'Error';
});
}

Exemplo para dispositivos móveis​

Também é possível utilizar o exemplo de assinaturas embutidas em dispositivos móveis, um app de exemplo está disponível em nosso repositório do GitHub. O exemplo contém uma página da web contendo o widget em JavaScript rodando em seu dispositivo. A aplicação foi desenvolvida com Flutter.

A imagem abaixo mostra o processo de assinatura sem preview de documento dentro do aplicativo:

Mobile embedded example without preview

Posicionamento de marcas de assinatura​

À partir da versão 1.70.0 do Signer e 0.7.0 do Widget, é possível embutir a tela de posicionamento de marcas de assinatura em outras aplicações tal como já era feito para a tela de assinatura. Uma vez posicionadas, é possível obter os dados de posicionamento correspondente tanto pela biblioteca quando pela API do Signer para que sejam criados um ou mais documentos com as posições selecionadas.

O primeiro passo é criar uma sessão de posicionamento utilizando a API de criação de sessão. Existem duas variações dessa API:

  • API de criação de sessão básica: permite criar a sessão de posicionamento fornecendo apenas os dados necessários para criação da sessão de posicionamento. Dados pessoais de signatários como e-mail e CPF, por exemplo, são opcionais. Use esta API, caso, após obter o resultado da sessão, você ainda pretenda atualizar os dados da requisição de criação de documentos que será enviada posteriormente ao Signer.

  • API de criação de sessão com requisição de criação de documento: permite criar a sessão de posicionamento fornecendo o mesmo request que é utilizado para criar documentos. Use esta API, caso prefira encaminhar o resultado da sessão diretamente para a API de criação de documentos sem fazer nenhuma alteração adicional.

O resultado de ambas APIs será o retorno de um ID de sessão e uma URL para embutir a tela de posicionamento:

{
//ID da sessão
"id": "4cdcfa93-8f38-46f9-8634-246d5589fe5f",
//URL para usar com o Widget
"embedUrl": "https://www.dropsigner.com/position-marks/4cdcfa93-8f38-46f9-8634-246d5589fe5f?v=1"
}

Uma vez obtida a URL de sessão, basta inicializar o Widget assim como é feito para a funcionalidade de assinatura:

var widget = new LacunaSignerWidget();

Chame o método on() passando o evento de posicionamento de marcas e uma função de callback que será chamada quando o usuário concluir o posicionamento:

//assinatura
widget.on(widget.events.marksPositioned, function (e) {
// O atributo data conterá a requisição preenchida com as posições das marcas
//console.log(e.data);
//alert('Marcas posicionadas');
});

Por fim, carregue o iFrame utilizando o método render():

widget.render(embedUrl, 'embed-container');

Uma vez concluída a sessão de posicionamento, cada entrada do atributo flowActions da requisição fornecida na criação da sessão será atualizada com as posições selecionadas na tela de posicionamento (mais especificamente, será preenchido o atributo prePositionedMarks).

Essa requisição atualizada pode ser obtida pelo atributo data do evento de posicionamento ou pelo atributo de mesmo nome da API de obtenção de dados da sessão.

observação

A sessão de posicionamento tem duração de 1 hora após sua criação. Após esse período, não será possível obter nem atualizar os dados da sessão.

Ver em Markdown