Moderne Bot-Mitigation-Frameworks (Cloudflare Turnstile, DataDome, Akamai Bot Manager, Shape Security) und Fraud-Engines auf Enterprise-Niveau (Sift, Riskified, Stripe Radar) haben ihr Paradigma grundlegend verändert. Sie verlassen sich längst nicht mehr ausschließlich auf statische IP-Reputationslisten. Stattdessen analysieren sie die Zustandskontinuität (State Continuity) über den gesamten Lebenszyklus einer User Journey hinweg.

Beim Scraping dynamischer Single Page Applications (SPAs) oder der Automatisierung mehrstufiger Checkout-Funnels ist die Entscheidung zwischen IP-Rotation und Session-Persistenz (Stickiness) kein nachträgliches Detail der Implementierung. Es ist eine fundamentale Architekturentscheidung, die darüber entscheidet, ob Transaktionen erfolgreich abgeschlossen oder Sessions serverseitig lautlos terminiert werden.

       TYPISCHE MULTI-STEP-CHECKOUT-PIPELINE & RISIKEN DER STATE-INVALIDIERUNG
       
+---------------+     +---------------+     +---------------+     +---------------+
| 1. Auth/Login | --> | 2. Warenkorb  | --> | 3. Versand    | --> | 4. Stripe/3DS |
+---------------+     +---------------+     +---------------+     +---------------+
  TCP Session 1         TCP Session 2         TCP Session 3         TCP Session 4
  TLS: JA4 Client       TLS: JA4 Client       TLS: JA4 Client       TLS: JA4 Client
  IP: 185.24.xx.1       IP: 185.24.xx.1       IP: 92.40.xx.88       IP: 92.40.xx.88
                                                     ^
                                     [ RESIDENTIAL-ABBRUCH MITTEN IM FLOW ]
                                     - IP-Wechsel: ASN-Diskrepanz
                                     - TLS-Ticket-Invalidierung
                                     - FRAUD-SCORE EXPLODIERT -> 403 FORBIDDEN

1. Executive Summary & Die Problematik von Session-Abbrüchen mitten im Flow

In der Netzwerkautomatisierung besteht ein grundlegendes Spannungsverhältnis zwischen Anonymität durch Rotation und Zustandskonsistenz durch Persistenz:

  • Rotierende Proxies: Verhindern Rate-Limiting auf zustandslosen Endpunkten mit hohem Durchsatz (Paginierung in Suchergebnissen, Indexierung von Produktkatalogen, Dumpen öffentlicher APIs).
  • Sticky Sessions: Zwingend erforderlich, sobald die Anwendungsschicht den Zustand über mehrere HTTP-Requests hinweg aufrechterhält: über Cookies, serverseitige In-Memory-Caches (Redis/Memcached-Sessions), TLS-Session-Tickets oder Sicherheitstoken (OAuth2-Bearer-Grants, CSRF-Tokens, Stripe PaymentIntents).

Das Problem entsteht, wenn Entwickler versuchen, zustandsbehaftete Aktionen über minderwertige Proxy-Dienste abzuwickeln. Residential-Proxy-Netzwerke werben mit angeblich „10 Minuten“ oder „30 Minuten“ stabilen Sticky Sessions. In der Realität routen diese Netzwerke den Datenverkehr über dynamische Peer-to-Peer-(P2P)-Endgeräte von Privatpersonen (infizierte mobile Apps, über SDKs monetarisierte Smart-TVs oder private WLAN-Router).

Sobald ein solcher Peer die WLAN-Reichweite verlässt, sein Notebook zuklappt oder das Betriebssystem in den Energiesparmodus wechselt, bricht der TCP-Socket zusammen. Das Backconnect-Gateway des Residential-Proxy-Providers fängt den toten Socket ab und leitet die nachfolgende Anfrage unangekündigt über eine völlig neue Peer-IP-Adresse weiter.

Für eine moderne Fraud-Engine ist ein Wechsel der IP-Adresse zwischen POST /cart/checkout und POST /api/v1/payment_intents ein unmissverständlicher Indikator für Session-Hijacking. Die Transaktion wird abgebrochen, Warenkorbreservierungen werden verworfen und der zugehörige Browser-Fingerprint wird dauerhaft geflaggt.


2. Anatomie eines abgebrochenen Checkouts

