Skip to content

Commit de18363

Browse files
Update app.py
1 parent 3f10f36 commit de18363

1 file changed

Lines changed: 15 additions & 82 deletions

File tree

app.py

Lines changed: 15 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from flask import Flask, g, jsonify, request, has_request_context
3030
from flask_cors import CORS
3131

32-
APP_VERSION = "2.3.3-nowpayments-ipnstreamfix"
32+
APP_VERSION = "2.3.1-nowpayments-ipnfix"
3333
TRANSFER_TOPIC = "0xddf252ad00000000000000000000000000000000000000000000000000000000"
3434
ZERO_EVM = "0x0000000000000000000000000000000000000000"
3535
BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
@@ -4848,72 +4848,19 @@ def nowpayments_order_status(order_id: str):
48484848
})
48494849

48504850

4851-
def parse_nowpayments_ipn_payload() -> Tuple[Dict[str, Any], Dict[str, Any]]:
4851+
def parse_nowpayments_ipn_payload() -> Dict[str, Any]:
48524852
payload: Dict[str, Any] = {}
4853-
debug: Dict[str, Any] = {}
48544853

4855-
raw_bytes = b""
4856-
try:
4857-
raw_bytes = request.get_data(cache=True, as_text=False, parse_form_data=False) or b""
4858-
except TypeError:
4859-
raw_bytes = request.get_data(cache=True, as_text=False) or b""
4860-
except Exception:
4861-
raw_bytes = b""
4862-
4863-
if not raw_bytes:
4864-
try:
4865-
content_length = int(request.environ.get("CONTENT_LENGTH") or 0)
4866-
except Exception:
4867-
content_length = 0
4868-
if content_length > 0:
4869-
try:
4870-
stream = request.environ.get("wsgi.input")
4871-
if stream is not None:
4872-
raw_bytes = stream.read(content_length) or b""
4873-
except Exception:
4874-
raw_bytes = b""
4875-
4876-
raw_text = ""
4877-
if raw_bytes:
4878-
try:
4879-
raw_text = raw_bytes.decode("utf-8-sig", errors="replace")
4880-
except Exception:
4881-
raw_text = str(raw_bytes)
4882-
4883-
if raw_text:
4884-
parsed = None
4854+
raw = request.get_data(cache=True, as_text=True) or ""
4855+
if raw:
48854856
try:
4886-
parsed = json.loads(raw_text)
4857+
parsed = json.loads(raw)
4858+
if isinstance(parsed, dict):
4859+
payload.update(parsed)
48874860
except Exception:
4888-
parsed = None
4889-
if isinstance(parsed, str) and parsed.strip():
4890-
try:
4891-
parsed = json.loads(parsed)
4892-
except Exception:
4893-
parsed = None
4894-
if isinstance(parsed, dict):
4895-
payload.update(parsed)
4896-
else:
4897-
try:
4898-
form_like = urllib.parse.parse_qs(raw_text, keep_blank_values=True)
4899-
for key, values in form_like.items():
4900-
if not values:
4901-
continue
4902-
field_value = values[-1]
4903-
if key in {"payload", "body", "data"} and isinstance(field_value, str) and field_value.strip():
4904-
try:
4905-
nested = json.loads(field_value)
4906-
if isinstance(nested, dict):
4907-
payload.update(nested)
4908-
continue
4909-
except Exception:
4910-
pass
4911-
if key not in payload:
4912-
payload[str(key)] = field_value
4913-
except Exception:
4914-
pass
4861+
pass
49154862

4916-
json_payload = request.get_json(silent=True, force=False)
4863+
json_payload = request.get_json(silent=True)
49174864
if isinstance(json_payload, dict):
49184865
payload.update(json_payload)
49194866

@@ -4942,37 +4889,25 @@ def parse_nowpayments_ipn_payload() -> Tuple[Dict[str, Any], Dict[str, Any]]:
49424889
except Exception:
49434890
pass
49444891

4945-
debug.update({
4946-
"content_type": str(request.content_type or ""),
4947-
"mimetype": str(request.mimetype or ""),
4948-
"content_length": int(request.content_length or 0),
4949-
"raw_len": len(raw_bytes),
4950-
"raw_preview": raw_text[:200],
4951-
"payload_keys": sorted([str(k) for k in payload.keys()]),
4952-
})
4953-
4954-
return payload, debug
4892+
return payload
49554893

49564894

49574895
@app.post("/api/payments/nowpayments/ipn")
49584896
def nowpayments_ipn_receive():
4959-
payload, payload_debug = parse_nowpayments_ipn_payload()
4897+
payload = parse_nowpayments_ipn_payload()
49604898
bypass_enabled = str(os.getenv("NOWPAYMENTS_IPN_TEST_BYPASS", "0")).strip().lower() in {"1", "true", "yes", "on"}
49614899
bypass_requested = str(request.args.get("test_bypass") or "").strip().lower() in {"1", "true", "yes", "on"}
49624900
has_identifier = any(normalize_text(payload.get(key), 120) for key in ("order_id", "invoice_id", "invoiceId", "payment_id", "id", "purchase_id"))
49634901
payment_status_value = normalize_text(payload.get("payment_status") or payload.get("status"), 80)
49644902
if not has_identifier or not payment_status_value:
4965-
details = {
4966-
"has_identifier": bool(has_identifier),
4967-
"has_payment_status": bool(payment_status_value),
4968-
}
4969-
if bypass_enabled and bypass_requested:
4970-
details["debug_payload"] = payload_debug
49714903
raise ApiError(
49724904
"NOWPayments IPN payload is missing required fields.",
49734905
400,
49744906
code="NOWPAYMENTS_IPN_PAYLOAD_INVALID",
4975-
details=details,
4907+
details={
4908+
"has_identifier": bool(has_identifier),
4909+
"has_payment_status": bool(payment_status_value),
4910+
},
49764911
)
49774912
if not (bypass_enabled and bypass_requested):
49784913
signature = str(request.headers.get("x-nowpayments-sig") or request.headers.get("X-NOWPAYMENTS-SIG") or "").strip()
@@ -5016,8 +4951,6 @@ def nowpayments_ipn_receive():
50164951
"invoice_id": normalize_text(payload.get("invoice_id") or payload.get("invoiceId"), 120),
50174952
"payment_status": normalize_text(payload.get("payment_status") or payload.get("status"), 80),
50184953
"payload_keys": sorted([str(k) for k in payload.keys()]),
5019-
"raw_len": payload_debug.get("raw_len", 0),
5020-
"content_type": payload_debug.get("content_type", ""),
50214954
"app_version": APP_VERSION,
50224955
}
50234956
return jsonify(response_payload)

0 commit comments

Comments
 (0)