notebookvb
This commit is contained in:
@@ -0,0 +1,105 @@
|
|||||||
|
"""
|
||||||
|
Stahování seznamu registrovaných pojištěnců OZP (207) — čistý Python.
|
||||||
|
|
||||||
|
OZP běží na stejné platformě jako ZPŠ (portalzp.cz / json-api).
|
||||||
|
Tento skript zatím umí jen KROK 1: přihlášení certifikátem.
|
||||||
|
|
||||||
|
Stavba poběží postupně:
|
||||||
|
[krok 1] přihlášení certifikátem ← hotovo
|
||||||
|
[krok 2] stažení nových výpisů ze schránky
|
||||||
|
[krok 3] podání žádosti o další měsíc
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
|
from cryptography.hazmat.primitives.serialization import pkcs7, pkcs12
|
||||||
|
|
||||||
|
PFX_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "Certificates", "MBQualifiedCert.pfx"))
|
||||||
|
PFX_PASSWORD = b"Vlado7309208104++"
|
||||||
|
|
||||||
|
BASE_URL = "https://portal.ozp.cz"
|
||||||
|
CHALLENGE_URL = f"{BASE_URL}/json-api/prihlaseni/prihlasovaci-zprava"
|
||||||
|
CERTLOGIN_URL = f"{BASE_URL}/json-api/prihlaseni/prihlaseni-certifikatem"
|
||||||
|
|
||||||
|
# Sdílený cookies soubor s OZP skriptem pro stahování zpráv
|
||||||
|
COOKIES_FILE = os.path.abspath(os.path.join(
|
||||||
|
os.path.dirname(__file__), "..", "..", "StahováníZpráv", "207 OZP", "ozp_cookies.json"
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
def prihlaseni() -> requests.Session:
|
||||||
|
"""Přihlásí se certifikátem, vrátí autentizovanou session. Uloží cookies pro Playwright."""
|
||||||
|
session = requests.Session()
|
||||||
|
session.headers.update({
|
||||||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
"Origin": BASE_URL,
|
||||||
|
"Referer": BASE_URL + "/",
|
||||||
|
})
|
||||||
|
|
||||||
|
# 1. Načti login stránku → session cookie
|
||||||
|
r = session.get(f"{BASE_URL}/app/prihlaseni")
|
||||||
|
r.raise_for_status()
|
||||||
|
session.cookies.set("pzp_sign", "CERT", domain="portal.ozp.cz", path="/")
|
||||||
|
|
||||||
|
# 2. Získej challenge
|
||||||
|
r = session.post(CHALLENGE_URL, json={"login_sign": "CERT"},
|
||||||
|
headers={"Content-Type": "application/json; charset=UTF-8"})
|
||||||
|
r.raise_for_status()
|
||||||
|
zprava = r.json()["data"]["zprava"]
|
||||||
|
print(f"Challenge: {zprava[:60]}...")
|
||||||
|
|
||||||
|
# 3. Podepiš challenge certifikátem (PKCS7 detached, RSA + SHA-256, s certifikátem)
|
||||||
|
with open(PFX_PATH, "rb") as f:
|
||||||
|
private_key, cert, _ = pkcs12.load_key_and_certificates(f.read(), PFX_PASSWORD)
|
||||||
|
|
||||||
|
podpis = (
|
||||||
|
pkcs7.PKCS7SignatureBuilder()
|
||||||
|
.set_data(zprava.encode("utf-8"))
|
||||||
|
.add_signer(cert, private_key, hashes.SHA256())
|
||||||
|
.sign(serialization.Encoding.PEM, [pkcs7.PKCS7Options.DetachedSignature])
|
||||||
|
.decode("ascii").strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. Přihlas se
|
||||||
|
r = session.post(CERTLOGIN_URL, json={"zprava": zprava, "podpis": podpis},
|
||||||
|
headers={"Content-Type": "application/json; charset=UTF-8"})
|
||||||
|
r.raise_for_status()
|
||||||
|
data = r.json()["data"]
|
||||||
|
|
||||||
|
if not data.get("prihlasen"):
|
||||||
|
raise RuntimeError(f"Přihlášení selhalo: {r.json().get('errMsg', '')}")
|
||||||
|
|
||||||
|
print(f"Přihlášení úspěšné! {data.get('url', '')}")
|
||||||
|
|
||||||
|
# 5. Ulož cookies pro Playwright
|
||||||
|
cookies = [
|
||||||
|
{
|
||||||
|
"name": c.name,
|
||||||
|
"value": c.value,
|
||||||
|
"domain": c.domain if c.domain.startswith(".") else "." + c.domain,
|
||||||
|
"path": c.path or "/",
|
||||||
|
"expires": int(c.expires) if c.expires else -1,
|
||||||
|
"secure": bool(c.secure),
|
||||||
|
"httpOnly": False,
|
||||||
|
"sameSite": "Lax",
|
||||||
|
}
|
||||||
|
for c in session.cookies
|
||||||
|
]
|
||||||
|
with open(COOKIES_FILE, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(cookies, f, indent=2, ensure_ascii=False)
|
||||||
|
print(f"Cookies uloženy: {len(cookies)} → {COOKIES_FILE}")
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
def hlavni() -> None:
|
||||||
|
prihlaseni()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
hlavni()
|
||||||
Reference in New Issue
Block a user