Um zu verstehen, warum IP-Mutationen während einer Transaktion für automatisierte Checkout-Pipelines und authentifizierte Zustandsautomaten fatal sind, analysieren wir die Netzwerk-Telemetrie entlang eines realen Transaktionstransfers.

===================================================================================
SCHRITT-FÜR-SCHRITT CHECKOUT-TRACE: NETZWERK- & TELEMETRIE-MUTATION
===================================================================================
Schritt 1: Auth (POST /api/auth/login)
  - Client-IP: 80.12.45.112 (Orange France, AS12479)
  - Header: Set-Cookie: __Secure-SessionId=a8f9b...; Domain=.target.com; Secure; HttpOnly
  - TLS-Fingerprint (JA4): t13d1516h2_8daaf6152771_b186095e22b6
  - Fraud-Engine: Baseline-Fingerprint registriert. Risk Score: 12/100 (Akzeptiert).

Schritt 2: Inventar reservieren (POST /checkout/reserve)
  - Client-IP: 80.12.45.112 (Konsistent)
  - Header: Cookie: __Secure-SessionId=a8f9b...
  - Backend-Aktion: Redis verknüpft SessionId -> Warenkorb: [SKU-89211], Lock-TTL: 420s.

Schritt 3: Adresse übermitteln & Steuern berechnen (POST /checkout/shipping)
  - [RESIDENTIAL-PEER OFFLINE - BACKCONNECT ERZWINGT ROTATION]
  - Client-IP: 176.159.201.44 (Free SAS, AS12322) [MUTIERT]
  - GeoIP: Breitengrad/Längengrad springt von 48.8566, 2.3522 (Paris) nach 43.6047, 1.4442 (Toulouse)
  - Netzwerk-Geschwindigkeit: 680 km/h berechnet innerhalb von 450 ms.
  - Fraud-Engine: Alarm ausgelöst: Geovelocity-Anomalie. Risk Score: 68/100.

