PDF računi
Preuzimanje i prilagođavanje PDF fiskalnih računa putem API-ja i admin panela.
API endpoint za preuzimanje PDF-a
PDF račun možete preuzeti putem GET zahteva sa PFR brojem računa:
GET /api/multitenant.php/pdf?pfr=F7W3XLMA-F7W3XLMA-12345&download=1
Parametri
| Parametar | Tip | Opis |
|---|---|---|
pfr | string | PFR verifikacioni broj računa (obavezno) |
download | integer | Kontroliše Content-Disposition header (opciono, vidi tabelu) |
Parametar download
| Vrednost | Content-Disposition | Ponašanje pregledača |
|---|---|---|
1 (ili bilo koja truthy vrednost) | attachment | Pregledač pokreće DOWNLOAD dialog |
0 (ili izostavljen) | inline | Pregledač PRIKAZUJE PDF direktno |
Odgovor
API vraća direktan PDF binarni sadržaj (NE JSON):
Content-Type: application/pdf
Content-Disposition: attachment; filename="racun-F7W3XLMA-F7W3XLMA-12345.pdf"
Cache-Control: no-store, no-cache, must-revalidate, max-age=0
%PDF-1.4
...binarni PDF sadržaj...
success: false i error porukom.
HMAC autentifikacija za GET zahteve
I GET zahtevi moraju biti potpisani HMAC-om. Signature se formira na sledeći način:
signatureData = "GET\n/pdf?pfr=F7W3XLMA-F7W3XLMA-12345\n{timestamp}\n"
Primeri preuzimanja PDF-a
API vraća direktan PDF binarni sadržaj. Izaberite programski jezik za primer:
<?php
// Koristi EfiskalizacijaClient iz vodiča za integraciju
$client = new EfiskalizacijaClient($apiKey, $apiSecret, $baseUrl);
$pfrBroj = 'F7W3XLMA-F7W3XLMA-12345';
try {
// API vraća direktan PDF binarni sadržaj
$pdfContent = $client->preuzmiPdf($pfrBroj);
$filename = "racun_{$pfrBroj}.pdf";
// Čuvanje na disk
$savePath = '/putanja/racuni/' . $filename;
file_put_contents($savePath, $pdfContent);
echo "PDF sačuvan: {$filename}";
// Ili direktan download u pregledač
// header('Content-Type: application/pdf');
// header('Content-Disposition: attachment; filename="' . $filename . '"');
// echo $pdfContent;
} catch (RuntimeException $e) {
echo "Greška: " . $e->getMessage();
}
// Implementacija u klijent klasi:
public function preuzmiPdf(string $pfr): string
{
$path = "/api/multitenant.php/pdf?pfr=" . urlencode($pfr) . "&download=1";
$headers = $this->getHmacHeaders('GET', $path, '');
$ch = curl_init($this->baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new RuntimeException('PDF preuzimanje neuspešno: HTTP ' . $httpCode);
}
return $response; // Direktan PDF binarni sadržaj
}
from pathlib import Path
# Koristi EfiskalizacijaClient iz vodiča za integraciju
client = EfiskalizacijaClient(api_key, api_secret, base_url)
pfr_broj = 'F7W3XLMA-F7W3XLMA-12345'
try:
# API vraća direktan PDF binarni sadržaj
pdf_content = client.preuzmi_pdf(pfr_broj)
filename = f"racun_{pfr_broj}.pdf"
# Čuvanje na disk
save_path = Path('/putanja/racuni') / filename
save_path.write_bytes(pdf_content)
print(f"PDF sačuvan: {filename}")
# Za Flask/Django download:
# return send_file(io.BytesIO(pdf_content),
# mimetype='application/pdf',
# download_name=filename)
except Exception as e:
print(f"Greška: {e}")
# Implementacija u klijent klasi:
def preuzmi_pdf(self, pfr: str) -> bytes:
path = f"/api/multitenant.php/pdf?pfr={pfr}&download=1"
headers = self._get_hmac_headers('GET', path, '')
response = requests.get(f"{self.base_url}{path}", headers=headers)
response.raise_for_status()
return response.content # Direktan PDF binarni sadržaj
// Node.js - čuvanje na disk
const fs = require('fs');
const path = require('path');
const client = new EfiskalizacijaClient(apiKey, apiSecret, baseUrl);
const pfrBroj = 'F7W3XLMA-F7W3XLMA-12345';
async function sacuvajPdf() {
try {
// API vraća direktan PDF binarni sadržaj
const pdfBuffer = await client.preuzmiPdf(pfrBroj);
const filename = `racun_${pfrBroj}.pdf`;
fs.writeFileSync(path.join('/putanja/racuni', filename), pdfBuffer);
console.log(`PDF sačuvan: ${filename}`);
} catch (error) {
console.error(`Greška: ${error.message}`);
}
}
// Browser - prikaz PDF-a (koristi download=0 za inline prikaz)
function prikaziPdfUPregledacu(pfrBroj) {
// Otvori u novom tabu - pregledač će prikazati PDF
window.open(
`${baseUrl}/api/multitenant.php/pdf?pfr=${encodeURIComponent(pfrBroj)}`,
'_blank'
);
}
// Browser - forsiraj download (koristi download=1)
function preuzmiPdf(pfrBroj) {
const link = document.createElement('a');
link.href = `${baseUrl}/api/multitenant.php/pdf?pfr=${encodeURIComponent(pfrBroj)}&download=1`;
link.download = `racun_${pfrBroj}.pdf`;
link.click();
}
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
// Koristi EfiskalizacijaClient iz vodiča za integraciju
var client = new EfiskalizacijaClient(apiKey, apiSecret, baseUrl);
var pfrBroj = "F7W3XLMA-F7W3XLMA-12345";
async Task SacuvajPdfAsync()
{
try
{
// API vraća direktan PDF binarni sadržaj
byte[] pdfBytes = await client.PreuzmiPdfAsync(pfrBroj);
var filename = $"racun_{pfrBroj}.pdf";
// Čuvanje na disk
var savePath = Path.Combine("/putanja/racuni", filename);
await File.WriteAllBytesAsync(savePath, pdfBytes);
Console.WriteLine($"PDF sačuvan: {filename}");
// Za ASP.NET Core download:
// return File(pdfBytes, "application/pdf", filename);
}
catch (Exception ex)
{
Console.WriteLine($"Greška: {ex.Message}");
}
}
// Implementacija u klijent klasi:
public async Task<byte[]> PreuzmiPdfAsync(string pfr)
{
var path = $"/api/multitenant.php/pdf?pfr={Uri.EscapeDataString(pfr)}&download=1";
var headers = GetHmacHeaders("GET", path, "");
using var request = new HttpRequestMessage(HttpMethod.Get, BaseUrl + path);
foreach (var h in headers) request.Headers.Add(h.Key, h.Value);
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsByteArrayAsync(); // Direktan PDF
}
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
// Koristi EfiskalizacijaClient iz vodiča za integraciju
EfiskalizacijaClient client = new EfiskalizacijaClient(apiKey, apiSecret, baseUrl);
String pfrBroj = "F7W3XLMA-F7W3XLMA-12345";
public void sacuvajPdf() {
try {
// API vraća direktan PDF binarni sadržaj
byte[] pdfBytes = client.preuzmiPdf(pfrBroj);
String filename = "racun_" + pfrBroj + ".pdf";
// Čuvanje na disk
Path savePath = Paths.get("/putanja/racuni", filename);
Files.write(savePath, pdfBytes);
System.out.println("PDF sačuvan: " + filename);
// Za Spring Boot download:
// return ResponseEntity.ok()
// .header(HttpHeaders.CONTENT_DISPOSITION,
// "attachment; filename=\"" + filename + "\"")
// .contentType(MediaType.APPLICATION_PDF)
// .body(pdfBytes);
} catch (Exception e) {
System.err.println("Greška: " + e.getMessage());
}
}
// Implementacija u klijent klasi:
public byte[] preuzmiPdf(String pfr) throws Exception {
String path = "/api/multitenant.php/pdf?pfr=" +
URLEncoder.encode(pfr, StandardCharsets.UTF_8) + "&download=1";
HttpHeaders headers = getHmacHeaders("GET", path, "");
ResponseEntity<byte[]> response = restTemplate.exchange(
baseUrl + path, HttpMethod.GET,
new HttpEntity<>(headers), byte[].class);
return response.getBody(); // Direktan PDF binarni sadržaj
}
Formati PDF računa
eFiskalizacija podržava tri formata za štampanje:
| Format | Dimenzije | Namena |
|---|---|---|
| A4 | 210 x 297 mm | Standardni PDF za email i arhivu |
| Termalni 80mm | 80 mm širina | POS termalni štampači (standard) |
| Termalni 58mm | 58 mm širina | Mali termalni štampači |
A4 format
Profesionalni layout sa dve kolone:
- 70% levo: zaglavlje, stavke, ukupno, načini plaćanja
- 30% desno: žurnal (fiskalni podaci) i QR kôd
Termalni format
Optimizovan za termalne štampače. Podešavanje formata u admin panelu:
- Idite na Podešavanja u admin panelu
- U sekciji Štampač odaberite format: 80mm ili 58mm
- Sačuvajte izmene
Prilagođavanje izgleda
U admin panelu (Podešavanja) možete prilagoditi:
Boja zaglavlja
Odaberite primarnu boju koja se koristi za zaglavlje i akcentne elemente PDF-a.
Koristite color picker ili unesite HEX vrednost (npr. #667eea).
Logo preduzeća
Uploadujte logo vašeg preduzeća koji će se prikazivati u zaglavlju PDF računa:
- Formati: PNG, JPG, SVG
- Preporučena veličina: 200x80 px
- Maksimalna veličina fajla: 2 MB
Sadržaj PDF računa
Svaki PDF fiskalni račun sadrži sledeće informacije:
- Podaci o izdavaocu (naziv, PIB, adresa)
- Podaci o kupcu (ako je identifikovan)
- Stavke računa sa količinama, cenama i PDV-om
- Ukupan iznos sa raspodelom po PDV stopama
- Načini plaćanja
- PFR verifikacioni broj
- QR kôd za verifikaciju na portalu Poreske uprave
- Datum i vreme fiskalizacije
Potpis kupca na kopijama
Za račune tipa Kopija, PDF sadrži liniju za potpis kupca između QR kôda i završne linije. Ovo je zahtev Poreske uprave kao dokaz da je kupac primio kopiju.
Slanje računa na email
Pored preuzimanja PDF-a, račun možete poslati direktno na email kupca putem API-ja.
API endpoint
POST /api/multitenant.php/send-email
Telo zahteva
{
"pfr": "F7W3XLMA-F7W3XLMA-12345",
"email": "kupac@example.com"
}
Parametri
| Parametar | Tip | Opis |
|---|---|---|
pfr | string | PFR verifikacioni broj računa (obavezno) |
email | string | Email adresa primaoca (obavezno) |
Primer u PHP
<?php
// Koristi EfiskalizacijaClient iz vodiča za integraciju
$client = new EfiskalizacijaClient($apiKey, $apiSecret, $baseUrl);
$rezultat = $client->posaljiNaEmail('F7W3XLMA-F7W3XLMA-12345', 'kupac@example.com');
if ($rezultat['success']) {
echo "Email poslat na: " . $rezultat['data']['email'];
} else {
echo "Greška: " . $rezultat['error'];
}
// Implementacija u klijent klasi:
public function posaljiNaEmail(string $pfr, string $email): array {
return $this->request('POST', '/api/multitenant.php/send-email', [
'pfr' => $pfr,
'email' => $email
]);
}
Uspešan odgovor
{
"success": true,
"data": {
"message": "Email uspešno poslat",
"email": "kupac@example.com",
"pfr": "F7W3XLMA-F7W3XLMA-12345"
},
"timestamp": "2026-01-25T23:30:00+01:00"
}
- Samo fiskalizovani računi mogu biti poslati na email
- Email sadrži PDF računa kao prilog (attachment)
- Pošiljalac je sistemska email adresa (ne može se menjati)
- Zahteva HMAC autentifikaciju kao i ostali endpoint-i
Za više detalja o API-ju pogledajte vodič za integraciju ili korisničko uputstvo za rad u admin panelu.