Table of Contents |
---|
Přímé volání Signi API
Při integraci Signi - Microsoft je jednou z možností volat napřímo Signi API. Výhodou přímého volání Signi API je flexibilita, novinky v Signi API jsou ihned dostupné pro využití. Je možné paralelně zpracovávat více dokumentů na jednou. Je možné ho použít jak z cloudových tenantů tak on premise instalací. Pro volání z Microsoft Power Automate se využijí operace HTTP a Webhook.
Před voláním API je třeba si vygenerovat v Signi aplikaci API Klíč pro pracovní prostor / worspaceworkspace, do kterého budete dokumenty k podpisu předávat viz Generování API klíče.
Detailní volání použití jednotlivých end pointů:
Mnoho úspěchů. V případě potíží se obracejte na help@signi.com .
...
Volat pak můžete kterýkoliv z End Pointů Signi API.
Následující příklady ukazují volání SIgni API ze tří různých technologií Microsoftu
Microsoft Power Automate,
kód v .NET,
kód ve Visual Basic for Application - VBA.
Příklad volání Signi API z MS Power Automate
MS Power Automate je integrační služba, která je součástí technologické platformy Microsoft Power Platform. Příklad volání Signi API z MS Power Automate se skládá ze dvou tří flow:
Signi Demo - Předání podkladů pro vzorPodepsání dokumentu ze vzoru- vyvolá podpis dokumentu vytvořeného ze vzoru Testovací “Testovací smlouva k podpisu podpisu” uloženém v Signi a zpřístupněném v testovacím workspace Demo API,
Signi Demo - Podepsání PDF souboru - předá k podpisu PDF soubor,
Signi Demo - Webhook - vytvoří v prostředí MS Power Automate webhook pro přijetí výsledků podepsání dokumentu, odkazuje se na ně první flow.
...
Vytvoření flow pro podepsání dokumentu ze vzoru v Signi
...
Pro vyzkoušení je na produkčním prostředí Signi workspace "Demo API" a má API klíč = “71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f” , při svých voláních zaměňte tento API klíč za API klíč svého workspace, který získáte po objednání služby "Integrace API" a Generování API klíče.
Jednotlivé flow z příkladů níže si můžete stáhnout zde.
Vytvoření flow pro podepsání dokumentu ze vzoru
Vytvořte nové flow přes MS Power Automate > Create (v levém panelu) > Instant cloud flow (pro ruční spuštění ) > Manually create flow.
...
Parametry operace HTTP pro vyvolání vzoru obdobně jako v Signi HELP > API Integrace > Příklad 3 - Předání podkladů pro vzor :
Požadavek typu POSTV HEAD pro autentizaci API klíč v
Adresa EndPointu je https://api.signi.com/api/v1/contract/?type=template
V HEAD pro autentizaci API klíč v poli s názvem x-api-key
Pro účely dema je na produkčním prostředí Signi https://api.signi.com je workspace "Demo API" a má API klíč = “71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f” , při svých voláních zaměňte tento API klíč za API klíč svého workspace, který získáte po objednání služby "Integrace API" a Generování API klíče.
V body je potřebný JSON se všemi parametry pro vytvoření dokumentu, url webhooku odpovídá webhooku vytvořeném v dalším krokudále, lze přidat po otestování tohoto flow.
...
E-mail demo+counterparty@signi.com si můžete změnit na svůj.
Code Block |
---|
{ "settings": { "signing_order": "proposers_before_counterparties", "autosign_proposers": "V Praze" }, "people": [ { "is_proposer": true, "email": "demo@signi.com", "contract_role": "sign" }, { "is_proposer": false, "party_order": 1, "email": "demo+counterparty@signi.com", "contract_role": "sign", "person_type": "nature", "first_name": "John", "last_name": "Doe2" } ], "webhooks": [ { "state": "completed", "url": "https://prod-174.westeurope.logic.azure.com:443/workflows/4255c88e046844319c27fdf997ee7eed/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=lJhO1j7pXPUUzQ6apYhS1TJmI6HoEyN4NS_cBMI-6rw" } ], "template": { "id": "7v1", "parameters": [ { "id": "112", "value": "Hnutí za digitalní revoluci" }, { "id": "131", "value": "Chci" }, { "id": "411", "value": "V šíření zpráv" }, { "id": "421", "value": "27.5.2021" }, { "id": "431", "value": "v Praze" } ] } } |
...
Výsledek odpovědi Signi API na požadavek přístupný v MS Power Automate:
...
...
Vytvoření flow pro
...
podepsání PDF souboru
Vytvořit Vytvořte nové flow přes přes MS Power Automate > Create (v levém panelu) > Create > Instant cloud flow (pro ruční spuštění spuštění ) > Manually create flow.
Vložit do flow operaci přes Next step > When an HTTP request is received (vybrat tento typ operace).
...
Jako šablonu dat, které webhook dostane, je třeba vložit příklad JSONu viz příklad na https://signi.docs.apiary.io/#reference/webhooky/ze-vzoru-s-prilohami tj,
Code Block |
---|
{
"type": "object",
"properties": {
"contract_id": {
"type": "integer"
},
"state": {
"type": "string"
},
"file": {
"type": "string"
},
"attachments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"contract_id": {
"type": "integer"
},
"state": {
"type": "string"
},
"file": {
"type": "string"
}
},
"required": [
"contract_id",
"state",
"file"
]
}
}
}
}
|
...
Jako druhá operace je do flow vložená Parse JSON , kde se řekne, že se bude zpracovávat kód z Body a jako příklad JSON schématu se bere to, co dostává webhook ze Signi viz výše. Zároveň se ikonou Copy získá URL webhooku , který se následně vyplní jako parametr volání Signi v prvním flow příkladu.
...
Výsledek volání webhooku lze zjistit v MS Power Automate v historii flow Signi Demo - webhook, na stránce detailu dole zobrazit v historii poslední volání , kde jsou vidět výsledky volání.
...
LikeBe the first to like thisVe flow pro podepsání PDF souboru je třeba nejprve do flow získat soubor k podpisu, zde používame operátor Get file content .
...
Následně vyvoláme opet operátor HTTP, Parametry operace HTTP pro vyvolání vzoru obdobně jako v Signi HELP > API Integrace > Příklad 2 - Předání PDF dokumentu k podpisu
Požadavek typu POST
Adresa EndPointu je https://api.signi.com/api/v1/contract/?type=doc
V HEAD pro autentizaci API klíč v poli s názvem x-api-key
Pro účely dema je na produkčním prostředí Signi https://api.signi.com je workspace "Demo API" a má API klíč = “71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f” , při svých voláních zaměňte tento API klíč za API klíč svého workspace, který získáte po objednání služby "Integrace API" a Generování API klíče.
V body je potřebný JSON se všemi parametry pro vytvoření dokumentu, url webhooku odpovídá webhooku vytvořeném dále, lze přidat po otestování tohoto flow.
E-mail demo+counterparty@signi.com si můžete změnit na svůj.
Code Block |
---|
{
"$content-type": "multipart/form-data",
"$multipart": [
{
"headers": {
"Content-Disposition": "form-data; name=\"metadata\"; filename=\"data.json\""
},
"body": {
"name": "test",
"number": "123456",
"locale": "cs",
"webhooks": [
{
"state": "completed",
"url": "https://prod-174.westeurope.logic.azure.com:443/workflows/4255c88e046844319c27fdf997ee7eed/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=lJhO1j7pXPUUzQ6apYhS1TJmI6HoEyN4NS_cBMI-6rw"
}
],
"settings": {
"signing_order": "one_at_a_time",
"missing_positions": "append_to_the_end"
},
"people": [
{
"is_proposer": true,
"party_order": 1,
"email": "demo@signi.com",
"contract_role": "sign"
},
{
"is_proposer": false,
"party_order": 2,
"email": "demo+counterparty@signi.com",
"phone": "723653670",
"first_name": "John",
"last_name": "Doe#1",
"contract_role": "sign",
"person_type": "nature"
}
],
"file": "file_key"
}
},
{
"headers": {
"Content-Disposition": "form-data; name=\"file_key\"; filename=\"test.pdf\""
},
"body": {
"$content-type": "application/pdf",
"$content": "@{body('Get_file_content')?['body']}"
}
}
]
} |
v JSONu se potřebujeme odkázat na soubor získaný v předchozím kroku , k tomu použijeme dynamický obsah File Content.
...
….
...
Další průběh testování je shodný s flow pro vytvoření dokumentu ze vzoru.
Vytvoření flow pro webhook pro přijetí výsledku podepsání
Vytvořte nové flow přes MS Power Automate v levém panelu > Create > Instant cloud flow pro ruční spuštění > Manually create flow.
Vložte do flow operaci přes Next step > When an HTTP request is received (vybrat tento typ operace).
...
Jako šablonu dat, které webhook dostane, je třeba vložit příklad JSONu viz příklad na https://signi.docs.apiary.io/#reference/webhooky/ze-vzoru-s-prilohami tj,
Code Block |
---|
{
"type": "object",
"properties": {
"contract_id": {
"type": "integer"
},
"state": {
"type": "string"
},
"file": {
"type": "string"
},
"attachments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"contract_id": {
"type": "integer"
},
"state": {
"type": "string"
},
"file": {
"type": "string"
}
},
"required": [
"contract_id",
"state",
"file"
]
}
}
}
}
|
...
Jako druhá je do flow vložená operace Parse JSON , kde se řekne, že se bude zpracovávat kód z Body a jako příklad JSON schématu se bere to, co dostává webhook ze Signi viz výše. Zároveň se ikonou Copy získá URL webhooku , který se následně vyplní jako parametr volání Signi v prvním a druhém flow příkladu.
...
Výsledek volání webhooku lze zjistit v MS Power Automate v historii flow Signi Demo - webhook, na stránce detailu dole zobrazit v historii poslední volání , kde jsou vidět výsledky volání.
...
Table of Contents | ||||
---|---|---|---|---|
|
Příklad kódu v .NET
.NET je prostředí, framework Microsoftu pro vývoj aplikací.
Na produkčním prostředí Signi je workspace "Demo API" a má API klíč = “71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f” , při svých voláních zaměňte tento API klíč za API klíč svého workspace, který získáte po objednání služby "Integrace API" a Generování API klíče.
Pro Pro zasílání HTTP požavavků se využívá knihovna RestSharp, https://restsharp.dev/
Níže jsou volání různých enpointů Signi API.
Code Block |
---|
using Art.Gaia;
using Art.IDocuments.Models;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Text;
using BE = Art.BusinessEntity;
namespace Art.IDocuments.Logic
{
public class AnnotationLogic
{
public Base _base;
public AnnotationLogic(Base myBase)
{
_base = myBase;
}
// Upload From File
public string Upload(EntityReference dokumentReference)
{
try
{
BE.art_idokument dokument = _base.Service.Retrieve(BE.art_idokument.EntityLogicalName, dokumentReference.Id,
new ColumnSet(BE.art_idokument.Attr.art_customerid.LogicalName, BE.art_idokument.Attr.art_name.LogicalName, BE.art_idokument.Attr.art_sablonaid.LogicalName)).ToEntity<BE.art_idokument>();
BE.art_idokumentsablona sablona = _base.Service.Retrieve(dokument.art_sablonaid.LogicalName, dokument.art_sablonaid.Id,
new ColumnSet(BE.art_idokumentsablona.Attr.art_emailautor.LogicalName, BE.art_idokumentsablona.Attr.art_mistopodpisu.LogicalName, BE.art_idokumentsablona.Attr.art_spolecnost.LogicalName, BE.art_idokumentsablona.Attr.art_stranapospisu.LogicalName)).ToEntity<BE.art_idokumentsablona>();
BE.contact contact = _base.Service.Retrieve(BE.contact.EntityLogicalName, dokument.art_customerid.Id,
new ColumnSet(BE.contact.Attr.firstname.LogicalName, BE.contact.Attr.lastname.LogicalName, BE.contact.Attr.emailaddress1.LogicalName, BE.contact.Attr.mobilephone.LogicalName, BE.contact.Attr.address1_line1.LogicalName, BE.contact.Attr.description.LogicalName)).ToEntity<BE.contact>();
QueryExpression queryAnno = new QueryExpression
{
EntityName = BE.annotation.EntityLogicalName,
NoLock = true,
TopCount = 1,
ColumnSet = new ColumnSet(BE.annotation.Attr.filename.LogicalName, BE.annotation.Attr.mimetype.LogicalName, BE.annotation.Attr.documentbody.LogicalName),
Criteria = new FilterExpression(LogicalOperator.And)
{
Conditions =
{
new ConditionExpression(BE.annotation.Attr.objectid.LogicalName,ConditionOperator.Equal,dokument.Id)
}
}
};
List<BE.annotation> annotations = _base.Service.RetrieveMultiple<BE.annotation>(queryAnno);
if (annotations.Count == 0) return "Žádné přílohy";
BE.annotation anno = annotations[0];
byte[] bytes = Convert.FromBase64String(anno.documentbody);
if (anno.filename.Contains("html"))
{
byte[] data = Convert.FromBase64String(anno.documentbody);
string decodedString = Encoding.UTF8.GetString(data);
string newBodyText = decodedString.Replace("{data_z_dynamics1}", contact.description).Replace("{data_z_dynamics2}", contact.address1_line1);
bytes = Encoding.UTF8.GetBytes(newBodyText);
}
// Dokument stažený z Dynamics 365 DB
var client = new RestClient("https://api.signi.com/api/v1/contract/sign/provided")
{
Timeout = -1
};
//client.UseNewtonsoftJson();
var request = new RestRequest(Method.POST);
//request.UseNewtonsoftJson();
request.AddHeader("x-api-key", "71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddParameter("email_author", sablona.art_emailautor);
request.AddParameter("email_signer", contact.emailaddress1);
request.AddParameter("phone_signer", contact.mobilephone);
request.AddParameter("firstname_signer", contact.firstname);
request.AddParameter("lastname_signer", contact.lastname);
request.AddParameter("proposer_sign", "true");
request.AddParameter("negotiator_sign", "true");
request.AddParameter("contract_name", dokument.art_name);
request.AddParameter("contract_number", dokument.art_cislodokumentu);
request.AddParameter("sign_date", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
request.AddParameter("sign_place", sablona.art_mistopodpisu);
request.AddParameter("last_document", "true");
request.AddParameter("person_type", "legal");
//request.AddParameter("date_of_birth", "1970-04-16");
//request.AddParameter("street", "5. května 67");
//request.AddParameter("city", "Libčice nad Vltavou");
//request.AddParameter("zip_code", "25266");
request.AddParameter("company_name", sablona.art_spolecnost);
//request.AddParameter("ic", "28524322");
//request.AddParameter("dic", "CZ28524322");
//request.AddParameter("sign_proposer", "{\"position\": {\"x\": 15,\"y\": 84,\"page\": 0}}");
//request.AddParameter("sign_negotiator", "{\"position\": {\"x\": 78,\"y\": 84,\"page\": 0}}");
request.AddParameter("sign_proposer[position][x]", 8);
request.AddParameter("sign_proposer[position][y]", 84);
request.AddParameter("sign_proposer[position][page]", sablona.art_stranapospisu - 1);
request.AddParameter("sign_negotiator[position][x]", 64);
request.AddParameter("sign_negotiator[position][y]", 84);
request.AddParameter("sign_negotiator[position][page]", sablona.art_stranapospisu - 1);
request.AddParameter("webhooks[0][state]", "signed");
request.AddParameter("webhooks[0][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookSigned");
request.AddParameter("webhooks[1][state]", "rejected");
request.AddParameter("webhooks[1][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookRejected");
request.AddParameter("webhooks[2][state]", "expired");
request.AddParameter("webhooks[2][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookExpired");
request.AlwaysMultipartFormData = true;
request.AddFileBytes("file", bytes, anno.filename, anno.mimetype);
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
BE.art_idokument iDokumentUpdate = new BE.art_idokument
{
Id = dokument.Id,
art_id = JsonConvert.DeserializeObject<UploadDokumentResponseClass>(response.Content).ContractId,
art_idokumentid = dokument.Id,
statuscode = new OptionSetValue(BE.art_idokument.Attr.statuscode.Options.A_Odeslany_k_podpisu)
};
_base.Trace = true;
_base.Debug(iDokumentUpdate, "iDokumentUpdate");
iDokumentUpdate.Update(_base.Service);
return response.Content;
}
return response.Content;
}
catch (Exception e)
{
_base.Error(e, "Art.IDocuments.Logic.AnnotationLogic.Upload");
return e.Message;
}
}
// Upload From Template
public string UploadTemplate(EntityReference dokumentReference)
{
try
{
BE.art_idokument dokument = _base.Service.Retrieve(BE.art_idokument.EntityLogicalName, dokumentReference.Id,
new ColumnSet(BE.art_idokument.Attr.art_customerid.LogicalName, BE.art_idokument.Attr.art_name.LogicalName, BE.art_idokument.Attr.art_sablonaid.LogicalName)).ToEntity<BE.art_idokument>();
BE.art_idokumentsablona sablona = _base.Service.Retrieve(dokument.art_sablonaid.LogicalName, dokument.art_sablonaid.Id,
new ColumnSet(BE.art_idokumentsablona.Attr.art_emailautor.LogicalName, BE.art_idokumentsablona.Attr.art_mistopodpisu.LogicalName, BE.art_idokumentsablona.Attr.art_spolecnost.LogicalName, BE.art_idokumentsablona.Attr.art_stranapospisu.LogicalName)).ToEntity<BE.art_idokumentsablona>();
BE.contact contact = _base.Service.Retrieve(BE.contact.EntityLogicalName, dokument.art_customerid.Id,
new ColumnSet(BE.contact.Attr.firstname.LogicalName, BE.contact.Attr.lastname.LogicalName, BE.contact.Attr.emailaddress1.LogicalName, BE.contact.Attr.mobilephone.LogicalName, BE.contact.Attr.address1_line1.LogicalName, BE.contact.Attr.description.LogicalName)).ToEntity<BE.contact>();
QueryExpression queryAnno = new QueryExpression
{
EntityName = BE.annotation.EntityLogicalName,
NoLock = true,
TopCount = 1,
ColumnSet = new ColumnSet(BE.annotation.Attr.filename.LogicalName, BE.annotation.Attr.mimetype.LogicalName, BE.annotation.Attr.documentbody.LogicalName),
Criteria = new FilterExpression(LogicalOperator.And)
{
Conditions =
{
new ConditionExpression(BE.annotation.Attr.objectid.LogicalName,ConditionOperator.Equal,dokument.Id)
}
}
};
List<BE.annotation> annotations = _base.Service.RetrieveMultiple<BE.annotation>(queryAnno);
if (annotations.Count == 0) {
var client1 = new RestClient("https://api.signi.com/api/v1/contract/sign/template")
{
Timeout = -1
};
//client.UseNewtonsoftJson();
var request1 = new RestRequest(Method.POST);
//request.UseNewtonsoftJson();
request1.AddHeader("x-api-key", "71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f");
request1.AddHeader("Content-Type", "multipart/form-data");
request1.AddParameter("email_author", sablona.art_emailautor);
request1.AddParameter("email_signer", contact.emailaddress1);
request1.AddParameter("phone_signer", contact.mobilephone);
request1.AddParameter("firstname_signer", contact.firstname);
request1.AddParameter("lastname_signer", contact.lastname);
request1.AddParameter("proposer_sign", "true");
request1.AddParameter("negotiator_sign", "true");
request1.AddParameter("contract_name", dokument.art_name);
request1.AddParameter("contract_number", dokument.art_cislodokumentu);
request1.AddParameter("sign_date", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
request1.AddParameter("sign_place", sablona.art_mistopodpisu);
request1.AddParameter("last_document", "true");
request1.AddParameter("person_type", "legal");
//request.AddParameter("date_of_birth", "1970-04-16");
//request.AddParameter("street", "5. května 67");
//request.AddParameter("city", "Libčice nad Vltavou");
//request.AddParameter("zip_code", "25266");
request1.AddParameter("company_name", sablona.art_spolecnost);
//request.AddParameter("ic", "28524322");
//request.AddParameter("dic", "CZ28524322");
//request.AddParameter("sign_proposer", "{\"position\": {\"x\": 15,\"y\": 84,\"page\": 0}}");
//request.AddParameter("sign_negotiator", "{\"position\": {\"x\": 78,\"y\": 84,\"page\": 0}}");
//request.AddParameter("sign_proposer[position][x]", 8);
//request.AddParameter("sign_proposer[position][y]", 84);
//request.AddParameter("sign_proposer[position][page]", sablona.art_stranapospisu - 1);
//request.AddParameter("sign_negotiator[position][x]", 64);
//request.AddParameter("sign_negotiator[position][y]", 84);
//request.AddParameter("sign_negotiator[position][page]", sablona.art_stranapospisu - 1);
request1.AddParameter("webhooks[0][state]", "signed");
request1.AddParameter("webhooks[0][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookSigned");
request1.AddParameter("webhooks[1][state]", "rejected");
request1.AddParameter("webhooks[1][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookRejected");
request1.AddParameter("webhooks[2][state]", "expired");
request1.AddParameter("webhooks[2][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookExpired");
request1.AddParameter("template_id", 170);
request1.AddParameter("parameters", JsonConvert.SerializeObject( new[] { new { id = 411, value = contact.description } }));
//request1.AddParameter("parameters[0][id]", 411);
//request1.AddParameter("parameters[0][value]", contact.description);
IRestResponse response1 = client1.Execute(request1);
if (response1.StatusCode == System.Net.HttpStatusCode.OK)
{
BE.art_idokument iDokumentUpdate = new BE.art_idokument
{
Id = dokument.Id,
art_id = JsonConvert.DeserializeObject<UploadDokumentResponseClass>(response1.Content).ContractId,
art_idokumentid = dokument.Id,
statuscode = new OptionSetValue(BE.art_idokument.Attr.statuscode.Options.A_Odeslany_k_podpisu)
};
_base.Trace = true;
_base.Debug(iDokumentUpdate, "iDokumentUpdate");
iDokumentUpdate.Update(_base.Service);
return response1.Content;
}
return "Žádné přílohy";
}
BE.annotation anno = annotations[0];
byte[] bytes = Convert.FromBase64String(anno.documentbody);
//if (anno.filename.Contains("html"))
//{
// byte[] data = Convert.FromBase64String(anno.documentbody);
// string decodedString = Encoding.UTF8.GetString(data);
// string newBodyText = decodedString.Replace("{data_z_dynamics1}", contact.description).Replace("{data_z_dynamics2}", contact.address1_line1);
// bytes = Encoding.UTF8.GetBytes(newBodyText);
//}
// Dokument stažený z Dynamics 365 DB
var client = new RestClient("https://api.signi.com/api/v1/contract/sign/provided")
{
Timeout = -1
};
//client.UseNewtonsoftJson();
var request = new RestRequest(Method.POST);
//request.UseNewtonsoftJson();
request.AddHeader("x-api-key", "71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddParameter("email_author", sablona.art_emailautor);
request.AddParameter("email_signer", contact.emailaddress1);
request.AddParameter("phone_signer", contact.mobilephone);
request.AddParameter("firstname_signer", contact.firstname);
request.AddParameter("lastname_signer", contact.lastname);
request.AddParameter("proposer_sign", "true");
request.AddParameter("negotiator_sign", "true");
request.AddParameter("contract_name", dokument.art_name);
request.AddParameter("contract_number", dokument.art_cislodokumentu);
request.AddParameter("sign_date", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
request.AddParameter("sign_place", sablona.art_mistopodpisu);
request.AddParameter("last_document", "true");
request.AddParameter("person_type", "legal");
//request.AddParameter("date_of_birth", "1970-04-16");
//request.AddParameter("street", "5. května 67");
//request.AddParameter("city", "Libčice nad Vltavou");
//request.AddParameter("zip_code", "25266");
request.AddParameter("company_name", sablona.art_spolecnost);
//request.AddParameter("ic", "28524322");
//request.AddParameter("dic", "CZ28524322");
//request.AddParameter("sign_proposer", "{\"position\": {\"x\": 15,\"y\": 84,\"page\": 0}}");
//request.AddParameter("sign_negotiator", "{\"position\": {\"x\": 78,\"y\": 84,\"page\": 0}}");
request.AddParameter("sign_proposer[position][x]", 8);
request.AddParameter("sign_proposer[position][y]", 84);
request.AddParameter("sign_proposer[position][page]", sablona.art_stranapospisu - 1);
request.AddParameter("sign_negotiator[position][x]", 64);
request.AddParameter("sign_negotiator[position][y]", 84);
request.AddParameter("sign_negotiator[position][page]", sablona.art_stranapospisu - 1);
request.AddParameter("webhooks[0][state]", "signed");
request.AddParameter("webhooks[0][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookSigned");
request.AddParameter("webhooks[1][state]", "rejected");
request.AddParameter("webhooks[1][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookRejected");
request.AddParameter("webhooks[2][state]", "expired");
request.AddParameter("webhooks[2][url]", "https://artidocumentswebapi.azurewebsites.net/IDocument/WebHookExpired");
request.AlwaysMultipartFormData = true;
request.AddFileBytes("file", bytes, anno.filename, anno.mimetype);
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
BE.art_idokument iDokumentUpdate = new BE.art_idokument
{
Id = dokument.Id,
art_id = JsonConvert.DeserializeObject<UploadDokumentResponseClass>(response.Content).ContractId,
art_idokumentid = dokument.Id,
statuscode = new OptionSetValue(BE.art_idokument.Attr.statuscode.Options.A_Odeslany_k_podpisu)
};
_base.Trace = true;
_base.Debug(iDokumentUpdate, "iDokumentUpdate");
iDokumentUpdate.Update(_base.Service);
return response.Content;
}
return response.Content;
}
catch (Exception e)
{
_base.Error(e, "Art.IDocuments.Logic.AnnotationLogic.Upload");
return e.Message;
}
}
// Download Document
public void DownloadTest()
{
BE.annotation anno = (BE.annotation)_base.Service.Retrieve(BE.annotation.EntityLogicalName, new Guid("54DC0A3F-75A5-EA11-A812-000D3AB7AF7A"), new ColumnSet(true));
RestClient client = new RestClient("https://api.signi.com/api/v1/contract/2842/download");
client.AddDefaultHeader("x-api-key", "71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f");
client.AddDefaultHeader("Content-Type", "application/json");
IRestRequest request = new RestRequest
{
Method = Method.GET
};
IRestResponse response = client.Get(request);
string fileBase64 = Convert.ToBase64String(response.RawBytes); //fileBase64 - serializovaný soubr, který je možné uložit do DB
}
public string Download(EntityReference dokumentReference)
{
try
{
string output = "OK";
BE.art_idokument dokument = _base.Service.Retrieve(BE.art_idokument.EntityLogicalName, dokumentReference.Id,
new ColumnSet(BE.art_idokument.Attr.art_customerid.LogicalName, BE.art_idokument.Attr.art_name.LogicalName, BE.art_idokument.Attr.art_sablonaid.LogicalName, BE.art_idokument.Attr.art_id.LogicalName)).ToEntity<BE.art_idokument>();
QueryExpression queryAnno = new QueryExpression
{
EntityName = BE.annotation.EntityLogicalName,
NoLock = true,
TopCount = 1,
ColumnSet = new ColumnSet(BE.annotation.Attr.filename.LogicalName),
Criteria = new FilterExpression(LogicalOperator.And)
{
Conditions =
{
new ConditionExpression(BE.annotation.Attr.objectid.LogicalName,ConditionOperator.Equal,dokument.Id)
}
}
};
List<BE.annotation> annotations = _base.Service.RetrieveMultiple<BE.annotation>(queryAnno);
if (annotations.Count == 0) return "Žádné přílohy";
BE.annotation anno = annotations[0];
RestClient client = new RestClient($"https://api.signi.com/api/v1/contract/{dokument.art_id}/download");
client.AddDefaultHeader("x-api-key", "71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f");
client.AddDefaultHeader("Content-Type", "application/json");
IRestRequest request = new RestRequest
{
Method = Method.GET
};
IRestResponse response = client.Get(request);
string fileBase64 = Convert.ToBase64String(response.RawBytes);
BE.annotation annotation = new BE.annotation
{
objectid = dokumentReference,
documentbody = fileBase64,
subject = $"Podepsaný dokument: {dokument.art_name}",
filename = $"{anno.filename}_podpis.pdf"
};
annotation.Create(_base.Service);
return output;
}
catch (Exception e)
{
_base.Error(e, "Art.IDocuments.Logic.AnnotationLogic.Download");
return e.Message;
}
}
}
}
|
Příklad kódu v VBA
Visual Basic for Application je vývojový jazyk používaný v desktopových verzích Microsoft Office . Není již podporován v cloudovém prostředí Office 365.
Na produkčním prostředí Signi je workspace "Demo API" a má API klíč = “71c4123d242bdd38047bee838d17e3367dc3ea6748d0975217ce501e834a224c83cab8afd35c9b0e6ade806b7987fae80f97f5c8253cfbb9089cf21f” , při svých voláních zaměňte tento API klíč za API klíč svého workspace, který získáte po objednání služby "Integrace API" a Generování API klíče.
Je třeba kód spouštět Micrisoft Excel for Desktop na MS Windows. Na cloudovém prostředí MS 356 nefugnují makrave VBA, v Microsoft Execl for Mac není přístupný objekt pro HTTP requesty.
Code Block |
---|
Sub FillTemplateAndSend()
Dim URL As String
Dim JSONString As String
Dim RowString As String
Dim objHTTP As New WinHttpRequest
Dim ConfProposerEmail As String
Dim ConfAPIKey As String
Dim ConfMapping As String
Dim ConfURL As String
Dim i As Integer
Dim ContractFrom As Integer
Dim ContractTo As Integer
Dim Contracts As Range
Dim SigniID As String
Dim ResponseText As String
Dim TemplateNo As Integer
Dim TemplateRow As Integer
'Načtení parametrů konfigurace
ConfURL = "https://api.signi.com/api/v1/contract/?type=template"
ConfAPIKey = Worksheets("Config").Range("C6").Value
ContractFrom = 5 'první řádek na kterém jsou data
ContractTo = Worksheets("Data").UsedRange.Rows.Count 'poslední řádek na kterém jsou data
objHTTP.Open "POST", ConfURL, False
objHTTP.SetRequestHeader "x-api-key", ConfAPIKey
objHTTP.SetRequestHeader "Content-Type", "application/json"
'procházení řádků , posílání do Signi a aktualizace řádků
For i = ContractFrom To ContractTo
If UCase(Worksheets("Data").Range("A" & i).Value) = "ODESLAT" Then
TemplateNo = Worksheets("Data").Range("B" & i).Value
If IsNumeric(TemplateNo) Then
RowString = Worksheets("Config").Range("C" & (TemplateNo + 10)).Value
RowString = Replace(RowString, "#proposeremail#", Worksheets("Config").Range("C7").Value)
RowString = Replace(RowString, "#state#", Worksheets("Config").Range("C8").Value)
RowString = Replace(RowString, "#locale#", Worksheets("Config").Range("C9").Value)
If TemplateNo = "1" Then
RowString = Replace(RowString, "#contract_name#", Worksheets("Data").Range("E" & i).Value)
RowString = Replace(RowString, "#number#", Worksheets("Data").Range("F" & i).Value)
RowString = Replace(RowString, "#firstname#", Worksheets("Data").Range("G" & i).Value)
RowString = Replace(RowString, "#lastname#", Worksheets("Data").Range("H" & i).Value)
RowString = Replace(RowString, "#email#", Worksheets("Data").Range("I" & i).Value)
RowString = Replace(RowString, "#phone#", Worksheets("Data").Range("J" & i).Value)
RowString = Replace(RowString, "#112#", Worksheets("Data").Range("K" & i).Value)
RowString = Replace(RowString, "#122#", Worksheets("Data").Range("L" & i).Value)
RowString = Replace(RowString, "#131#", Worksheets("Data").Range("M" & i).Value)
RowString = Replace(RowString, "#411#", Worksheets("Data").Range("N" & i).Value)
RowString = Replace(RowString, "#421#", Worksheets("Data").Range("O" & i).Value)
RowString = Replace(RowString, "#431#", Worksheets("Data").Range("P" & i).Value)
End If
objHTTP.Send RowString
ResponseText = objHTTP.ResponseText
ResponseText = Replace(ResponseText, "{""contract_id"":", "")
If InStr(ResponseText, """attachments""") >= 2 Then
SigniID = Left(ResponseText, InStr(ResponseText, """attachments""") - 2)
Else
SigniID = ResponseText 'pokud chybí text "attachements", předpokládá se, že došlo k chybě
End If
Worksheets("Data").Range("D" & i) = RowString ' JSON použitý pro volání
Worksheets("Data").Range("C" & i) = SigniID
Worksheets("Data").Range("A" & i).Value = "Odesláno"
End If
End If
Next i
Dim Z As String
End Sub
Sub ReadStatus()
Dim ConfURL As String
Dim ConfAPIKey As String
Dim URL As String
Dim SigniID As String
Dim ResponseText As String
Dim i As Integer
Dim ContractFrom As Integer
Dim ContractTo As Integer
Dim objHTTP As New WinHttpRequest
'Načtení parametrů konfigurace
ConfAPIKey = Worksheets("Config").Range("C6").Value
ConfURL = "https://api.signi.com/api/v1/contract/"
ContractFrom = 5
ContractTo = Worksheets("Data").UsedRange.Rows.Count
'procházení řádků , posílání do Signi a aktualizace řádků
For i = ContractFrom To ContractTo
SigniID = Worksheets("Data").Range("B" & i).Value 'Načtení SigniID ze sloupce D
If IsNumeric(SigniID) And Not (IsEmpty(SigniID)) Then 'když je hodnota numerická a neprázdná tj.j. je v ní pravděpodobně smysluplné ContractID
URL = ConfURL & SigniID
objHTTP.Open "GET", URL, False
objHTTP.SetRequestHeader "x-api-key", ConfAPIKey
objHTTP.SetRequestHeader "Content-Type", "application/json"
objHTTP.Send
ResponseText = objHTTP.ResponseText
If InStr(ResponseText, """pending""") > 0 Then
Worksheets("Data").Range("A" & i).Value = "Rozesláno"
ElseIf InStr(ResponseText, """completed""") > 0 Then
Worksheets("Data").Range("A" & i).Value = "Podepsáno"
ElseIf InStr(ResponseText, """expired""") > 0 Then
Worksheets("Data").Range("A" & i).Value = "Uplynula doba"
ElseIf InStr(ResponseText, """refused""") > 0 Then
Worksheets("Data").Range("A" & i).Value = "Odmítnuto"
End If
End If
Next i
End Sub
|