API
Application programming interface alebo skratkou API je rozhranie pre prácu s ReFISom z iného programu. Momentálne je podporovaná verzia API 1.0.
Overovanie
V ReFISe si opíšte identifikátor API kľúča (ApiKeyID) a samotný API kľúč (ApiKey). ReFIS API využíva autentifikáciu cez HMAC, ktorá vyzerá nasledovne:
- Je nutné v každom requeste poslať HTTP hlavičku:
- "Authorization"
- "Date"
- Príklad:
- Authorization: ReFIS db000:4:Dr5v5iqDg1bsp0NJDdmCiqmXhyA=.
- Date: Mon, 15 Jan 2018 14:20:08 GMT
- Date obsahuje RFC2616 sformátovaný dátum
- Hodnoty hlavičky Authorization pozostávajú z:
- Service label "ReFIS"
- Meno spoločnosti
- Identifikátor API kľúča
- Hash, ktorý sa vypočíta takto:
base64(sha1(
upperstring(httpmethod) + "\n" +
request_uripath + "\n" +
httpheader_date_unixtime + "\n" +
ApiKey
))
Na otestovanie overovania môžete použiť end-point /api/1.0/authorization/. V prípade úspechu príde JSON odpoveď s textom: „You are authorized! Welcome!“
Operácie
Je možné vykonávať všetky operácie, ktoré môže robiť používateľ. „API key ID“ sa viaže ku kontu používateľa a operácie sa vykonávajú pod týmto používateľom. To znamená, že ak má používateľ napríklad prístup k operácii „Odoslať doklad“, môže API odoslať doklad.
Všetky operácie sú zdokumentované vo formáte SWAGGER na adrese: https://app.swaggerhub.com/api/ReFIS/re-fis_api/1.0
Vzorové implementácie
Java/Groovy
import grails.plugins.rest.client.RestBuilder
import grails.util.Holders
import org.apache.http.client.methods.HttpUriRequest
import org.grails.web.json.JSONObject
import org.springframework.http.HttpMethod
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate
import java.security.MessageDigest
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
class ReFISUtilService {
private sendGetRequestToReFIS(RefisEndpoint endpoint, String company, LinkedHashMap payload = null, String param = null) {
def headerDate = getDate()
def response = this.restBuilder.get(getServerAddress() + getEndpoint(endpoint, param)) {
header 'Authorization', getAccessTokenSHA1(headerDate, endpoint, "GET", company, param)
header 'Date', headerDate.formatedTime
header 'User-Agent', "yourservice/useragent"
accept JSONObject, 'application/json'
contentType('application/json')
if(payload)
json(payload)
}
def details = [body: response.body, response: response]
def json = response.json
if(response.responseEntity.statusCode.value in [200,201,202]) {
return [response: json]
} else if(response.responseEntity.statusCode.value == 400) {
return [response: json, withError: true]
} else {
throw new IllegalStateException("[ReFIS API] Endpoint responded with status ${response?.responseEntity?.statusCode?.value}. Payload: $payload, response: $json, details: $details.")
}
}
protected String getServerAddress() {
return "https://dev.refis.sk"
}
private getEndpoint(RefisEndpoint endpoint, String param = null) {
switch(endpoint) {
case RefisEndpoint.AUTHORIZATION :
return "/api/1.0/authorization"
case RefisEndpoint.INVOICE:
return "/api/1.0/accdocument/invoice"
}
}
private getDate() {
def date = ZonedDateTime.now()
return [
unixTime: date.toEpochSecond().toString(),
formatedTime: date.format(DateTimeFormatter.RFC_1123_DATE_TIME) //RFC2616 - rfc1123 give same result // Mon, 15 Jan 2018 14:20:08 GMT
]
}
private getInputString(headerDate, RefisEndpoint endpoint, String httpMethod, String param) {
return httpMethod.toUpperCase()+"\n"+getEndpoint(endpoint, param)+"/\n"+headerDate+"\n"+config.refis.apiKey
}
private getAccessTokenSHA1(headerDate, RefisEndpoint endpoint, String httpMethod, String company, String param) {
company = company ?: "testDB"
MessageDigest sha1 = MessageDigest.getInstance("SHA1")
return "ReFIS "+ company + ":" + config.refis.apiKeyID + ":" + Base64.encoder.encodeToString(sha1.digest(getInputString(headerDate.unixTime, endpoint, httpMethod, param).getBytes()))
}
def testAuthorization(String company) {
def result = sendGetRequestToReFIS(RefisEndpoint.AUTHORIZATION, company,null)
return result && !result.withError
}
}
enum RefisEndpoint {
AUTHORIZATION,
INVOICE
}
PHP
Kód je pre úpravu dátumu dodania v objednávke, iné end-pointy fungujú podobne.
<?php
$serviceLabel = 'ReFIS';
$AccDocumentID = 999999; // ID dokladu
$endpoint = "/api/1.0/accdocument/order/" . $AccDocumentID . '/';
$path = "https://dev.refis.sk" . $endpoint;
$method = 'put';
$date = mktime(date("H"), 0, 0);
$company = 'db004'; // nazov spolocnosti
// API kluc
$apikey = [
'ID' => 1, // Identifikator
'Key' => 'cg1KmVAXDPBMGa86FAWy9123' // Kluc
];
// Vypocet hash-u
$hash = base64_encode(sha1(
strtoupper($method) . "\n" .
$endpoint . "\n" .
$date . "\n" .
$apikey['Key'], TRUE
));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $path);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'DeliveryDate' => '01.10.2018' // datum dodania
]));
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
sprintf("authorization: %s %s:%d:%s", $serviceLabel, $company, $apikey['ID'], $hash),
'date: ' . date('r', $date),
],
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_VERBOSE => 1,
CURLOPT_FOLLOWLOCATION => 1
]);
$server_output = curl_exec($ch);
print_r(json_decode($server_output));
curl_close($ch);
C#
using System.Net;
using System.Text;
public class ReFISAPI
{
//... your code here
public async Task Authorization()
{
// Execute Authorization
CreateHeader(HttpMethod.Get, RefisApiUrlEndpoints.AuthorizationUrl);
var response = await SendAsync(HttpMethod.Get, _refisApiProxySetting.Endpoint + RefisApiUrlEndpoints.AuthorizationUrl, null);
// Response Authorization with StatusCode: response.StatusCode
var json = await response.Content.ReadAsStringAsync();
if (response.StatusCode != HttpStatusCode.OK)
{
_logger.LogError(json);
throw new Exception("Authorization Error");
}
}
private string GetAuthorizationHash(HttpMethod httpMethod, string methodUrl, string dateUnix)
{
var key = httpMethod.ToString().ToUpperInvariant() + "\n" + methodUrl + "\n" + dateUnix + "\n" + _refisApiProxySetting.ApiKey;
var sha = System.Security.Cryptography.SHA1.Create();
byte[] bytes = Encoding.UTF8.GetBytes(key);
var hash = sha.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
private string CreateAuthotizationHeader(HttpMethod httpMethod, string methodUrl, string dateUnix)
{
var hash = GetAuthorizationHash(httpMethod, methodUrl, dateUnix);
return $ "ReFIS {_refisApiProxySetting.CompanyName}:{_refisApiProxySetting.ApiKeyId}:{hash}";
}
private void CreateHeader(HttpMethod httpMethod, string methodUrl)
{
_httpClient.DefaultRequestHeaders.Clear();
var currentTime = DateTime.UtcNow;
var dateHeader = currentTime.ToString("r");
var dateUnix = ((DateTimeOffset) currentTime).ToUnixTimeSeconds();
var authorization = CreateAuthotizationHeader(httpMethod, methodUrl, dateUnix.ToString());
_httpClient.DefaultRequestHeaders.Add("Authorization", authorization);
_httpClient.DefaultRequestHeaders.Add("Date", dateHeader);
}
}
VB.NET
Tento kód slúži iba na vygenerovanie informácie do Header v HTTP requeste (Authorization: authorizationHeader, Date: dateHeader)
Dim authStaticVal As String = "ReFIS COMPANY_NAME_PLACEHOLDER:API_KEY_ID_PLACEHOLDER:"
Dim apiKey As String = "API_KEY_PLACEHOLDER"
Dim httpMethod As String = "GET"
'pre ukazku: metoda pre ziskanie informacii o fakture s ID 123
Dim methodUrl As String = "/api/1.0/accdocument/invoice/123"
Dim currentUtcTime As DateTime = DateTime.UtcNow
unixTimestamp = CLng((currentUtcTime - New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString()
Dim key As String = httpMethod.ToString().ToUpperInvariant() & vbLf & methodUrl & vbLf & unixTimestamp & vbLf & apiKey
Dim sha As System.Security.Cryptography.SHA1 = System.Security.Cryptography.SHA1.Create()
Dim bytes() As Byte = System.Text.Encoding.UTF8.GetBytes(key)
Dim hash() As Byte = sha.ComputeHash(bytes)
authorizationHeader = authStaticVal & Convert.ToBase64String(hash)
dateHeader = currentUtcTime.ToString("ddd, dd MMM yyyy HH:mm:ss 'GMT'")
Python
import time
from datetime import datetime
import hashlib
import base64
import requests
def generate_auth_header(http_method, request_uri, api_key_id, api_key, company_name):
date_header = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
unix_timestamp = str(int(time.time()))
string_to_hash = http_method.upper() + "\n" + request_uri + "\n" + unix_timestamp + "\n" + api_key
hashed = hashlib.sha1(string_to_hash.encode('UTF-8'))
base64_encoded_hash = base64.b64encode(hashed.digest()).decode('utf-8')
authorization_value = "ReFIS" + " " + company_name + ":" + api_key_id + ":" + base64_encoded_hash
print("string_to_hash", string_to_hash)
print(f"Authorization: {authorization_value} \n Date: {date_header}")
return {"Authorization": authorization_value, "Date": date_header}
# priklad: pre otestovanie autorizacie
# headers = generate_auth_header("GET", "/api/1.0/authorization/", "API_KEY_ID_PLACEHOLDER", "API_KEY_PLACEHOLDER", "COMPANY_NAME_PLACEHOLDER")
# priklad: pre ziskanie informacii o fakture s ID 123
headers = generate_auth_header("GET", "/api/1.0/accdocument/invoice/123", "API_KEY_ID_PLACEHOLDER", "API_KEY_PLACEHOLDER", "COMPANY_NAME_PLACEHOLDER")
URL = "https://app1.refis.sk"
response = requests.get(URL, headers=headers)
print(f"HTTP response: {response.status_code} {response.content.decode('utf-8')}")