Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
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ů: 

  1. Předání dokumentu ve formě souboru k podpisu

  2. Seznam dokumentů

  3. Stav dokumentu

  4. Stažení dokumentu

  5. Stažení auditní stopy / kontrolního listu dokumentu

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

  1. Microsoft Power Automate,

  2. kód v .NET,

  3. 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 - Webhook - vytvoří v prostředí MS 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.

...

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řit 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 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 v dalším krokudále, lze přidat po otestování tohoto flow.

...

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"
      }
    ]
  }
}

...

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: 

...

}

...

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ží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řit 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žit Vložte do flow operaci přes Next step > When an HTTP request is received  (vybrat tento typ operace).

...

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á 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
minLevel1
maxLevel7

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.

...