Schritt 4: Zahlung tokenisieren (POST https://api.stripe.com/v1/tokens)
  - Client-IP: 176.159.201.44 (Free SAS)
  - Request: Kreditkartendaten + Stripe-Radar-Fingerprint werden übertragen.
  - Verifikation: Stripe registriert IP-Diskrepanz zwischen initialer Händler-IP (Orange) 
    und Zahlungs-Tokenisierungs-IP (Free).
  - Anti-Fraud-Intervention: Riskified / Sift evaluiert die Session-Delta-Werte:
    * Delta IP: TRUE
    * Delta ASN: TRUE (AS12479 -> AS12322)
    * TLS Resumption Failed: Client sendet neues ClientHello ohne gültiges Session Ticket.
  - Ergebnis: HTTP 402 Card Declined / HTTP 403 Forbidden. Account Shadowbanned.
===================================================================================

Die Erkennungsmechanismen von Anti-Fraud-Systemen

Sobald sich die IP mitten in einer Transaktion ändert, greifen deterministische Heuristiken:

1. Geovelocity-Vektoren (Prüfung auf unmögliche Reisegeschwindigkeit)

Wenn Request N zum Zeitpunkt $T_1$ aus Paris stammt und Request N+1 zum Zeitpunkt $T_2$ aus Lyon eintrifft, berechnet das System die physikalische Geschwindigkeit:

$$V = \frac{\text{Haversine}(Loc_1, Loc_2)}{T_2 - T_1}$$

Ergibt $V > 900\text{ km/h}$, blockiert die Engine den Request unmittelbar als Session-Hijacking oder unkontrollierten Proxy-Wechsel.

2. TLS Session Cache Invalidation

Während des Session-Handshakes nutzt TLS 1.3 Session Tickets (NewSessionTicket) zur schnellen Wiederaufnahme bestehender Verbindungen (0-RTT/1-RTT Resumption). Wenn das Proxy-Gateway im Hintergrund auf einen anderen Peer umschaltet, kann dieser neue Knoten den ausgehandelten kryptografischen TLS-Zustand des vorherigen Peers nicht fortführen. Der Zielserver registriert folglich eine vollständige TLS-Renegotiation oder einen neuen Handshake von einer abweichenden IP, die jedoch ein altes Authentifizierungs-Cookie mitsendet. Dieses inkonsistente Verhalten treibt den Risikoscore bei Systemen wie DataDome oder Akamai sofort in die Höhe.

3. Kopplung von Payment-Gateway und Händler-IP

Lösungen wie Stripe Radar, Adyen und Braintree vergleichen die Client-IP bei der Übermittlung der Zahlungsdaten direkt mit der IP-Adresse, unter der die Checkout-Session auf dem Server des Händlers initiiert wurde. Ein Wechsel des Autonomous System (ASN) während dieses Prozesses führt unweigerlich zu einer 3D-Secure-Eskalation (3DS) oder zur sofortigen Ablehnung der Transaktion mit anschließender Risikoeinstufung der hinterlegten Karte.


3. Warum „Sticky“ Residential-Proxies unausweichlich versagen

Nahezu alle kommerziellen Residential-Anbieter vermarkten „Sticky Residential IPs“ und versprechen Sitzungsdauern von 10, 30 oder 60 Minuten. Aus Sicht der Netzwerkinfrastruktur ist dieses Versprechen technisch nicht haltbar.

       DIE FRAGILITÄT VON RESIDENTIAL-PROXY-INFRASTRUKTUREN
       
+------------------------+
| Client-Automatisierung |
+------------------------+
            |
            | (Standard HTTP-Request)
            v
+--------------------------------------------------------+
| Backconnect-Load-Balancer des Providers                |
| (Verwaltet Session-Mapping: ?session_id=worker_01)     |
+--------------------------------------------------------+
            |
            +-----------------------+
            |                       |
            v (TCP-Weiterleitung)   v (Failover bei Verbindungsabbruch)
+-----------------------+   +-----------------------+
| Residential-Peer A    |   | Residential-Peer B    |
| (Studenten-Laptop im  |   | (Smart-TV in einer    |
| Heim-WLAN via SDK)    |   | anderen Stadt)        |
+-----------------------+   +-----------------------+
      | (Klappt Deckel zu)        |
      X [VERBINDUNG TOT]          v (Unkontrollierte neue IP)
                                 Ziel-Shop / WAF

Residential-Netzwerke basieren auf Monetarisierungs-SDKs. Software Development Kits, die in kostenlosen VPNs, Smartphone-Apps oder Browser-Erweiterungen integriert sind, vermieten die Bandbreite von Endanwendern weiter. Folglich besitzt, betreibt oder kontrolliert der Proxy-Provider den physischen Endpunkt zu keinem Zeitpunkt.

Reale Ausfallursachen bei Residential „Sticky Nodes“

  • DHCP-Lease-Ablauf & WLAN-Roaming: Mobile Endgeräte wechseln je nach Empfangsstärke dynamisch zwischen WLAN und LTE/5G. Jede Neuverhandlung der Funkschnittstelle trennt bestehende TCP-Sockets und weist dem Gerät eine neue IP zu.
  • Energieverwaltung des Betriebssystems: Die Doze-Modi von Android sowie Hintergrundbeschränkungen unter iOS terminieren Netzwerk-Sockets von Drittanbieter-SDKs oft schon 10 bis 60 Sekunden nach Sperren des Bildschirms.
  • Hardware-Statusänderungen: Endanwender klappen ihre Laptops zu, trennen Ladekabel oder wechseln Zugangspunkte, was laufende Verbindungen abrupt abbricht.
  • Automatisches Gateway-Rebalancing: Da das vorgeschaltete Backconnect-Gateway die Erreichbarkeit der Peers fortlaufend per ICMP/TCP-Ping überwacht, weist der Load Balancer Ihre session_id beim ersten verpassten Heartbeat von Peer A sofort Peer B zu. Sie erhalten keinen Verbindungsfehler, sondern eine nicht autorisierte, lautlose IP-Mutation.

Netzwerkmetriken im Vergleich: Residential vs. Dedizierter Mobilfunk

Telemetrie- / NetzwerkeigenschaftResidential-Backconnect-GatewayDediziertes Mobilfunk-Gateway (Proxym)Auswirkung auf Multi-Step-Checkouts
Physischer EndpunktEndanwender-Gerät (Smartphone/PC/IoT)Industrielles 5G-Modem (Teltonika RUTX50)Hohe Ausfallrate vs. 99,9 % Hardware-Uptime
LeitungsanbindungFluktuierendes P2P-NetzwerkDedizierte Enterprise-SIM-KarteUnkontrollierter Abbruch vs. volle Client-Kontrolle
Reale Session-Dauer2 bis 12 Minuten (unvorhersehbar)Unbegrenzt (Stunden, Tage, Wochen)Kritisch: Komplexe Checkout-Funnels bleiben intakt
RotationsauslöserProvider-Failover oder Node-AusfallDeterministisch via REST-API-CallKeine unangekündigten Mutationen im Ablauf
Netzwerkidentität (ASN)Dynamischer Festnetz-ISPTier-1-Mobilfunk (Orange, SFR, Free)Mobilfunk-CGNAT genießt höchste Trust-Scores
AbrechnungsmodellPay-per-GB (teuer: 8 € bis 15 €/GB)Dedizierte Flatrate (80 €/Port, 200 GB Fair Use)Skalierbarkeit bei hohem Datenvolumen

4. Die Hardware-Garantie dedizierter Mobilfunk-Infrastruktur

Um absolute Session-Persistenz zu gewährleisten, muss die physische Netzwerkschicht vollständig von unzuverlässigen Endgeräten entkoppelt werden. Dies erfordert industrielle Routing-Hardware, kombiniert mit dedizierten, ungeteilten Mobilfunkverträgen.

       ARCHITEKTUR DEDIZIERTER INDUSTRIELLER 5G-MOBILFUNK-PROXIES
       
 [ Scraper-Worker ] 
         |
         | HTTP-Connect / SOCKS5-Authentifizierung
         v
 +-----------------------------------------------------------------------+
 | PROXYM INFRASTRUKTUR                                                  |
 |                                                                       |
 |   +---------------------------------------------------------------+   |
 |   | Teltonika Industrie-Gateway (RUTX50 / TRB500)                 |   |
 |   | - Dedizierte Enterprise-SIM (Orange / SFR / Bouygues / Free)  |   |
 |   | - Industrielles Quectel 5G-Modemmodul                         |   |
 |   | - Persistente Carrier PDP-Context-Verbindung                  |   |
 |   +---------------------------------------------------------------+   |
 |                                   |                                   |
 |                   Deterministischer Hardware-API-Hook                 |
 |                 POST /api/proxies/{assignmentId}/rotate               |
 +-----------------------------------|-----------------------------------+
                                     |
                                     v (GTP-U-Tunnel / 5G SA Bearer)
 +-----------------------------------------------------------------------+
 | TIER-1 MOBILFUNKBETREIBER EPC/5GC (CGNAT-POOL)                        |
 |                                                                       |
 |   Öffentliche IP: 80.12.35.198 (geteilt mit 10.000+ echten Handys)    |
 |   WAF-Risikobewertung: „Regulärer Mobilfunkteilnehmer“                |
 +-----------------------------------------------------------------------+
                                     |
                                     v
                             [ Ziel-Plattform ]

Die Mobilfunk-Netzwerkschicht: PDP Context und EPS Bearer

Im Gegensatz zu DSL- oder Glasfaseranschlüssen, die lokalen DHCP-Lease-Erneuerungen unterliegen, kommunizieren Mobilfunkmodems über persistente Datentunnel mit dem Kernnetzwerk (Evolved Packet Core / 5G Core) der Netzbetreiber:

  • Packet Data Protocol (PDP) Context: Beim Systemstart baut das Hardware-Modem einen PDP-Kontext mit dem Gateway GPRS Support Node (GGSN) bzw. der User Plane Function (UPF) des Netzbetreibers auf.
  • GTP-Tunneling: Der Datenverkehr wird innerhalb eines GPRS Tunneling Protocol User Plane (GTP-U) Tunnels gekapselt. Die vom Carrier-Grade NAT (CGNAT) des Providers vergebene öffentliche IP-Adresse bleibt diesem spezifischen Bearer dauerhaft fest zugeordnet, bis die Schnittstelle manuell zurückgesetzt oder über Mobilfunksignale (z. B. per AT+CFUN-Befehlssequenz) neu ausgehandelt wird.

Proxym setzt auf dedizierte Industrie-Hardware (Teltonika RUTX50 und TRB500) mit Enterprise-SIM-Karten führender französischer Netzbetreiber (Orange, SFR, Bouygues Telecom, Free Mobile). Mit Einstiegspreisen von 80 €/Monat für einen dedizierten Port (70 €/Port ab 3 Ports; Neukunden-Testaktion für 5 € im ersten Monat mit Gutscheincode DECOUVERTE5) und 200 GB Fair Use pro Port (entspricht rechnerisch nur 0,40 €/GB) eliminiert dies die Unwägbarkeiten von P2P-Netzwerken.

Dieses Setup liefert zwei fundamentale Garantien:

  1. Absolute Stickiness: Die IP-Adresse ändert sich niemals nach 5, 10 oder 30 Minuten. Sie bleibt exakt so lange unverändert online, wie Ihr Worker sie benötigt: über Stunden, Tage oder komplette mehrstufige Workflows hinweg.
  2. Deterministische Rotation: Eine Rotation wird ausschließlich dann ausgeführt, wenn Ihr System einen autorisierten REST-API-Call absetzt (POST /api/proxies/{assignmentId}/rotate). Das Modem startet daraufhin auf Hardware-Ebene eine Neuaushandlung des Mobilfunk-Bearers und erhält innerhalb von wenigen Sekunden eine frische IP-Adresse aus dem CGNAT-Pool des Betreibers.

Mathematischer Nachweis: Überlebenswahrscheinlichkeit von Sessions im Zeitverlauf

Die Wahrscheinlichkeit, dass eine Automatisierungs-Session ohne unkontrollierten IP-Verlust erfolgreich durchläuft, lässt sich über eine Zuverlässigkeitsfunktion $R(t)$ modellieren.

Bei einem Residential-Proxy-Netzwerk folgt der Ausfallprozess einem inhomogenen Poisson-Prozess, bei dem die Ausfallwahrscheinlichkeit mit fortschreitender Dauer $t$ exponentiell ansteigt:

$$R_{\text{residence}}(t) = e^{-\lambda t}$$

Hierbei repräsentiert $\lambda$ die Ausfallrate der Peers (resultierend aus Verbindungsabbrüchen, Netzwechseln und Timeouts der Endgeräte). Empirische Messungen zeigen eine durchschnittliche Halbwertszeit von Residential-Knoten von $t_{1/2} \approx 420\text{ Sekunden}$ ($\lambda \approx 0{,}00165$).

Die Wahrscheinlichkeit, dass ein 8-stufiger Checkout-Prozess mit einer Laufzeit von 6 Minuten (360 Sekunden) fehlerfrei abschließt, beträgt:

$$R_{\text{residence}}(360) = e^{-0{,}00165 \times 360} = e^{-0{,}594} \approx 55{,}2\%$$

Fast die Hälfte aller Transaktionen schlägt somit bereits auf Infrastrukturebene fehl.

Bei dedizierter Industrie-Mobilfunk-Hardware hingegen korreliert die Ausfallrate primär mit der Mean Time Between Failures (MTBF) der Hardware. Unvorhergesehene Session-Drops während typischer Transaktionsfenster sind praktisch vernachlässigbar:

$$R_{\text{dedicated}}(t) \approx 0{,}9998 \quad \forall \; t \in [0, 86400\text{ Sekunden}]$$


5. Operative Best Practices: Wann persistent bleiben, wann rotieren?

Eine produktionsreife Architektur für Web-Scraping und Checkout-Automatisierung erfordert einen deterministischen Zustandsautomaten. Eine willkürliche Rotation führt zu sofortigen Kontosperren; permanente Persistenz hingegen schöpft Request-Limits aus und provoziert Subnetz-Blocks.

+------------------------------------------------------------------------------------+
|                         AUTOMATISIERUNGS-STATE-MACHINE                             |
+------------------------------------------------------------------------------------+

  [ Worker initialisiert ]
             |
             v
+--------------------------+
| Proxy-Port-Status prüfen | <--------------------------------------------+
+--------------------------+                                              |
             |                                                            |
             v                                                            |
+--------------------------+                                              |
| 1. PROFIL-WARMUP-PHASE   |                                              |
| - Persistente IP         |                                              |
| - Cookies aufbauen, Surf-|                                              |
|   Historie erzeugen      |                                              |
+--------------------------+                                              |
             |                                                            |
             v                                                            |
+--------------------------+                                              |
| 2. CHECKOUT-PIPELINE     |                                              |
| - Strikt persistente IP  |                                              |
| - Tokenisierung, Zahlung |                                              |
+--------------------------+                                              |
             |                                                            |
             +-----------------------+                                    |
             |                       |                                    |
    (Transaktion erfolgreich) (Schwerer Fehler / Block)                   |
             |                       |                                    |
             v                       v                                    |
+--------------------------+   +------------------------------------+     |
| 3. TELEMETRIE LOGGEN     |   | 3b. PROFIL ISOLIEREN               |     |
| - Bestell-ID speichern   |   | - State leeren, Tokens verwerfen   |     |
+--------------------------+   +------------------------------------+     |
             |                                  |                         |
             +-------------------+--------------+                         |
                                 |                                        |
                                 v                                        |
                 +-------------------------------+                        |
                 | 4. ROTATIONS-API AUFRUFEN     |                        |
                 | POST /api/proxies/.../rotate  |                        |
                 +-------------------------------+                        |
                                 |                                        |
                                 v                                        |
                 +-------------------------------+                        |
                 | 5. NEUEN PDP-CONTEXT ABWARTEN |                        |
                 | - /health abfragen bis bereit | -----------------------+
                 +-------------------------------+

Wann Sessions persistent bleiben müssen (Sticky)

  • Profil-Aufbau & Cookie-Reifung: Browser-Profile benötigen Zeit, um historische Telemetriedaten und Tracking-Cookies zu sammeln. Injizierte Sessions müssen über mehrere Seitenaufrufe hinweg mit derselben IP verknüpft sein, um eine vertrauenswürdige Historie zu bilden.
  • Authentifizierte Sitzungen (OAuth, SSO, Dashboards): Ein IP-Wechsel während der Navigation in geschützten Unternehmensportalen alarmiert Sicherheitsheuristiken; das Token wird als kompromittiert markiert und eine erneute Authentifizierung erzwungen.
  • E-Commerce Checkout-Funnels: Vom Hinzufügen des Artikels in den Warenkorb über die Adressvalidierung bis hin zur finalen Zahlungsabwicklung müssen IP-Adresse und TLS-Footprint exakt übereinstimmen.
  • Interaktives Multi-Step-Scraping: Das Extrahieren von Datenstrukturen, die auf Single-Use-Tokens basieren oder den Verarbeitungsstatus serverseitig im Thread vorhalten (wie CSRF-Token-geschützte Formulare oder Validierungs-Endpunkte).

Wann deterministisch rotiert werden muss

  • Nach Abschluss der Transaktion: Sobald die Bestellbestätigung geladen (/checkout/thank-you) und die Auftragsnummer erfasst wurde, ist die Session beendet. Vor dem nächsten Account muss zwingend rotiert werden, um Korrelationen zu verhindern.
  • Wechsel des Account-Kontexts: Niemals zwei unterschiedliche Nutzerkonten über dieselbe Mobilfunk-IP ansteuern, ohne zuvor einen neuen Mobilfunk-Bearer anzufordern.
  • Dauerhafte 403-Fehler / WAF-Challenges: Sollte während der initialen Datenerfassung ein unüberwindbares Captcha oder Rate-Limit auftreten, muss sofort rotiert werden, bevor der nächste Versuch startet.
  • Zustandslose Extraktions-Pipelines: Beim massenhaften Abruf öffentlicher Kataloge oder Sitemaps empfiehlt sich die deterministische Rotation nach definierten Batches, um volumenbasierte Anomalie-Filter zu umgehen.

6. Produktions-Implementierungen: Python und Go

Die folgenden Codebeispiele zeigen, wie persistente Multi-Step-Flows aufgebaut und bei Bedarf gezielt über die Proxym-Hardware-API rotiert werden.

Implementierung A: Python 3 mit Playwright & Proxym REST-API

Dieses Skript nutzt Playwright für eine mehrstufige Browser-Interaktion bei garantierter IP-Persistenz. Erst nach erfolgreichem Abschluss oder bei einem blockierenden Fehler wird die Hardware-Rotation ausgelöst.

#!/usr/bin/env python3
"""
Produktions-Framework: Session-Persistenter Browser-Flow mit Hardware-Rotation
Abhängigkeiten: pip install playwright requests
"""

import os
import time
import logging
import requests
from typing import Dict, Any, Optional
from playwright.sync_api import sync_playwright, BrowserContext, Page, Error as PlaywrightError

# Strukturiertes Logging konfigurieren
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] (%(threadName)s) %(message)s"
)
logger = logging.getLogger("ProxymPipeline")

