- Přímé volání Signi API
- Příklad volání Signi API z MS Power Automate
- Příklad kódu v .NET
- Příklad kódu v VBA
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 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 tří flow:
Signi Demo - Podepsání dokumentu ze vzoru- vyvolá podpis dokumentu vytvořeného ze vzoru “Testovací smlouva k 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.
Příkladová flow v MS Power Automate.
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.
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
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 dále, lze přidat po otestování tohoto flow.
E-mail demo+counterparty@signi.com si můžete změnit na svůj.
{ "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 podepsání PDF souboru
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.
Ve flow pro podepsání PDF souboru je třeba nejprve do flow získat soubor k podpisu, zde používáme 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.
{ "$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://app.swaggerhub.com/apis-docs/Signi/Signi/1.3.3/#/Contract/post_api_v1_contract_ 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á 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í.
- Přímé volání Signi API
- Příklad volání Signi API z MS Power Automate
- Vytvoření flow pro podepsání dokumentu ze vzoru
- Vytvoření flow pro podepsání PDF souboru
- Vytvoření flow pro webhook pro přijetí výsledku podepsání
- Příklad kódu v .NET
- Příklad kódu v VBA
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.
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 nefugují 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
Byl tento článek užitečný?
To je skvělé!
Děkujeme Vám za zpětnou vazbu
Je ním líto, že jsme vám nepomohli
Děkujeme Vám za zpětnou vazbu
Zpětná vazba odeslána
Oceňujeme vaši snahu a pokusíme se článek opravit