Asynchronní podepisování souborů pomocí formuláře

Krok č. 1) Přihlášení

Pro přístup k API je nutné nejprve získat přístupový token pomocí koncového bodu pro přihlášení externího informačního systému pod identitou konkrétního uživatele.

Koncový bod: /api/sofa/v1/auth/extis/login-impersonate

Metoda: POST

Hlavičky:

  • Accept: application/json

  • Content-Type: application/json

Parametry:

  • login … uživatelské jméno externího informačního systému.

  • password … heslo externího informačního systému.

  • impersonateUserId … LDAP identifikátor uživatele, jehož identitou má externí informační systém vystupovat (návod na zjištění tohoto identifikátoru je uveden v kapitole Postupy).

Příklad:

POST /api/sofa/v1/auth/extis/login-impersonate HTTP/1.1
Host: sofaws.602.cz
Accept: application/json
Content-Length: …
Content-Type: application/json

{
  "login": "48a0ecdd540849f0af416307406467f0",
  "password": "wau3S99vx2d_NW2P",
  "impersonateUserId": "9e5f2f76-fff5-44c3-b943-06a95fdc08e2"
}

Výsledek:

{
  "token": "eyJhbGciOiJBMjU2…"
}

Krok č. 2) Nahrání souborů

V dalším kroku je nutné nahrát dokumenty jeden po druhém do výchozího úložiště (default) pomocí koncového bodu File API. Výsledkem bude seznam identifikátorů souborů použitý v dalším kroku.

Koncový bod: /api/sofa/v2/file?storeId=default

Metoda: POST

Hlavičky:

  • Accept: application/json

  • Authorization: Bearer <token>

  • Content-Type: multipart/form-data

Parametry:

  • file … soubor dokumentu (ve verzi 2.0 se již nepoužívá hlavička FileId s parametry kódovanými ve formátu JSON, ale přenáší se standardní cestou pro upload souborů podle RFC 2854, tzn. že se název souboru uvádí v hlavičce Content-Disposition, velikost souboru v hlavičce Content-Length a typ souboru v hlavičce Content-Type).

Příklad:

POST /api/sofa/v2/file?storeId=default HTTP/1.1
Host: sofaws.602.cz
Accept: application/json
Authorization: Bearer eyJhbGciOiJBMjU2…
Content-Length: …
Content-Type: multipart/form-data; boundary="-----086735ab-f408-405e-9628-4eb525d56d71"

-------086735ab-f408-405e-9628-4eb525d56d71
Content-Disposition: form-data; name="file"; filename="Document.pdf"
Content-Length: …
Content-Type: application/pdf

…binary file content…
-------086735ab-f408-405e-9628-4eb525d56d71--

Výsledek:

{
  "fileId": "eyJhbGciOiJIUzI1…"
}

Krok č. 3) Spuštění agendy

Pro spuštění podpisové agendy je nutné zavolat koncový bod GraphQL API s mutací pro zahájení agendy zprávou, které předáme identifikátor zprávy, identifikátor agendy (návod na zjištění tohoto identifikátoru je uveden v kapitole Postupy), seznam identifikátorů dokumentů z předchozího kroku, případně další JSON data nebo globální proměnné, pokud agenda nějaké používá. Výsledkem bude URL pro zobrazení podpisové agendy a seznam globálních proměnných, z nichž jedna bude použita pro URL, pomocí které lze čekat na dokončení operace.

JSONPath pro získání URL podpisové agendy pro přesměrování uživatele:

$.data.processes.sendMessageToAgendaEx.url

JSONPath pro získání URL pro zjištění výsledku operace/podepisování:

$.data.processes.sendMessageToAgendaEx.instance.variables[?(@.name == 'jobOperationUrl')].valueString
Mutaci lze samozřejmě měnit dle potřeby. Níže uvedená varianta představuje minimalistickou verzi, která vrací pouze hodnoty potřebné pro zobrazení agendy a čekání na dokončení operace.

Koncový bod: /api/sofa/v1/graphql

Metoda: POST

Hlavičky:

  • Accept: application/json

  • Authorization: Bearer <token>

  • Content-Type: application/json

GraphQL operace:

mutation startAgenda(
  $messageIdent: String!
  $agendaIdent: String!
  $fileIds: [File_Id!]!
) {
  processes {
    sendMessageToAgendaEx(
      messageIdent: $messageIdent
      agendaIdent: $agendaIdent
      fileIds: $fileIds
    ) {
      instance {
        variables {
          name
          type
          valueString
        }
      }
      url
    }
  }
}

Příklad:

POST /api/sofa/v1/graphql HTTP/1.1
Host: sofaws.602.cz
Accept: application/json
Authorization: Bearer eyJhbGciOiJBMjU2…
Content-Length: …
Content-Type: application/json

{
  "operationName": "startAgenda",
  "query": "mutation startAgenda(…",
  "variables": {
    "agendaIdent": "sys_agenda_signpoint_sdk",
    "messageIdent": "sys_start_template",
    "fileIds": [
      "eyJhbGciOiJIUzI1…"
    ]
  }
}

Výsledek:

{
  "data": {
    "processes": {
      "sendMessageToAgendaEx": {
        "instance": {
          "variables": [
            {
              "name": "jobOperationUrl",
              "type": "STRING",
              "valueString": " https://sofa.602.cz/api/sofa/v1/operations/job?wait=true&operationToken=eyJhbGciOiJIUzI1…"
            },
            {
              "name": "jobOperationIdent",
              "type": "STRING",
              "valueString": "c0cdc7ed-d54c-457c-9f1e-c69bf5e8cd09"
            },
            {
              "name": "configSignatureWidth",
              "type": "STRING",
              "valueString": "300"
            },
            {
              "name": "configSignatureHeight",
              "type": "INTEGER",
              "valueString": null
            },
            {
              "name": "configSignaturePlaceholder",
              "type": "STRING",
              "valueString": "SIGN2"
            },
            {
              "name": "configUsePlaceholder",
              "type": "BOOLEAN",
              "valueString": null
            }
          ]
        },
        "url": "https://sofa.602.cz/GuestUser/GuestLogin?Token=eyJhbGciOiJIUzI1…"
      }
    }
  }
}

Krok č. 4) Zobrazení agendy

Nejjednodušším krokem celého postupu je zobrazení agendy uživateli, kdy se pouze v prohlížeči otevře URL pro zobrazení agendy z předchozího kroku.

Příklad:

https://sofa.602.cz/GuestUser/GuestLogin?Token=eyJhbGciOiJIUzI1…

Krok č. 5) Čekání na dokončení operace

Před stažením dokumentů opatřených podpisem je potřeba nejprve počkat, dokud uživatel požadované dokumenty nepodepíše. K tomu slouží URL adresa z výsledku GraphQL mutace z předchozího kroku, která vede na koncový bod Job Operations API, které slouží pro získání stavu probíhajících dlouhotrvajících operací. V případě zmíněné URL adresy se pro zjednodušení jedná o synchronní volání, tzn. že koncový bod nevrací výsledek ihned, ale snaží se počkat co nejdéle na dokončení probíhající operace. V případě chyby, dokončení operace nebo vypršení časového limitu se vrátí výsledek, který obsahuje stavovou informaci (state), která může nabývat jednu z následujících hodnot:

  • done – operace byla úspěšně dokončena.

  • canceled – operace byla zrušena (uživatel zavřel formulář bez podepsání dokumentů).

  • error – došlo k chybě.

  • pending – operace stále probíhá.

  • deleted - vypršela platnost operace (doba platnosti: 4 hodiny).

JSONPath pro získání stavu operace/podepisování:

$.state

JSONPath pro získání seznamu souborů (platné pouze pro stav done):

$.data.documents

Kromě stavu pending jsou všechny ostatní stavy konečné, tzn. že nemá smysl koncový bod volat znovu. V případě úspěšného dokončení operace (done) se navíc vrací strukturovaná data ve formátu JSON, která obsahují výsledek operace (závislý na agendě) obsahující identifikátory dokumentů opatřených podpisem doplněné o identifikátory původních dokumentů kvůli spárování.

Koncový bod: /api/sofa/v1/operations/job

Metoda: GET

Hlavičky:

  • Authorization: Bearer <token>

Příklad:

GET /api/sofa/v1/operations/job?wait=true&operationToken=eyJhbGciOiJIUzI1…
Host: sofaws.602.cz
Authorization: Bearer eyJhbGciOiJBMjU2…

Výsledek v případě úspěšného dokončení operace:

{
  "id": "c0cdc7ed-d54c-457c-9f1e-c69bf5e8cd09",
  "type": "process-application",
  "state": "done",
  "data": {
    "documents": [
      {
        "signedFileId": "eyJhbGciOiJIUzI1…",
        "originalFileId": "eyJhbGciOiJIUzI1…",
        "filename": "Document.pdf",
        "orginalFilename": "Document.pdf"
      }
    ]
}

Výsledek v případě stále probíhající operace:

{
  "id": "c0cdc7ed-d54c-457c-9f1e-c69bf5e8cd09",
  "type": "process-application",
  "state": "pending",
  "data": null
}

Výsledek v případě zavření formuláře:

{
  "id": "c0cdc7ed-d54c-457c-9f1e-c69bf5e8cd09",
  "type": "process-application",
  "state": "canceled",
  "data": null
}

Výsledek v případě chyby:

{
  "id": "c0cdc7ed-d54c-457c-9f1e-c69bf5e8cd09",
  "type": "process-application",
  "state": "error",
  "data": null
}

Krok č. 6) Stažení souborů

Posledním krokem je stažení podepsaných souborů jeden po druhém pomocí koncového bodu File API:

Koncový bod: /api/sofa/v2/file

Metoda: GET

Hlavičky:

  • Authorization: Bearer <token>

Parametry:

  • fileId … identifikátor stahovaného dokumentu.

Příklad:

GET /api/sofa/v2/file?fileId=eyJhbGciOiJIUzI1…
Host: sofaws.602.cz
Authorization: Bearer eyJhbGciOiJBMjU2…

Výsledek:

Výsledkem je stahovaný dokument.

Název souboru lze získat buď standardně z hlavičky Content-Disposition, nebo File API v2 nastavuje pro snazší zpracování hlavičku X-Sofa-FileName.