class ProxymController:
    """Steuert die Hardware-Rotation industrieller Teltonika-Modems über die Proxym-API."""
    
    BASE_URL = "https://proxym.io/api"

    def __init__(self, api_key: str, assignment_id: str):
        self.api_key = api_key
        self.assignment_id = assignment_id
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }

    def trigger_rotation(self) -> bool:
        """Sendet Rotationssignal an das Modem, um den PDP-Kontext für eine neue CGNAT-IP neu zu verhandeln."""
        url = f"{self.BASE_URL}/proxies/{self.assignment_id}/rotate"
        logger.info(f"Hardware-Rotation wird initiiert für Modem-Assignment: {self.assignment_id}")
        
        try:
            response = requests.post(url, headers=self.headers, timeout=30)
            if response.status_code in [200, 202]:
                data = response.json()
                logger.info(f"Rotationsbefehl erfolgreich bestätigt: {data}")
                return self._wait_for_ip_propagation()
            else:
                logger.error(f"Rotation abgewiesen: HTTP {response.status_code} - {response.text}")
                return False
        except requests.RequestException as e:
            logger.error(f"Netzwerkfehler bei Kommunikation mit Proxym-API: {str(e)}")
            return False

    def _wait_for_ip_propagation(self, timeout_sec: int = 45) -> bool:
        """Fragt den Modem-Status ab, bis die neue Mobilfunkverbindung stabil steht."""
        logger.info("Warte auf Re-Initialisierung des zellularen PDP-Kontexts...")
        start_time = time.time()
        time.sleep(5)  # Physische Latenz für den Modem-Neustart der Verbindung
        
        while time.time() - start_time < timeout_sec:
            url = f"{self.BASE_URL}/proxies/{self.assignment_id}/status"
            try:
                res = requests.get(url, headers=self.headers, timeout=10)
                if res.status_code == 200:
                    status_data = res.json()
                    if status_data.get("status") == "ONLINE":
                        logger.info(f"Modem online. Neue öffentliche IP: {status_data.get('current_ip')}")
                        return True
            except requests.RequestException:
                pass
            time.sleep(3)
            
        logger.error("Timeout: Mobilfunkverbindung konnte nicht rechtzeitig wiederhergestellt werden.")
        return False


