Files
tainagustului/UI_V2/flask_server.py
2025-12-19 15:00:21 +02:00

93 lines
3.0 KiB
Python

from __future__ import annotations
import jwt
import os
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask, request, jsonify
from flask_cors import CORS
from flask import Response
from werkzeug.middleware.proxy_fix import ProxyFix
try:
from dotenv import load_dotenv
load_dotenv()
except Exception:
pass
from helpers.netopia import verify_ipn, get_status
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "*"}})
# Tell Flask it is behind a proxy and should trust the X-Forwarded headers
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
# ---------- Logging ----------
app.logger.setLevel(logging.INFO)
_log_dir = os.getenv("LOG_DIR", "logs")
os.makedirs(_log_dir, exist_ok=True)
_handler = RotatingFileHandler(os.path.join(_log_dir, "netopia_api.log"), maxBytes=1_000_000, backupCount=3)
_handler.setLevel(logging.INFO)
_handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
app.logger.addHandler(_handler)
@app.get("/healthz")
def healthz():
return {"ok": True}, 200
@app.post("/api/payments/ipn")
def ipn():
try:
app.logger.info("--- RAW REQUEST INSPECTION ---")
app.logger.info(f"Headers: {dict(request.headers)}")
app.logger.info(f"Form Data: {dict(request.form)}")
app.logger.info(f"JSON Data: {request.get_json(silent=True)}")
# Check common Netopia signature locations
sig = (request.headers.get('X-Netopia-Signature') or
request.form.get('data') or
(request.get_json(silent=True) or {}).get('data'))
if sig:
app.logger.info(f"FOUND SIGNATURE: {sig[:50]}...")
try:
import jwt
decoded = jwt.decode(sig, options={"verify_signature": False})
app.logger.info(f"DECODED POS FROM NETOPIA: {decoded.get('posSignature')}")
except Exception as e:
app.logger.error(f"Could not decode found signature: {e}")
else:
app.logger.error("NO SIGNATURE FOUND IN HEADERS, FORM, OR JSON")
# Pass the whole request object, not just request.data
data = verify_ipn(request)
app.logger.info("IPN OK: %s", data)
return jsonify({"errorCode": 0}), 200
except Exception as e:
app.logger.exception("IPN verification failed: %s", e)
return jsonify({"errorCode": 0}), 200
@app.get("/api/payments/status")
def status():
ntp_id = request.args.get("ntpID")
order_id = request.args.get("orderID")
try:
resp = get_status(ntp_id=ntp_id, order_id=order_id)
return jsonify({"ok": True, "data": resp}), 200
except Exception as e:
app.logger.exception("Status query failed: %s", e)
return jsonify({"ok": False, "error": str(e)}), 400
if __name__ == "__main__":
host = os.getenv("API_HOST", "0.0.0.0")
port = int(os.getenv("API_PORT", "9000"))
app.logger.info("Starting NETOPIA Flask sidecar on %s:%s", host, port)
app.run(host=host, port=port)