Porovnat verze

Klíč

  • Tento řádek byl přidán.
  • Tento řádek byl odstraněn.
  • Formátování bylo změněno.
AApiComPREM

ApiComPREM


Api (application programming interface) - aplikačné programové rozhranie (API) je súbor definícií podprogramov, komunikačných protokolov a nástrojov pre vývoj softvéru.

Com (communication) - z latinského communicare, čo znamená "zdieľať",

Prem - program Premier,

ApiComPrem - komunikačný nástroj pre zdieľanie dát v programe Premier.


Aplikácia slúži pre softvér tretích strán, ktoré majú možnosť priamo komunikovať s programom Premier.

ApiComPrem komunikuje cez protokol HTTP 1.1 metódou POST. Odosielané a prijaté dáta sú vo formáte JSON.

JavaScript Object Notation (javascriptový objektový zápis, JSON) je spôsob zápisu dát (dátový formát) nezávislý na počítačovej platforme, určený pre prenos dát, ktoré môžu byť organizované v poliach alebo zoskupené v objektoch. Vstupom je ľubovoľná dátová štruktúra (číslo, reťazec, boolean, objekt alebo z nich zložene pole), výstupom je vždy reťazec. Zložitosť hierarchie vstupnej premennej nie je teoreticky nijako obmedzená.

Header (hlavička HTTP):

POST /api/comm HTTP/1.1
Content-Type: application/json; charset=utf-8
Authorization: Basic Z3JhczpncjE3
ID-UJ: c8175fe2-5aba-460e-a492-5da487105394
Content-Length: xy
{
        JSON command
}


Authorization                   Meno a heslo používateľa z programu Premier vo formáte Base64.

ID-UJ                                 nastavenie ID účtovnej jednotky na servery HTTP

Content-Length              dĺžka odoslaných dát (JSON command)


Všeobecný popis ApiComPrem súborov


ApiComPrem.dll

  • trieda volania HTTP / HTTPS, server
  • komunikácia s SQL
  • jednoduché SQL procedúry (select)
  • registrovanie CLR SQL procedúr cez AutoRegisterAsm
  • podpora pre VFP (čítanie DBF tabuliek, mem súborov, volanie procedúr z VFP, ...)
  • štruktúry tried
  • štruktúry tabuliek
  • triedy pre JSON
  • šifrovanie hesiel
  • práca s certifikátmi
  • čítanie Premier licencie
  • ...

ApiComPremForm.exe

  • nastavenie komunikácie (funguje iba s SQL verziou programu Premier)
  • nastavenie účtovných jednotiek
  • testovací server pre vývojárov
  • testovací formulár pre vývojárov

ApiComPremSql.dll

  • CLR SQL procedúry

ApiComService.exe

  • windows služba pre volanie ApiComPrem.dll
  • podpora pre inštalovanie a odinštalovanie služby

ApiComPremUpdate.exe

  • aktualizácia ApiComPrem z FTP
  • podpora automatického spustenia na pozadí

setup.xml

  • uložená konfigurácia ApiComPrem

Newtonsoft.Json.dll

JSON command


Používajú sa dva typy príkazov:

  • OUT -čítanie dát z API servera
  • IN - zapisovanie dát na API server

OUT príkaz (výstupný formát)

Formát HTTP_OUT

  • Result
  • CommandIn
  • Error
    • { row }
      • number
      • desc
      • Warning
        • { row }
          • desc
          • help
          • Data
            •  vráti JSON dáta v závislosti od príkazu

Príklad načítania zoznamu všetkých príkazov s popisom použitia


Blok kódu
languagejs
{ "command": {
    "inComm": "INFO",
    "inParam": {
      "parameters": {
        "prikaz": "FULL"
      } } } }


inComm - názov príkazu

inParam - parametre príkazu, ktoré sa líšia podľa požadovaného inComm


Vrátený JSON v prípade úspešného načítania (RESULT – OK)

CommandIn - vrátený poslaný príkaz

Data - vrátí dáta podľa typu príkazu

