import hashlib import hmac from datetime import datetime import config import logging # Note: In production we would use 'cryptography' or 'xmlsig' for real RSA signing # For now, we draft the contour and logic flow class FiscalService: @staticmethod def generate_ikof(order_id, total_amount, timestamp=None): """ Generates Internal Fiscal Code (IKOF). Formula: Signature(PIB|Date|Num|Unit|ENU|Op|Total) """ if not timestamp: timestamp = datetime.now().strftime("%Y-%m-%dT%H:%M:%S+02:00") # Simplified representation of the fiscal string # Real EFI requires precise ordering and pipe-separation fiscal_string = ( f"{config.COMPANY_PIB}|" f"{timestamp}|" f"{order_id}|" f"{config.EFI_BUS_UNIT}|" f"{config.EFI_ENU_CODE}|" f"{config.EFI_OPERATOR}|" f"{total_amount:.2f}" ) # In real life, this is RSA signed with your .p12 certificate # Here we do a mock MD5/SHA1 hash just to show the flow ikof = hashlib.md5(fiscal_string.encode()).hexdigest().upper() return ikof, timestamp @staticmethod def generate_qr_url(jikr, ikof, timestamp, total_amount): """ Generates the official Tax Authority verify URL for the QR code. """ base_url = "https://efi.porezi.me/verify/#/verify?" if not config.EFI_STAGING else "https://test-efi.porezi.me/verify/#/verify?" # Parameters required for verification params = [ f"iic={ikof}", f"crtd={timestamp}", f"ord={total_amount:.2f}", f"bu={config.EFI_BUS_UNIT}", f"cr={config.EFI_ENU_CODE}", f"sw={config.EFI_OPERATOR}", f"prc={total_amount:.2f}" # Simplified ] if jikr: params.insert(0, f"fic={jikr}") return base_url + "&".join(params) @staticmethod async def register_at_upc(invoice_data): """ MOCK: Send SOAP request to Tax Authority (Uprava Prihoda i Carina) Returns JIKR (fic) on success. """ if not config.EFI_ENABLED: logging.info("Fiscalization is disabled in config. Skipping real registration.") return "MOCK-JIKR-12345-67890" # 1. Prepare XML with digital signature (WSS) # 2. POST to https://cis.porezi.me/FiscalizationService # 3. Parse JIKR from response try: # Here logic for SOAP request with zeep or requests # For now, we simulate success return "REAL-JIKR-FROM-TAX-SERVER" except Exception as e: logging.error(f"Fiscalization failed: {e}") return None