When an order becomes "Processing" or "Completed", the plugin sends it to the HAFiskal Cloud API, which issues a fiscal receipt through the Serbian Tax Administration fiscal system (PFR). The receipt (number, QR code, journal, verification link) is stored on the order and shown:
- to the customer on the "Thank you" page and in "My account > Orders";
- in customer emails (the receipt is issued before the email is sent) - black text on white with inline styles, readable in Gmail, Outlook and dark mode, with the verification QR code above "КРАЈ ФИСКАЛНОГ РАЧУНА" as on the printed receipt;
- on a public printable page;
- to the shop admin in an order meta box and an orders list column.
Other features:
- Fiscalization start date: orders paid before the date the fiscal software (ESIR) was approved are never fiscalized - not automatically, not by the retry cron, not by bulk or manual actions.
- Foreign buyers (billing country other than Serbia): all lines with the 0% rate (tax label G) and a configurable legal note printed after the fiscal part of the receipt.
- Customer type field: private person or company, with company name, tax ID (PIB) and company registration number (MB), validated by check digit. Company buyers get their details on the receipt. Compatible with "Serbian Addons for WooCommerce" (same field keys, no duplicate fields).
- Explicit mapping of every payment method to the fiscal payment type (bank transfer, card, instant payment, cash).
- Automatic retries via WP-Cron without duplicate receipts.
- Automatic storno when an order is refunded.
- Serbian e-invoices (eFaktura, SEF) for company buyers, sent through HAFiskal - see below.
- Bank transfer / IPS QR payment method confirmed automatically by HAFiskal - see below.
- Products and stock synced with HAFiskal - see below.
Bank transfer / IPS QR payment
A payment method "Uplata na račun / IPS QR" (bank transfer / IPS QR), available for RSD.
- At checkout the plugin opens a payment request in HAFiskal (one per order, idempotent). If HAFiskal cannot open it (no connection, company bank account missing), the customer sees a clear error and can choose another payment method.
- The order is set to "On hold" and the customer gets the NBS IPS QR code and the payment slip data (payee, account, amount, model 97 and reference number, purpose, payment code) on the "Thank you" page, in "My account > Orders" and in the "On hold" / invoice email (the QR image in emails is a signed link, because many email clients block embedded images).
- When HAFiskal matches the payment from the bank statement, it notifies the shop (webhook, HMAC-SHA256 signature checked with the webhook secret). A fully paid order is marked paid and the existing flow issues the fiscal receipt or e-invoice. Partial or over-payments only add an order note and an admin notice.
- Fallback: WP-Cron checks waiting orders every 15 minutes for a configurable number of days (default 14).
- Cancelling the order cancels the payment request.
- On the fiscal receipt this method is always mapped (default "Bank transfer"; can be changed to "Instant payment" in the payment method mapping).
Products and stock
Settings tab "Artikli i zalihe" (products and stock).
- Simple products and variations with a SKU are sent to HAFiskal when saved, or all at once with "Send all products" (batches of 100 in the background, progress shown). Products without a SKU are skipped and listed.
- Price with VAT (active price, sale price when valid) according to the store tax settings; VAT rate from the product tax class (editable table, default standard 20%, reduced 10%, zero 0%).
- Stock is managed in HAFiskal (selected warehouse). A paid order ("Processing"/"Completed") decreases it once, cancelled or refunded orders (full or per line) increase it. Stock changes in HAFiskal reach the shop through a webhook, the "Reconcile stock now" button and a daily check; these updates are never sent back. Quantities held by orders still waiting for payment are subtracted on the shop.
- Products list column and order notes show the sync status.
Fiscalization start date
Settings tab "Fiskalizacija": "Datum početka fiskalizacije" (fiscalization start date) and "Blokiraj fiskalizaciju zaostalih porudžbina" (block backlog orders, default on).
- An order whose payment date is before the start date is never sent to HAFiskal: not when its status changes, not by the WP-Cron retry or the "unsent orders" sweep, not by the bulk action and not by the "Fiscalize" button (the order screen shows the reason instead). The order is marked "skipped (before fiscalization start)".
- On a new installation or update to 1.11.0 the date is set to the day of the first load and an admin notice asks to change it to the ESIR approval date.
- A skipped order stays skipped while "block backlog orders" is on, even if the date is moved back. It can be fiscalized (manually or in bulk) only after the date is moved earlier and the block is turned off.
Foreign buyers
Settings tab "Fiskalizacija", section "Strani kupci (van Srbije)". A foreign buyer is an order whose billing country is not Serbia (an empty country counts as Serbia).
- Issue fiscal receipts to foreign buyers: yes / no.
- Tax label: G (all lines at 0%, the fiscal device assigns label G to the 0% rate; default) or the rates from the order. The amount is always what the customer paid. HAFiskal must have a 0% tax rate.
- With label G, a note is printed after the fiscal part of the receipt (HAFiskal "note" field, not sent to the fiscal device): one text for companies and one for private persons (company or person is taken from the customer type field or a filled company name). Both texts are editable; the defaults refer to the place of supply of services - for goods sold abroad check the legal basis with your accountant.
- A foreign company's tax number is never sent as a Serbian tax ID (PIB); foreign buyers never get a Serbian e-invoice (SEF).
eFaktura (SEF)
E-invoices are a feature of the HAFiskal service: the plugin sends the invoice data to HAFiskal, and HAFiskal sends the e-invoice to SEF (the Serbian e-invoice system) on the merchant's behalf, using the SEF settings (SEF API key, environment, company data, bank account) stored in the merchant's HAFiskal account. The plugin itself never connects to SEF. The invoice also appears in HAFiskal among outgoing invoices, numbered by the company's HAFiskal numbering. An HAFiskal account with eFaktura enabled and set up is required; if it is not, HAFiskal's message is shown on the order and the buyer gets a fiscal receipt.
- Turned on with "Send e-invoices" ("Šalji eFakture") on the eFaktura settings tab; "Check connection" ("Proveri vezu") shows whether eFaktura is ready in HAFiskal.
- Only buyers marked as a company with a valid tax ID (PIB) whose company is registered on SEF get an e-invoice (HAFiskal checks the tax ID; the answer is kept for 24 hours). Private persons never get one.
- Invoice lines are the same as on the fiscal receipt (exact order total, shipping as a line, RSD only); VAT category and exemption code for 0% lines are configurable.
- Sent automatically when the order becomes "Processing" or "Completed" (configurable) or manually from the order screen and the "Send e-invoice" ("Pošalji eFakturu") bulk action. An already sent order is never sent again automatically; a new e-invoice for the same order requires explicit confirmation.
- Temporary errors are retried by WP-Cron with the same invoice reference, so no duplicates are created.
- Configurable fiscal receipt rules: company with e-invoice - no fiscal receipt (default), company without e-invoice - fiscal receipt, private person - fiscal receipt. A skipped receipt is recorded on the order with the reason and can still be issued manually.
An HAFiskal account with an API key is required (
https://hafiskal.rs).