VIES Knjižnice za programiranje
Programske biblioteke omogućuju pretraživanje podataka o poduzetnicima na temelju unesenog PDV EU broja. Trenutno su API biblioteke dostupne za sljedeće programske jezike:
- .NET (C#, Visual Basic)
- Java
- JavaScript (Node.js)
- PHP
- Piton
- C/C++
API pruža sljedeće značajke:
getVIESData
– funkciju potvrđivanja aktivnosti EU PDV broja koji je dodijelila bilo koja država članica Europske unije,getVIESDataParsed
– funkcija za potvrdu aktivnosti EU PDV broja koji je dodijelila bilo koja država članica Europske unije i vraćanje raščlanjene adrese trgovca,getVIESDataAsync
– asinkrona funkcija, koja na temelju poslane serije PDV brojeva omogućuje dobivanje trenutnog EU PDV statusa i podataka trgovca.getVIESDataAsyncResult
– funkcija vam omogućuje dohvaćanje skupnih rezultata na temelju tokena koji vraća funkcija getVIESDataAsyncgetAccountStatus
– funkcija za dohvaćanje ažuriranih podataka o korisničkom računu.
Integracija
Sve biblioteke s izvornim kodovima dostupne su za preuzimanje na preuzimanje datoteka stranica. Osim toga, izvorni kod za knjižnice također je dostupan u našem službenom repozitoriju na Github.
Način integracije biblioteke ovisi o odabranom programskom jeziku. Za one jezike koji podržavaju upravljanje knjižnicom na temelju središnjeg repozitorija, moguće ga je koristiti.
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
// NuGet Gallery
// https://www.nuget.org/packages/VIESAPI.VIESAPIClient
PM> Install-Package VIESAPI.VIESAPIClient
// No central repository support
// Maven
// https://viesapi.eu/maven/
<repository>
<id>viesapi</id>
<url>https://viesapi.eu/maven/releases</url>
</repository>
<dependency>
<groupId>eu.viesapi</groupId>
<artifactId>viesapi-client</artifactId>
<version>1.2.6</version>
</dependency>
// NPM
// https://www.npmjs.com/package/viesapi-client
npm install viesapi-client
// Packagist (Composer)
// https://packagist.org/packages/viesapi/client
composer require viesapi/client
# No central repository support
pip install viesapi-python-client-1.2.6.zip
' No central repository support
Ovjera
Kako bi se izvršila ispravna autentifikacija, ispravne vrijednosti za id
i key
parametri se trebaju osigurati tijekom izgradnje klijentovog objekta. The id
parametar treba sadržavati važeći identifikator ključa koji se koristi za autorizaciju. The key
parametar treba sadržavati valjanu vrijednost ključa koji se koristi za autorizaciju. Identifikator ključa i ključ generira korisnik nakon što se prijavi na svoj račun na viesapi.eu
portal. Proces generiranja ključeva i identifikatora detaljno je opisan gore.
Sljedeći primjer ilustrira kako koristiti funkcije knjižnice:
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
using viesapiLibrary.dll;
// Create the service client object
// id - a string representing the API key identifier
// key - a string representing the API key
VIESAPIClient viesapi = new VIESAPIClient("id", "key");
#include "viesapi.h"
// Create the service client object
// id - a string representing the API key identifier
// key - a string representing the API key
VIESAPIClient* viesapi = NULL;
viesapi_new_prod(&viesapi, "id", "key");
import pl.viesapi.client.*;
// Create the service client object
// id - a string representing the API key identifier
// key - a string representing the API key
VIESAPIClient viesapi = new VIESAPIClient("id", "key");
var VIESAPI = require('viesapiclient');
// Create the service client object
// id - a string representing the API key identifier
// key - a string representing the API key
var viesapi = new VIESAPI.VIESAPIClient('id', 'key');
require_once 'VIESAPI/VIESAPIClient.php';
\VIESAPI\VIESAPIClient::registerAutoloader();
// Create the service client object
// id - a string representing the API key identifier
// key - a string representing the API key
$viesapi = new \VIESAPI\VIESAPIClient('id', 'key');
from viesapi import *
from pprint import pprint
// Create the service client object
// id - a string representing the API key identifier
// key - a string representing the API key
viesapi = VIESAPIClient('id', 'key')
' Create the service client object
' id - a string representing the API key identifier
' key - a string representing the API key
Dim viesapi As New VIESAPIClient
viesapi.URL = "https://www.viesapi.eu/api"
viesapi.Id = "id"
viesapi.Key = "key"
Pažnja! Tijekom procesa autentifikacije koristi se trenutno vrijeme na klijentovom računalu. Stoga u slučaju problema s autentifikacijom prilikom pokušaja spajanja na sustav viesapi.eu prvo provjerite ima li računalo ili poslužitelj s kojeg se uspostavlja veza ispravno trenutno vrijeme i vremensku zonu. Više informacija o metodi koju sustav viesapi.eu koristi za provjeru autentičnosti upita možete pronaći ovdje.
Provjera EU PDV brojeva
EU PDV broj se potvrđuje pozivom na getVIESData
funkciju čiji je parametar EU PDV broj koji želimo provjeriti. Funkcija omogućuje provjeru EU PDV brojeva izdanih od strane svih država članica Europske unije.
Sljedeći primjer ilustrira kako se funkcije koriste u bibliotekama:
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
// A call to a method that returns data from a VIES system
VIESData vies = viesapi.GetVIESData("PL1234567890");
if (vies != null) {
Console.WriteLine(vies);
}
else {
Console.WriteLine("Error: " + viesapi.LastError + " (code: " + viesapi.LastErrorCode + ")");
}
// A call to a method that returns data from a VIES system
VIESData* vies = viesapi_get_vies_data(viesapi, "PL1234567890");
if (vies != NULL) {
printf("Kraj: %s\n", vies->CountryCode);
printf("VAT ID: %s\n", vies->VATNumber);
printf("Aktywny: %d\n", vies->Valid);
}
else {
printf("Error: %s (code: %d)\n", viesapi_get_last_err(viesapi), viesapi_get_last_err_code(viesapi));
}
// A call to a method that returns data from a VIES system
VIESData vies = viesapi.getVIESData("PL1234567890");
if (vies != null) {
System.out.println(vies);
}
else {
System.out.println("Error: " + viesapi.getLastError() + " (code: " + viesapi.getLastErrorCode() + ")");
}
// A call to a method that returns data from a VIES system
viesapi.getVIESData('PL1234567890').then((vies) => {
console.log(vies.toString());
}).catch((e) => {
console.log(e.message);
});
// A call to a method that returns data from a VIES system
$vies = $viesapi->get_vies_data('PL1234567890');
if ($vies) {
print_r($vies);
}
else {
echo '<p>Error: ' . $viesapi->get_last_error() . '</p>';
}
# A call to a method that returns data from a VIES system
vies = viesapi.get_vies_data('PL1234567890')
if vies:
pprint(vars(vies))
else:
print('Error: ' + viesapi.get_last_error() + ' (code: ' + str(viesapi.get_last_error_code()) + ')')
' A call to a method that returns data from a VIES system
Dim vies As VIESData
Set vies = viesapi.GetVIESData("PL1234567890")
If vies Is Nothing Then
Console.WriteLine("Error: {0}", viesapi.LastError)
Else
Console.WriteLine(vies.ToString())
End If
Detaljan opis vraćenih atributa:
uid
– jedinstveni identifikator upita koji generira viesapi.eu,countryCode
– kôd zemlje u kojoj je registrirana tvrtka povezana s EU PDV brojem navedenim u upitu,vatNumber
– EU PDV broj provjerene tvrtke naveden u upitu,valid
– odgovor VIES servisa s informacijom o trenutnom EU PDV statusu provjeravanog subjekta:true
– EU PDV broj naveden u upitu je valjan,false
– EU PDV broj naveden u upitu nije valjan,
traderName
– trgovačko ime društva,traderCompanyType
– uvijek vraća niz znakova '-',traderAddress
– adresu tvrtke na kojoj je tvrtka registrirana,id
– jedinstveni identifikator upita koji generira VIES sustav (Consultation Number)date
– datum izvršenja upitasource
– izvor podataka, uvijek: http://ec.europa.eu
Provjera EU PDV brojeva s raščlanjenom adresom trgovca
Također možete potvrditi EU PDV broj pozivom na getVIESDataParsed
funkciju čiji je parametar EU PDV broj koji želimo provjeriti. Pozivom ove funkcije, osim podataka o statusu PDV obveznika, dobivate i raščlanjenu adresu trgovca.
Bilješka! Zbog nedostatka podataka koje vraća VIES za trgovce iz Njemačke i Španjolske, funkcija ih vraća ne vratiti se raščlanjena adresa trgovca (traderAddressComponent
) za ove zemlje.
Važno odricanje od odgovornosti
Funkcija raščlambe koristi vanjske AI algoritme i API-je za automatsko izdvajanje atributa kao što su: grad, poštanski broj, ulica s brojem ulice (broj zgrade) i kućni broj, tako da ne možemo jamčiti ispravan rad 100%.
Sljedeći primjer ilustrira kako se funkcije koriste u bibliotekama:
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
// A call to a method that returns data from a VIES system
VIESData vies = viesapi.GetVIESDataParsed("PL1234567890");
if (vies != null) {
Console.WriteLine(vies);
}
else {
Console.WriteLine("Error: " + viesapi.LastError + " (code: " + viesapi.LastErrorCode + ")");
}
// A call to a method that returns data from a VIES system
VIESData* vies = viesapi_get_vies_data_parsed(viesapi, "PL1234567890");
if (vies != NULL) {
printf("Kraj: %s\n", vies->CountryCode);
printf("VAT ID: %s\n", vies->VATNumber);
printf("Aktywny: %d\n", vies->Valid);
}
else {
printf("Error: %s (code: %d)\n", viesapi_get_last_err(viesapi), viesapi_get_last_err_code(viesapi));
}
// A call to a method that returns data from a VIES system
VIESData vies = viesapi.getVIESDataParsed("PL1234567890");
if (vies != null) {
System.out.println(vies);
}
else {
System.out.println("Error: " + viesapi.getLastError() + " (code: " + viesapi.getLastErrorCode() + ")");
}
// A call to a method that returns data from a VIES system
viesapi.getVIESDataParsed('PL1234567890').then((vies) => {
console.log(vies.toString());
}).catch((e) => {
console.log(e.message);
});
// A call to a method that returns data from a VIES system
$vies = $viesapi->get_vies_data_parsed('PL1234567890');
if ($vies) {
print_r($vies);
}
else {
echo '<p>Error: ' . $viesapi->get_last_error() . '</p>';
}
# A call to a method that returns data from a VIES system
vies = viesapi.get_vies_data_parsed('PL1234567890')
if vies:
pprint(vars(vies))
else:
print('Error: ' + viesapi.get_last_error() + ' (code: ' + str(viesapi.get_last_error_code()) + ')')
' A call to a method that returns data from a VIES system
Dim vies As VIESData
Set vies = viesapi.GetVIESDataParsed("PL1234567890")
If vies Is Nothing Then
Console.WriteLine("Error: {0}", viesapi.LastError)
Else
Console.WriteLine(vies.ToString())
End If
Detaljan opis vraćenih atributa:
uid
– jedinstveni identifikator upita koji generira viesapi.eu,countryCode
– kôd zemlje u kojoj je registrirana tvrtka povezana s EU PDV brojem navedenim u upitu,vatNumber
– EU PDV broj provjerene tvrtke naveden u upitu,valid
– odgovor VIES servisa s informacijom o trenutnom EU PDV statusu provjeravanog subjekta:true
– EU PDV broj naveden u upitu je valjan,false
– EU PDV broj naveden u upitu nije valjan,
traderName
– trgovačko ime društva,traderCompanyType
– uvijek vraća niz znakova '-',traderAddress
– adresa tvrtke na kojoj je tvrtka registrirana (izvorni format)traderAddressComponent
– detalji adrese grupiranja komponenticountry
– naziv zemlje trgovca na njenom nacionalnom jezikupostalCode
– poštanski broj adrese trgovcacity
– grad adrese trgovcastreet
-ulica adrese trgovcastreetNumber
– kućni broj adrese trgovcahouseNumber
– kućni broj adrese trgovca
id
– jedinstveni identifikator upita koji generira VIES sustav (Consultation Number)date
– datum izvršenja upitasource
– izvor podataka, uvijek: http://ec.europa.eu
Skupna (asinkrona) provjera EU PDV brojeva
getVIESDataAsync
– asinkrona funkcija, koja na temelju poslane serije PDV brojeva omogućuje dobivanje trenutnog EU PDV statusa i podataka trgovca.
Kao parametar navedite niz nizova koji sadrži EU PDV brojeve za koje treba provjeriti status poreznog obveznika EU PDV-a i preuzeti podatke trgovca.
Najmanji broj poslanih EU PDV brojeva je 2, a maksimalan 99.
Ispravno pozvana funkcija vraća token, koji je neophodan za dohvaćanje rezultata zahtjeva. Sljedeći primjer ilustrira kako se funkcije koriste u bibliotekama:
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
// Upload batch of VAT numbers and get their current VAT statuses and traders data
List numbers = new List {
"PL1234567890,
"DK64839576",
"CZ8475630234"
};
string token = viesapi.GetVIESDataAsync(numbers);
if (token != null) {
Console.WriteLine("Batch token: " + token);
} else {
Console.WriteLine("Error: " + viesapi.LastError + " (code: " + viesapi.LastErrorCode + ")");
}
// Upload batch of VAT numbers and get their current VAT statuses and traders data
char* numbers[] = {
"PL1234567890,
"DK64839576",
"CZ8475630234"
};
token = viesapi_get_vies_data_async(viesapi, numbers, 3);
if (token != NULL) {
printf("Batch token: %s\n", token);
} else {
printf("Error: %s (code: %d)\n", viesapi_get_last_err(viesapi), viesapi_get_last_err_code(viesapi));
}
// Upload batch of VAT numbers and get their current VAT statuses and traders data
List numbers = new ArrayList<>();
numbers.add("PL1234567890");
numbers.add("DK64839576");
numbers.add("CZ8475630234");
String token = viesapi.getVIESDataAsync(numbers);
if (token != null) {
System.out.println("Batch token: " + token);
} else {
System.out.println("Error: " + viesapi.getLastError() + " (code: " + viesapi.getLastErrorCode() + ")");
}
// Upload batch of VAT numbers and get their current VAT statuses and traders data
const numbers = [
'PL1234567890',
'DK64839576',
'CZ8475630234'
];
viesapi.getVIESDataAsync(numbers).then((token) => {
console.log('Batch token: ' + token);
}).catch((e) => {
console.log(e.message);
});
// Upload batch of VAT numbers and get their current VAT statuses and traders data
$numbers = array(
'PL1234567890',
'DK64839576',
'CZ7710043187'
);
$token = $viesapi->get_vies_data_async($numbers);
if ($token) {
echo '<pre>Batch token: ' . $token . '</pre>';
} else {
echo '<p>Error: ' . $viesapi->get_last_error() . ' (code: ' . $viesapi->get_last_error_code() . ')</p>';
}
# Upload batch of VAT numbers and get their current VAT statuses and traders data
numbers = [
'PL1234567890',
'DK64839576',
'CZ7710043187'
]
token = viesapi.get_vies_data_async(numbers)
if token:
print('Batch token: ' + token)
else:
print('Error: ' + viesapi.get_last_error() + ' (code: ' + str(viesapi.get_last_error_code()) + ')')
' Not supported yet
Zbog asinkrone prirode funkcije, rezultati se mogu dohvatiti nakon otprilike 2-3 minute. Nije bitno jesu li u zahtjevu poslani 2 ili 99 EU PDV brojeva.
Ako barem jedan EU PDV broj proslijeđen u zahtjevu ima netočan format, sustav vraća pogrešku "PDV broj je nevažeći".
Za dohvat rezultata za poslani zahtjev nazovite getVIESDataAsyncResult
funkcija, pružajući vrijednost tokena kao ulazni parametar.
Važna napomena!
- Funkcija je pripremljena kao zaobilazno rješenje za grešku koju je vratio VIES sustav: “
The maximum number of concurrent requests has been reached
” (MS_MAX_CONCURRENT_REQ
). Preporučujemo da ga koristite prilikom slanja zahtjeva za Njemačka (DE) i Francuska (FR), koji je vratio gore navedenu pogrešku. - Dok se proces provjere svih EU PDV brojeva poslanih u zahtjevu ne završi, svi sljedeći pokušaji će biti odbijeni, a pogreška će biti ispravljena”
The maximum number of batch request has been reached, please re-submit your request later
“.
getVIESDataAsyncResult
– funkcija vam omogućuje dohvaćanje skupnih rezultata na temelju tokena koji je vratio getVIESDataAsync
funkcija.
Sljedeći primjer ilustrira kako se funkcije koriste u bibliotekama:
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
// Check batch result and download data (at production it usually takes 2-3 min for result to be ready)
BatchResult result;
while ((result = viesapi.GetVIESDataAsyncResult(token)) == null) {
if (viesapi.LastErrorCode != Error.BATCH_PROCESSING) {
Console.WriteLine("Error: " + viesapi.LastError + " (code: " + viesapi.LastErrorCode + ")");
return;
}
Console.WriteLine("Batch is still processing, waiting...");
Thread.Sleep(30000);
}
// Batch result is ready
Console.WriteLine(result);
// Check batch result and download data (at production it usually takes 2-3 min for result to be ready)
while ((result = viesapi_get_vies_data_async_result(viesapi, token)) == NULL) {
if (viesapi_get_last_err_code(viesapi) != VIESAPI_ERR_BATCH_PROCESSING) {
printf("Error: %s (code: %d)\n", viesapi_get_last_err(viesapi), viesapi_get_last_err_code(viesapi));
return;
}
printf("Batch is still processing, waiting...\n");
Sleep(30000);
}
// Batch result is ready
for (i = 0; i < result->NumbersCount; i++) {
printf("Country: %s\n", result->Numbers[i]->CountryCode);
printf("VAT ID: %s\n", result->Numbers[i]->VATNumber);
printf("Is valid: %d\n", result->Numbers[i]->Valid);
printf("\n");
}
for (i = 0; i < result->ErrorsCount; i++) {
printf("Country: %s\n", result->Errors[i]->CountryCode);
printf("VAT ID: %s\n", result->Errors[i]->VATNumber);
printf("Error: %s\n", result->Errors[i]->Error);
printf("\n");
}
// Check batch result and download data (at production it usually takes 2-3 min for result to be ready)
BatchResult result;
while ((result = viesapi.getVIESDataAsyncResult(token)) == null) {
if (viesapi.getLastErrorCode() != eu.viesapi.client.Error.BATCH_PROCESSING) {
System.out.println("Error: " + viesapi.getLastError() + " (code: " + viesapi.getLastErrorCode() + ")");
return;
}
System.out.println("Batch is still processing, waiting...");
Thread.sleep(30000);
}
// Batch result is ready
System.out.println(result);
// Check batch result and download data (at production it usually takes 2-3 min for result to be ready)
const looper = setInterval(() => {
viesapi.getVIESDataAsyncResult(token).then((result) => {
// Batch result is ready
console.log(result);
clearInterval(looper);
}).catch((e) => {
console.log(e.message);
});
}, 30000);
// Check batch result and download data (at production it usually takes 2-3 min for result to be ready)
while (($result = $viesapi->get_vies_data_async_result($token)) === false) {
if ($viesapi->get_last_error_code() !== \VIESAPI\Error::BATCH_PROCESSING) {
echo '<p>Error: ' . $viesapi->get_last_error() . ' (code: ' . $viesapi->get_last_error_code() . ')</p>';
die();
}
echo '<p>Batch is still processing, waiting...</p>';
sleep(30);
}
// Batch result is ready
echo '<pre>' . print_r($result, true) . '</pre>';
# Upload batch of VAT numbers and get their current VAT statuses and traders data
numbers = [
'PL1234567890',
'DK64839576',
'CZ7710043187'
]
token = viesapi.get_vies_data_async(numbers)
if token:
print('Batch token: ' + token)
else:
print('Error: ' + viesapi.get_last_error() + ' (code: ' + str(viesapi.get_last_error_code()) + ')')
' Not supported yet
Za svaki EU PDV broj proslijeđen u skupnom pozivu, atributi su u skladu s odgovorom na getVIESData
funkcija se vraćaju.
Dohvaćanje informacija o statusu korisničkog računa
Funkcija omogućuje preuzimanje svih osnovnih podataka o korisničkom računu koji se prikazuju nakon prijave na račun na portalu viesapi.eu. Funkcija također vraća podatke o maksimalnom broju dostupnih upita prema odabranom planu (npr. 5.000 za Poslovni plan) i ukupnom broju svih upita postavljenih u tekućem mjesecu na korisničkom računu.
Pažnja! Pozivanje funkcije čini ne povećati broj postavljenih upita.
Sljedeći primjer ilustrira kako koristiti funkcije knjižnice.
- C#
- C/C++
- Java
- JavaScript
- PHP
- Piton
- Visual Basic
// Get current account status
AccountStatus account = viesapi.GetAccountStatus();
if (account != null) {
Console.WriteLine(account);
}
else {
Console.WriteLine("Error: " + viesapi.LastError);
}
// Get current account status
AccountStatus* account = viesapi_get_account_status(viesapi);
if (account != NULL) {
printf("Plan name: %s\n", account->BillingPlanName);
printf("Price: %.2f\n", account->SubscriptionPrice);
printf("Number of queries: %d\n", account->TotalCount);
}
else {
printf("Error: %s\n", viesapi_get_last_err(viesapi));
}
// Get current account status
AccountStatus account = viesapi.getAccountStatus();
if (account != null) {
System.out.println(account);
}
else {
System.err.println("Error: " + viesapi.getLastError());
}
// Get current account status
viesapi.getAccountStatus().then((account) => {
console.log(account.toString());
}).catch((e) => {
console.log(e.message);
});
// Get current account status
$account = $viesapi->get_account_status();
if ($account) {
echo '<p>' . print_r($account, true) . '</p>';
}
else {
echo '<p>Error: ' . $viesapi->get_last_error() . '</p>';
}
# Get current account status
account = viesapi.get_account_status()
if account:
pprint(vars(account))
else:
print u'Error: ' + viesapi.get_last_error()
'Get current account status
Dim account As AccountStatus
Set account = viesapi.GetAccountStatus()
If account Is Nothing Then
Console.WriteLine("Error: {0}", viesapi.LastError)
Else
Console.WriteLine(account.ToString())
End If
Registriranje .NET knjižnice kao COM objekta
The viesapiLibrary.dll
biblioteka se može registrirati u Windows sustavu kao tzv COM
objekt. Tada se funkcije biblioteke mogu referencirati iz mnogo različitih programskih jezika i gotovih aplikacija, uklj. Microsoft Excel, Access, SQL Server, Dynamics ili Visual FoxPro.
Da biste registrirali biblioteku kao COM objekt, slijedite ove korake:
- Preuzmite .NET biblioteka arhivirati i raspakirati na lokalni disk na bilo koje mjesto.
- Idite u direktorij s neraspakiranim datotekama knjižnice i pronađite
com-register.bat
datoteka. - Odaberite
com-register.bat
datoteku mišem i odaberiteRun as administrator
naredba iz kontekstnog izbornika.
Korištenje .NET knjižnice u MS Excelu
Funkcije biblioteke viesapiLibrary.dll mogu se koristiti u aplikaciji MS Excel za pisanje vlastitih funkcija i postupaka u Visual Basic
Jezik. Da bi to bilo moguće, potrebno je:
- Registar the
viesapiLibrary.dll
knjižnica kaoCOM
objekt naWindows
. - Pokrenite Excel aplikaciju. Odaberite
DEVELOPER
na vrpci, a zatim klikniteVisual Basic
dugme. - u
Visual Basic for Application
prozor, odaberiteTools
i ondaReferences
iz izbornika. uAvailable References
popis, pronađite i odaberiteVIESAPI Service Client for .NET Framework (C#)
. Potvrdite svoj odabir pomoćuOK
dugme. - Od
Insert
izbornik, odaberiteModule
i zalijepite funkcijski kod predstavljen u primjerima za Visual Basic u novi prozor. - Konačno, odgovarajuće vrijednosti w za
viesapi.ID
iviesapi.Key
treba postaviti. Način dobivanja ključa i pristupnog ključa opisan je u poglavlju Generiranje identifikatora i pristupnog ključa