From b9de2bcd30791ab1e387084e3e37b2fcc8a6157d Mon Sep 17 00:00:00 2001 From: Marius Robert Macamete Date: Sat, 20 Dec 2025 18:22:53 +0200 Subject: [PATCH] something --- UI_V2/flask_server.py | 48 ++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/UI_V2/flask_server.py b/UI_V2/flask_server.py index dd83a3d..c1d4750 100644 --- a/UI_V2/flask_server.py +++ b/UI_V2/flask_server.py @@ -55,48 +55,40 @@ def healthz(): def ipn(): token = request.headers.get('Verification-Token') or request.headers.get('X-Netopia-Signature') - if not token: - app.logger.error("No token found") - return jsonify({"errorCode": 1, "error": "No token"}), 400 - try: - # Get the clean key from your env/settings from helpers.netopia import NetopiaSettings settings = NetopiaSettings.from_env() - # Ensure newlines are correct public_key = settings.public_key_str.replace('\\n', '\n').strip() - if not public_key.startswith("-----BEGIN"): - public_key = f"-----BEGIN PUBLIC KEY-----\n{public_key}\n-----END PUBLIC KEY-----" - - # MANUAL VERIFICATION - # We allow 30 seconds of 'leeway' for the clock - # We specify RS512 because that's what Netopia uses + + # 1. Try to decode without Audience check first to isolate the Signature + # This tells us if the Public Key actually matches the Private Key used by Netopia decoded_data = jwt.decode( token, public_key, algorithms=["RS256", "RS512"], - audience=settings.pos_signature, - leeway=30 + options={"verify_aud": False}, # Temporarily disable audience check + leeway=60 ) - app.logger.info(f"VERIFIED DATA: {decoded_data}") + app.logger.info(f"SUCCESS! Verified Data: {decoded_data}") - # If we got here, the signature is VALID! - # Now we just need to get the order status from the body - json_body = request.get_json() - order_id = json_body.get('order', {}).get('orderID') - status = json_body.get('payment', {}).get('status') - - app.logger.info(f"Order {order_id} has status {status}") + # 2. Check audience manually + token_aud = decoded_data.get('aud') + expected_aud = settings.pos_signature + # Netopia sends ['SIG'], we expect 'SIG' + if expected_aud not in token_aud and expected_aud != token_aud: + app.logger.error(f"Audience mismatch: Got {token_aud}, expected {expected_aud}") + return jsonify({"error": "Audience mismatch"}), 400 + return jsonify({"errorCode": 0}), 200 - except jwt.ExpiredSignatureError: - app.logger.error("Token expired") - return jsonify({"errorCode": 1, "error": "Expired"}), 400 - except jwt.InvalidTokenError as e: - app.logger.error(f"Invalid Token: {e}") - return jsonify({"errorCode": 1, "error": str(e)}), 400 + except jwt.InvalidSignatureError: + app.logger.error("DANGER: The Public Key does not match the signature. Check if this is the SANDBOX key.") + return jsonify({"error": "Invalid Signature"}), 400 + except Exception as e: + app.logger.error(f"Verification Failed: {type(e).__name__} - {e}") + return jsonify({"error": str(e)}), 400 @app.get("/api/payments/status")