"""POST one report follow-up and print the complete JSON response (HMAC v2).""" import argparse import base64 import hashlib import hmac import json import os import secrets import time from pathlib import Path import httpx def sign_follow_up_request( method: str, url: httpx.URL, client_id: str, secret: str, body: bytes, *, timestamp: str | None = None, nonce: str | None = None, ) -> dict[str, str]: timestamp = timestamp or str(int(time.time())) nonce = nonce or secrets.token_urlsafe(18) path, _, query = url.raw_path.partition(b"?") canonical = b"\n".join((method.upper().encode("ascii"), path, query, timestamp.encode(), nonce.encode(), body)) return { "X-Signature-Version": "2", "X-Client-Id": client_id, "X-Timestamp": timestamp, "X-Nonce": nonce, "X-Signature": base64.b64encode(hmac.new(secret.encode(), canonical, hashlib.sha256).digest()).decode(), } def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--url", required=True, help="Full /api/v1/integrations/risk-assessments/follow-up URL") parser.add_argument("--client-id", default="dieya-plm") parser.add_argument( "--body-file", type=Path, required=True, help="UTF-8 JSON with requestId/messageRequestId/operator/content" ) args = parser.parse_args() secret = os.environ.get("RISK_INTEGRATION_CLIENT_SECRET", "") if len(secret) < 32: parser.error("Set RISK_INTEGRATION_CLIENT_SECRET to the backend-issued secret (at least 32 characters)") url = httpx.URL(args.url) if url.scheme not in {"http", "https"} or url.query or url.fragment or url.userinfo: parser.error("--url must be HTTP(S) without query, credentials or fragment") body = args.body_file.read_bytes() data = json.loads(body) signed = sign_follow_up_request("POST", url, args.client_id, secret, body) signed.update({"Content-Type": "application/json", "Idempotency-Key": data["messageRequestId"]}) try: response = httpx.post(url, content=body, headers=signed, timeout=httpx.Timeout(270, connect=10)) print(response.text) return 0 if response.status_code == 200 else 1 except httpx.HTTPError as exc: print(f"调用未完成({type(exc).__name__}),请使用原 messageRequestId 和原内容重试同一接口。") return 1 if __name__ == "__main__": raise SystemExit(main())