#!/usr/bin/env python3 """ Minimal SEAP WSP connectivity test. SEAP_ENV=prod -> https://e-licitatie.ro:8883/pub (mTLS, requires credentials/client.crt + client.key extracted from p12) SEAP_ENV=demo -> http://demo.e-licitatie.ro:8884/pub (no TLS) SEAP_OP= -> SuContracts (default), CANotices, PINotices, SU_CaNotices Extract cert+key on demand (do NOT commit): source ~/Code/claude-dotfiles/load-infisical-path.sh /seap cd credentials openssl pkcs12 -in 50076FB3826FADA540ACFB19.p12 -clcerts -nokeys \\ -passin env:SEAP_CERT_KEY > client.crt openssl pkcs12 -in 50076FB3826FADA540ACFB19.p12 -nocerts -nodes \\ -passin env:SEAP_CERT_KEY > client.key chmod 600 client.{crt,key} """ import os import sys from lxml import etree from zeep import Client, Settings from zeep.plugins import HistoryPlugin from zeep.transports import Transport DEMO_WSDL = 'http://demo.e-licitatie.ro:8884/pub?wsdl' LOCAL_WSDL = os.path.join(os.path.dirname(__file__), 'wsdl', 'pub.wsdl') SICAP_NS = 'http://schemas.datacontract.org/2004/07/SICAP.Service.Integration' TEMPURI_NS = 'http://tempuri.org/' def build_credentials_header(user: str, password: str) -> etree._Element: cred = etree.Element('{%s}SeapUserCredentials' % TEMPURI_NS, nsmap={ None: TEMPURI_NS, 'i': 'http://www.w3.org/2001/XMLSchema-instance', }) pw = etree.SubElement(cred, '{%s}Password' % SICAP_NS, nsmap={None: SICAP_NS}) pw.text = password un = etree.SubElement(cred, '{%s}Username' % SICAP_NS, nsmap={None: SICAP_NS}) un.text = user return cred def main(): user = os.environ.get('SEAP_USER') pw = os.environ.get('SEAP_PASS') if not user or not pw: print('ERROR: SEAP_USER / SEAP_PASS not in env', file=sys.stderr) sys.exit(2) wsdl_source = LOCAL_WSDL if os.path.exists(LOCAL_WSDL) else DEMO_WSDL use_prod = os.environ.get('SEAP_ENV') == 'prod' endpoint = 'https://e-licitatie.ro:8883/pub' if use_prod else 'http://demo.e-licitatie.ro:8884/pub' print(f'WSDL: {wsdl_source}') print(f'Endpoint: {endpoint}') history = HistoryPlugin() settings = Settings(strict=False, xml_huge_tree=True, raw_response=False) import requests as _req session = _req.Session() if use_prod: cred_dir = os.path.join(os.path.dirname(__file__), 'credentials') session.cert = (os.path.join(cred_dir, 'client.crt'), os.path.join(cred_dir, 'client.key')) transport = Transport(timeout=30, session=session) client = Client(wsdl_source, settings=settings, transport=transport, plugins=[history]) service = client.create_service( '{http://tempuri.org/}IPubServiceEndpoint', endpoint, ) cred_header = build_credentials_header(user, pw) operation = os.environ.get('SEAP_OP', 'SuContracts') requests = { 'SuContracts': { 'PageIndex': 1, 'ContractStartDate': '2024-01-01T00:00:00', 'ContractEndDate': '2026-05-05T00:00:00', }, 'CANotices': { 'PageIndex': 1, 'PublicationStartDate': '2026-04-01T00:00:00', 'PublicationEndDate': '2026-05-05T00:00:00', }, 'PINotices': { 'PageIndex': 1, 'PublicationStartDate': '2026-04-01T00:00:00', 'PublicationEndDate': '2026-05-05T00:00:00', }, 'SU_CaNotices': { 'PageIndex': 1, 'PublicationStartDate': '2026-04-01T00:00:00', 'PublicationEndDate': '2026-05-05T00:00:00', }, } print(f'\n--- Calling {operation} ---') try: result = getattr(service, operation)( request=requests[operation], _soapheaders=[cred_header], ) except Exception as e: print(f'SOAP fault / error: {type(e).__name__}: {e}') if history.last_sent is not None: print('\n--- Last sent envelope (truncated) ---') sent = etree.tostring(history.last_sent['envelope'], pretty_print=True).decode() # redact password sent = sent.replace(pw, '') print(sent[:2000]) if history.last_received is not None: print('\n--- Last received envelope (truncated) ---') print(etree.tostring(history.last_received['envelope'], pretty_print=True).decode()[:2000]) sys.exit(1) if history.last_sent is not None: sent = etree.tostring(history.last_sent['envelope'], pretty_print=True).decode() sent = sent.replace(pw, '') print('\n--- Sent envelope ---') print(sent) if history.last_received is not None: recv = etree.tostring(history.last_received['envelope'], pretty_print=True).decode() print('\n--- Received envelope (first 3000 chars) ---') print(recv[:3000]) print('\n--- Result ---') print(f'Status: {getattr(result, "Status", "?")}') print(f'Description: {getattr(result, "Description", None)}') print(f'PageIndex: {getattr(result, "PageIndex", "?")}') print(f'PageTotal: {getattr(result, "PageTotal", "?")}') items = getattr(result, 'Items', None) if items is not None: for child_field in ('ContractItem', 'CANoticeItem', 'PINoticeItem', 'NoticeItem', 'Item'): sub = getattr(items, child_field, None) if sub: print(f'Items count ({child_field}): {len(sub)}') print(f'First item fields: {list(sub[0].__values__.keys())[:15]}') break else: print('Items present but unknown shape') if __name__ == '__main__': main()