Blok kódu
languagejs
{ "Result":"OK",
    "CommandIn":"INFO",
    "Data":
    [ {
            "CommList":
            [ {
                    "INFO":
                    {
                        "ID": 100,
                        "nazov": "INFO",
                        "pouziva_param": true,
                        "parametre":
                        [ {
                                "name": "table_name",
                                "is_required": false,
                                "desc": "nazov tabulky pre nacitanie struktury",
                                "format": "S",
                                "order": 0
                            }, {
                                "name": "prikaz",
                                "is_required": false,
                                "desc": "informacie o prikaze (FULL - posle vsetky)",
                                "format": "S",
                                "order": 0
                            } ],
                        "popis": "nacitanie inform.udajov",
                        "typ_prikazu": "OUT"
                    } },


Keď nastane chyba v spracovaní (RESULT - ERR)


Error - číslo a popis chyby. API nepošle žiadne pole "Data"
Warning - upozorní na nesprávne naplnené parametre, a v prípade, že RESULT = OK, tak polia Data sú vytvorené. Warning môže mať viac riadkov

Blok kódu
languagejs
{ "Result":"ERR",
    "CommandIn":"INFO",
    "Error":
    [  {
            "number":502,
            "desc":"Tabulka sa nenasla."
        } ],
    "Warning":
    [
        {
            "desc":"chyba spracovanie SQL stru.tabulky [Exception Type: System.Data.SqlClient.SqlException, Message: Invalid object name 'SDFASFA'.]]"
        } ] }

K príkazu command sa môže pridať príkaz "queryFields" ,ktorý určuje vrátené polia použitých tabuliek povolených v inComm:

Blok kódu
languagejs
  "queryFields": [ {
      "tableName": "FA_OUT",
      "tableFields": "INTER,CISLO,ZKKOD,STKOD,K_SYMBOL,OBJEDNAVKA,DOD_LIST,BANKA_DOKL,BANKA_NAZ"  },{
      "tableName": "POLOZKY",
      "tableFields": "FAKTURA,MNOZSTVI,CENA_MJ,CENA_SLV,CENA,CENA_DPH,SAZBA_DPH"
    }  ]


Varování
titleUpozornenie

Pri použití queryfields sa v niektorých prípadoch môže vrátiť chybová hláška Invalid column name 'názov', ktorá znamená nutnosť uviesť vo výpočte i dané pole.


Keď logika inComm povolí, je možnosť poslať vlastné podmienky (parametre výberu) "queryCondition" príkazu:

Blok kódu
languagejs
    "queryCondition": {
      "tableName": "FA_OUT",
      "conditions": [ {
          "fieldName": "INTER",
          "relationalOperator": "=",
          "value": "15"
        } ] }

IN príkaz (vstupný formát)

Formát HTTP_in

  • Command
    •  inComm
    •  inParam
      • Parameters
        • názvy a hodnoty parametrov v závislosti od príkazu
  •  queryCondition
    • { row }
      • tableName
      • conditions
        • logicalOperator
        • fieldName
        • relationalOperator
        • value
        • queryFields
          • { row }
            • tableName
            • tableFields
            • Select
            • Data


Používa rovnakú logiku ako OUT príkaz + doplnené o pole „DATA“, ktoré sa posielajú na server.

Blok kódu
languagejs
{
  "command": {
    "inComm": "PARTNERI_ADD",
    "inParam": {
      "parameters": {
        "typCmd": null
      }
    }
  },
  "Data": {
    "INTER": 0,
    "ODBERATEL": true,
    "ID": "057fe3f7-3363-49ab-88bc-8c6342ad9a33",
    "CISLO": "0123456789",
    "NAZEV": "Test ADD",
    "ALT_NAZEV": null,
    "ULICE": null,
    "PSC": null,
    "MESTO": null,
    "STAT": null,
    "ICO": null,
    "DIC": null,
    "KON_PRIJEM": null,
    "MOBIL": null,
    "E_MAIL": null
  }
}

Všeobecné špecifikácie v príkazoch


Vstupný formát Timestamp:    rrrr-MM-dd HH: mm: ss
                                                   (HH = 24 hod. Formát, príklad: 2020-01-31 19:55:00)
Vstupný formát Dátumu:          rrrr-MM-dd


Chybové hlásenia


Vrátené chybové hlásenia majú spravidla tento formát:

Blok kódu
languagejs
{
    "Result": "ERR",                                                       /* OK/ERR */
    "CommandIn": "FA_OUT",                                                 /* názov príkazu */
    "Error": [
        {
            "number": 900,                                                 /* číslo chyby */
            "desc": "Exception Type: System.Data.SqlClient.SqlException, Message: Invalid column name 'inter'." /* podrobnosti k chybe */
        }
    ]
}

Prehľad chybových hlášok v result


Arithmetic overflow error converting expression to data type - došlo k pretečeniu hodnoty, keď je v databáze nižšia, než ktorú sa pokúšate zapísať

Invalid column name 'nazov' - obvykle sa zobrazí pri použití queryFields, kde je nutné uviesť vo výpočte aj povinnú databázovú položku

Musí byť vyplnený aspoň jeden z parametrov [ 'nazov'] alebo [queryConditions] - chýba vyplnenie aspoň jednej z uvedených povinných položiek

Can not continue the execution because the session is in the kill state - môže nastať v prípade volania príkazov za sebou, kedy sa nestihne vrátiť Result z predchádzajúceho príkazu a dochádza k stornu. Maximálny čas pre spracovanie jedného príkazu je nastavený v API na 2 min. Tento maximálny čas spojenia by si mal súčasne nastaviť a strážiť vo svojom programe aj programátor.

Chyba: 3521 - Požadovaná mena nie je v nastavení pre Kurzový lístok ČNB. Pre tuzemskú faktúru menu neudávajte - je nutné mať v Premier povolenú požadovanú menu:

Chyba: 3514 ... - chybný parameter FORMA vo faktúrach
Chyba: 3005 ... - všeobecná chyba SQL
Chyba: 3006 ... - názov partnera už existuje
Chyba: 3007 ... - požadované ID [xy] pre update partnera som nenašiel

ApiComPremForm

Pokiaľ nie je správne nastavený Compatibility Level v administrácii MS SQL, zobrazí sa pri Teste pripojenia táto chyba:

ApiComPremForm: Nastavenie HTTP


Slúži na nastavenie základných parametrov. Uložené nastavenie preberá HTTP server aj služba ApiComPremService, ktorá musí byť po vykonaní zmien reštartovaná.


Ak nie sú nainštalované SQL procedúry v SQL databáze, môže ApiComPrem vyhadzovať pri odosielaní príkazov chyby, potom je potrebné vykonať reinštaláciu procedúr hr. "Reinstall SQL CLR" a zároveň musí byť správne nastavená a programom prístupná cesta "Default cesta k HTML".

Tlačidlo Pridanie nového záznamu (= pripojenie ku konkrétnej firme v SQL verzii programu Premier)

Konfigurácia sa zapisuje do súboru setup.xml, ktorý môžete v prípade potreby upraviť aj ručne, dáta nie sú zašifrované.


ApiComPremForm: HTTP server


Vizuálne zobrazenie komunikácie HTTP servera. Po spustení preberá nastavenia z predchádzajúceho kroku a funguje iba s SQL verziou programu Premier.
Pri spustení http serveru sa kontroluje verzia ApiComSQL.dll a automaticky sa nainštalujú alebo preinštalujú požadované SQL procedúry na SQL servery. Pokiaľ k preinštalovaniu SQL procedúr nedôjde z nejakého dôvodu automaticky, možno použiť v Nastavení http tlačidlo Reinstal SQL CRL.

ApiComPremService



Služba HTTP server, nahrádza spustenie vizuálneho formulára HTTP server. Inštaláciu vykonávajte ako správca. Všetky nastavenia sa preberajú z Nastavení http (súbor setup.xml).


Inštalácia:          ApiComPremService.exe "/ install
Odinštalácia:     ApiComPremService.exe "/ uninstall


Ak si nastavíte spustenie príkazu "ApiComPremUpdate.exe -auto" v plánovači úloh v požadovanú dobu, dôjde k zastaveniu spustenej služby a k automatickej aktualizácii programu.

ApiComPremForm: HTTP klient


Slúži na skladanie, vyskúšanie a ladenie všetkých odosielaných príkazov.

URI - IP adresa, na ktorej beží serverová časť http server.

Port - musí byť zhodný s nastavením.

ID UJ - ID účtovnej jednotky, musí byť zhodné s nastavením.

Basic authorization - je označenie pre jednoduchú autentizáciu pri prístupe na webové stránky. Webový server vyzve pomocou protokolu HTTP pristupujúceho klienta, aby poslal v rámci požiadavky na stránku tiež autentizačné informácie (tj. meno a heslo).

Užívateľ - užívateľ zavedený v IS Premier, s nastavenými právami pre čítanie, prípadne zápis podľa potreby s ohľadom na možnosti vzdialeného prístupu do systému.

Heslo - používateľ MUSÍ mať vložené heslo.

Create JSON Post - vytvorenie príkazu.

JSON parametre, kde je uvedená hodnota null, sa nemusia odosielať na server, v príkladoch sú uvádzané pre prehľadnosť.

Post - odoslanie vytvoreného príkazu

Ak sú vrátené dáta (JSON Result) príliš veľké, vytvorí sa súbor s výstupom v podadresári / temp. Ukladajú sa tu aj stiahnuté obrázky.

ApiComPremUpdate.exe


Spustením možno program aktualizovať z FTP. Parametrom -auto sa vykoná aktualizácia na pozadí (v prípade, že sa používa služba ApiComPremService).


Popis testovacieho webového rozhrania


Nájdete ho na adrese:               https://dev.premier.cz
Prihlasovacie meno:                  test
Heslo:                                           test

Stránka je vytvorená pre to, aby vývojár pre prehľad, vyskúšanie všetkých možností API a otestovanie zasielania dát, nemusel inštalovať Premier a SQL.

Zároveň je v Helpu uvedený zoznam všetkých aktuálne podporovaných príkazov a aktuálny prehľad dátových typov databázových položiek použitých tabuliek. Ten v tomto manuáli nie je uvedený, je generovaný automaticky a prejaví sa už v okamihu aktualizácie databázy (napr. rozšírenie veľkosti databázové položky). Zásadnejšie zmeny, ak sa nebude jednať len o obyčajné rozšírenie veľkosti, budú zapísané v tomto manuáli. Súčasne sa pridanie nových databázových položiek alebo príkazov prejaví v danom prostredí obvykle rýchlejšie, než následne dôjde k aktualizácii manuálu.

Parametre pre vonkajšiu komunikáciu nájdete na úvodnej stránke:


Popis dostupných príkazov


Nájdete tu popis všetkých použiteľných príkazov, vrátane aktuálnych prehľadov štruktúr jednotlivých tabuliek, ktorý tento manuál len dopĺňa. Prípadné zásadné zmeny vo verziách databázy budú zohľadnené a popísané v manuáli.







Zobrazené dátové typy

char - textový typ

decimal - číselný typ

datetime - datum + čas

timestamp

bit - logický typ (true/false)

uniqueidentifier - jednoznačný identifikátor


Ak kliknete, ktorejkoľvek stránka na túto značku  . Zobrazí sa naposledy odoslaný príkaz spoločne s vráteným výsledkom:

Pre tvorcov v PHP


Tipy na nástroje pre tvorbu

PHP a mySQL – nájdete aj pod XAMPP (apachefriends.org)

BRACKETS (brackets.io) – open source textový editor

BOOTSRAP (getbootstrap.com) – komponenty a templates

DataTables (datatables.net) – HTML tabulky

Font Awesome (fontawesome.com) – ikonky

URL kódovanie

Varování
titleUpozornenie

Pri odosielaní dát vo formáte JSON z webového prehliadača cez HTTP, je nutné všetky použité rezervované znaky nahradiť pomocou znaku percenta, viď. tabuľka nižšie. V opačnom prípade sa vráti chybové hlásenie a dáta sa nevložia. Pri čítaní obdobných dát s rezervovanými znakmi, k žiadnej chybe nedochádza a zakódované nie sú. Rovnako pri použití v C# je to v poriadku a nie je nutné nič meniť.

Napríklad po vložení reťazca "Johnson & Johnson", je potom nutné ho odosielať v tvare "Johnson% 26 Johnson"

Rezervované znaky a ich zakódovanie
(https://cs.wikipedia.org/wiki/URL_kódování)

Vzorový

příklad komunikace

príklad komunikácie s Premier API

Výber prvých desiatich záznamov z tabulky partnerov príkazom SELECT

Blok kódu
languagephp
collapsetrue
<?php
$DEBUG = false;
$crlf = "\r\n";
$data_in = '';
 
// hodnoty pro testovací server – doplňte váš požadovaný server
$host = 'ssl://'.'dev.premier.cz';
// ID účetní jednotky
$iduj = '3ce17312-8dbd-49a0-94d3-2e01b65e4173';
// číslo portu
$port = 12375;
 
// vlastní příkaz
$data = '{"select": "select top 10 * from partnery"}';
$odpoved = sendAndRec($data);
 
// výpis vrácených hodnot nebo případné chyby
if ($odpoved->status == 200){   
    echo 'Status: '.$odpoved->content->result.'<br>'  ;
    echo 'CommandIn: '.$odpoved->content->commandin.'<br>';
   
    if ($odpoved->content->error != null)   { 
        echo 'Chyba: '.json_encode((array)$odpoved->content->error).'<br>';
    }
   
    if ($odpoved->content->warning != null ){     
        echo 'Varování: '.json_encode((array)$odpoved->content->warning).'<br>';
    }
   
   if ($odpoved->content->data != null ){ 
        echo 'Data: <br>';
        echo json_encode((array)$odpoved->content->data, JSON_PRETTY_PRINT);
   }
} else {
    echo $odpoved->status ;
}
 
// funkce pro odeslání požadavku
function sendAndRec($data){
                global $DEBUG, $crlf,$host,$port,$iduj ;
                $response = "";   
                // vytvorim objekt pre vysledok
                $urlinfo = new stdClass;    
                $urlinfo->status = 0 ;
                $urlinfo->errstr = '';
                $errno = 0;
$errstr = '';
try{
                $fp = fsockopen($host, $port, $errno, $errstr, 30);
}
                               catch(\Exception $ex) {      //used back-slash for global namespace
array_push($errors, $errstr);
                }
   
                if ($fp) {
                                $msg  = 'POST /api/comm HTTP/1.1' . "\r\n";
                $msg .= 'Content-Type: application/json; charset=utf-8' . $crlf;
                                $msg .= 'Content-Length: ' . strlen($data) . $crlf;
                               $msg .= 'ID-UJ: '. $iduj . $crlf;
                $msg .= 'Host: ' . $host . $crlf;
                                $msg .= 'Connection: close' . $crlf . $crlf;
                $msg .= $data;                    
                               $_SESSION['data_out'] = $msg;
                                if (fwrite($fp, $msg) ) {
                while ( !feof($fp) ) {
                $response .= fgets($fp, 1024);
                                               }
                }
                               fclose($fp);          
                } else {
                               $response = false;
                }
 
                if ($response===false){
                               $urlinfo->errstr = 'chyba připojení';
                               return $urlinfo;
                }
 
                $lines = explode(PHP_EOL, $response);
                $code = trim(substr($lines[0],9,4));
                
// if no status code default to 400 = Bad Request
                if(empty($code) || !is_numeric($code)){
                               $code = 400;
                }
                if ($code!=200){
                               $urlinfo->status = $code ;
                               $urlinfo->errstr = 'chybný status stránky';
                               return $urlinfo;
                }
 
                $result  = explode("\r\n\r\n", $response, 2);
                $header = isset($result[0]) ? $result[0] : '';

// parse headers
                $headers = array();
                $lines = explode($crlf, $header);
                foreach ($lines as $line) {
                               if (($pos = strpos($line, ':')) !== false) {
                                               $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos + 1));
                                }
                }
 
                // načtu info o HTTP
                $urlinfo->status = $code ;
                $urlinfo->header = $headers;
                $urlinfo->content_type = get_content_type($result[0]);

                // načtu data
                $url_data = new stdClass;
                $content = isset($result[1]) ? $result[1] : '';
                $jsonobj = json_decode($content);
                $url_data->result = isset($jsonobj->Result) ? $jsonobj->Result : '' ;
                $url_data->commandin = isset($jsonobj->CommandIn) ? $jsonobj->CommandIn : '';
                $url_data->error = isset($jsonobj->Error) ? $jsonobj->Error : '';
                $url_data->warning = isset($jsonobj->Warning) ? $jsonobj->Warning : '';
                $url_data->data = isset($jsonobj->Data) ? $jsonobj->Data : '';
                
// zapíšu data
                $urlinfo->content = $url_data;
$urlinfo->json_out = $msg ;
$urlinfo->data_in = $response;
               
                return $urlinfo;
}
 
// zkontroluje záhlaví content-type, pro správné zobrazení obrázků
function get_content_type($headers){
                $content_type = "";
                if(!empty($headers)){
                               $headerarray = explode("\r\n", $headers);
                               foreach($headerarray as $head){
                               //             echo "header item = ".$head;
                                               if(preg_match("/Content-Type: .+$/i",$head)){
                                                               $content_type = $head;
                                                               break;
                                               }                                                            
                               }
                }
                return $content_type ;
}
 
?>

Pre tvorcov v C#


Tipy na nástroje pre tvorbu

Online prevod JSON do C# triedy: https://app.quicktype.io/#

Vzorový príklad komunikácie s Premier API

Výber prvých desiatich záznamov z prijatých objednávok (tabulka OB_IN) príkazom SELECT: 

Blok kódu
languagec#
collapsetrue
using System;
using System.IO;
using System.Net;
using System.Text;
 
namespace TestApiConsole {
    class Program {
       
        // doplňte správnou adresu
        static readonly Uri url = new Uri(@"https://dev.premier.cz:12375/api/comm");
        
        // vlastní příkaz
        static readonly string JsonSendData = "{\"select\": \"select top 10 * from ob_in\"}";
    
        static void Main(string[] args) {
            string responseFromServer = "";
            if (!SendAnRec(url, JsonSendData, ref responseFromServer)) {
                Console.WriteLine("Err:"+responseFromServer);
            }
            else {
                // zpracovat odpověď (Result) z Premier API
                Console.WriteLine(responseFromServer);
            }
            Console.ReadKey();
        }
 
        private static bool SendAnRec(Uri url, string JsonData, ref string responseFromServer) {
            bool odpoved = true;
            byte[] byteArray = Encoding.UTF8.GetBytes(JsonData);
            responseFromServer = "";
            WebRequest request = WebRequest.Create(url);
            request.Method = "POST";

// doplňte správné ID účetní jednotky
            request.Headers.Add("ID-UJ: 3ce17312-8dbd-49a0-94d3-2e01b65e4173");
            request.ContentType = "application/json; charset=utf-8";
            request.ContentLength = byteArray.Length;
            request.Timeout = 200000;
 
// pošlu údaje
            try {
                using (var dataStream = request.GetRequestStream()) {
                    dataStream.Write(byteArray, 0, byteArray.Length);
                }
            }
            catch (Exception ex) {
                responseFromServer = ex.Message;
                return false;
            }
 
// čekám na odpověď
            try {
                Encoding enc = new UTF8Encoding(true, true);
                using (var response = request.GetResponse()) {
                    using (var stream = new StreamReader(response.GetResponseStream(), enc)) {
                        responseFromServer = stream.ReadToEnd();
                    }
                }
            } 
// zpracování výjimek
            catch (WebException ex) {
                if (ex.Status == WebExceptionStatus.ProtocolError) {
                    using (var stream = new StreamReader(ex.Response.GetResponseStream())) {
                        responseFromServer = stream.ReadToEnd();
                        odpoved = false;
                    }
                }
                else {
                    if (ex.Status == WebExceptionStatus.Timeout) {
                        responseFromServer = "{Request timeout is expired.}";
                        odpoved = false;
                    }
                    else {
                        responseFromServer = "{" + ex.Message + "}";
                        odpoved = false;
                    }
                }
            }
            return odpoved;
        }
    }
}



Obsah stránky

Obsah
classobsah