Přímé volání 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 / workspace, do kterého budete dokumenty k podpisu předávat viz Generování API klíče. Volat můžete z kterýkoliv End Pointů Signi API.
Příklad volání Signi API z MS Power Automate
Příklad volání Signi API z MS Power Automate se skládá ze dvou flow
Signi Demo - Předání podkladů pro vzor - vyvolá podpis dokumentu vytvořeného ze vzoru Testovací smlouva k podpisu v testovacím workspace Demo API
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.
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.
Vytvoření flow pro podepsání dokumentu ze vzoru v Signi
Vytvořit nové flow přes MS Power Automate > Create (v levém panelu) > Instant cloud flow (pro ruční spuštění ) > Manually create flow.
Vložit do flow operaci přes Next step > HTTP (vybrat tento typ operace).
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 POST
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 kroku, lze přidat po otestování tohoto flow.
{ "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" } ] } }
Uložit flow přes Save.
Pro testování zvolit Test a Run Flow .
Výsledek odpovědi Signi API na požadavek přístupný v MS Power Automate:
Vytvoření flow pro webhook pro přijetí výsledku podepsání
Vytvořit 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ž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,
{ "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í.
Příklad kódu v .NET
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.
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
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.
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