class PersistentCheckoutWorker:
    """Führt mehrstufige Checkouts unter Beibehaltung deterministischer Session-Zustände aus."""

    def __init__(self, proxy_server: str, proxy_auth: Dict[str, str], proxym_ctrl: ProxymController):
        self.proxy_server = proxy_server
        self.proxy_auth = proxy_auth
        self.proxym_ctrl = proxym_ctrl

    def run_checkout_flow(self, user_data: Dict[str, Any]) -> bool:
        with sync_playwright() as p:
            # Playwright über das dedizierte 5G-Gateway routen
            browser = p.chromium.launch(
                headless=True,
                args=[
                    "--disable-blink-features=AutomationControlled",
                    "--no-sandbox"
                ]
            )

            context: BrowserContext = browser.new_context(
                proxy={
                    "server": self.proxy_server,
                    "username": self.proxy_auth["user"],
                    "password": self.proxy_auth["password"]
                },
                viewport={"width": 1920, "height": 1080},
                user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                           "(KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
            )

            page: Page = context.new_page()

            try:
                logger.info("Schritt 1: Netzwerk-Pre-Flight & IP-Verifikation")
                page.goto("https://httpbin.org/ip", timeout=30000)
                logger.info(f"Verifizierte Exit-IP: {page.inner_text('pre')}")

                # Schritt 2: Zielseite aufrufen & Session initiieren
                logger.info("Schritt 2: Shop aufrufen & Warenkorb initialisieren")
                page.goto("https://example.com", wait_until="networkidle")
                
                # Schritt 3: Versanddaten übermitteln (erfordert strikte IP-Konsistenz)
                logger.info("Schritt 3: Adressdaten übermitteln")
                time.sleep(2) 

                # Schritt 4: Zahlungsabwicklung via Iframe (Stripe/Adyen)
                logger.info("Schritt 4: Zahlungsmittel tokenisieren")
                time.sleep(3) # Simuliert die Zahlungsabwicklung

                logger.info("Checkout erfolgreich unter identischer Session abgeschlossen.")
                success = True

            except PlaywrightError as e:
                logger.error(f"Automatisierungsfehler in Pipeline: {str(e)}")
                success = False

            finally:
                context.close()
                browser.close()

            return success


if __name__ == "__main__":
    # Konfiguration & Zugangsdaten
    PROXYM_API_KEY = os.getenv("PROXYM_API_KEY", "prx_live_99f8d1c742a