Files
lux_fiscal/backend/app/services/crm/checksum.py
lauadminandClaude Sonnet 5 f4072be451 Add CRM order queue: live sync, view modal, receipt tabs, delete
Wires the CRM (exoCRM GetOrders) into the dashboard as a locally
persisted order queue instead of the previous static mockup:

- CrmClient Protocol + ExoCrmClient/StubCrmClient for the CRM's
  signed JSON-RPC API
- Order model + migration, synced from CRM on each queue view;
  soft-deleted orders stay hidden across re-syncs
- GET/DELETE /api/v1/orders with "no receipt"/"receipt issued" tabs
  (the latter is empty until Checkbox fiscalization lands)
- Dashboard: real order list, item-detail modal, tab switcher,
  one-click delete

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 21:39:03 +03:00

39 lines
1.7 KiB
Python

"""Контрольная сумма запросов к CRM API (см. документацию "My CRM API 1.1")."""
from __future__ import annotations
import hashlib
from typing import Any
def _collect_values_sorted(obj: Any) -> list[Any]:
"""Рекурсивно сортирует ключи на каждом уровне и собирает значения depth-first."""
values: list[Any] = []
if isinstance(obj, dict):
for key in sorted(obj.keys()):
values.extend(_collect_values_sorted(obj[key]))
elif isinstance(obj, list):
for item in obj:
values.extend(_collect_values_sorted(item))
else:
values.append(obj)
return values
def _to_str(value: Any) -> str:
# Булевы значения CRM ожидает в контрольной сумме как "1"/"" (PHP-style
# truthy-приведение) — это нигде не задокументировано и подобрано опытным
# путём: "True"/"False" и "true"/"false" оба дают "Checksum Error".
if isinstance(value, bool):
return "1" if value else ""
return str(value)
def compute_md5sum(payload: dict[str, Any], secret_key: str) -> str:
"""Считает md5sum по алгоритму из документации CRM: отсортировать все ключи
(включая вложенные), конкатенировать все значения, добавить приватный ключ, взять MD5.
"""
values = _collect_values_sorted(payload)
concatenated = "".join(_to_str(v) for v in values)
return hashlib.md5((concatenated + secret_key).encode("utf-8")).hexdigest()