fiscal_service.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import hashlib
  2. import hmac
  3. from datetime import datetime
  4. import config
  5. import logging
  6. # Note: In production we would use 'cryptography' or 'xmlsig' for real RSA signing
  7. # For now, we draft the contour and logic flow
  8. class FiscalService:
  9. @staticmethod
  10. def generate_ikof(order_id, total_amount, timestamp=None):
  11. """
  12. Generates Internal Fiscal Code (IKOF).
  13. Formula: Signature(PIB|Date|Num|Unit|ENU|Op|Total)
  14. """
  15. if not timestamp:
  16. timestamp = datetime.now().strftime("%Y-%m-%dT%H:%M:%S+02:00")
  17. # Simplified representation of the fiscal string
  18. # Real EFI requires precise ordering and pipe-separation
  19. fiscal_string = (
  20. f"{config.COMPANY_PIB}|"
  21. f"{timestamp}|"
  22. f"{order_id}|"
  23. f"{config.EFI_BUS_UNIT}|"
  24. f"{config.EFI_ENU_CODE}|"
  25. f"{config.EFI_OPERATOR}|"
  26. f"{total_amount:.2f}"
  27. )
  28. # In real life, this is RSA signed with your .p12 certificate
  29. # Here we do a mock MD5/SHA1 hash just to show the flow
  30. ikof = hashlib.md5(fiscal_string.encode()).hexdigest().upper()
  31. return ikof, timestamp
  32. @staticmethod
  33. def generate_qr_url(jikr, ikof, timestamp, total_amount):
  34. """
  35. Generates the official Tax Authority verify URL for the QR code.
  36. """
  37. base_url = "https://efi.porezi.me/verify/#/verify?" if not config.EFI_STAGING else "https://test-efi.porezi.me/verify/#/verify?"
  38. # Parameters required for verification
  39. params = [
  40. f"iic={ikof}",
  41. f"crtd={timestamp}",
  42. f"ord={total_amount:.2f}",
  43. f"bu={config.EFI_BUS_UNIT}",
  44. f"cr={config.EFI_ENU_CODE}",
  45. f"sw={config.EFI_OPERATOR}",
  46. f"prc={total_amount:.2f}" # Simplified
  47. ]
  48. if jikr:
  49. params.insert(0, f"fic={jikr}")
  50. return base_url + "&".join(params)
  51. @staticmethod
  52. async def register_at_upc(invoice_data):
  53. """
  54. MOCK: Send SOAP request to Tax Authority (Uprava Prihoda i Carina)
  55. Returns JIKR (fic) on success.
  56. """
  57. if not config.EFI_ENABLED:
  58. logging.info("Fiscalization is disabled in config. Skipping real registration.")
  59. return "MOCK-JIKR-12345-67890"
  60. # 1. Prepare XML with digital signature (WSS)
  61. # 2. POST to https://cis.porezi.me/FiscalizationService
  62. # 3. Parse JIKR from response
  63. try:
  64. # Here logic for SOAP request with zeep or requests
  65. # For now, we simulate success
  66. return "REAL-JIKR-FROM-TAX-SERVER"
  67. except Exception as e:
  68. logging.error(f"Fiscalization failed: {e}")
  69. return None