@@ -4849,29 +4849,46 @@ def nowpayments_order_status(order_id: str):
48494849
48504850
48514851def parse_nowpayments_ipn_payload () -> Dict [str , Any ]:
4852- payload = request .get_json (silent = True )
4853- if isinstance (payload , dict ) and payload :
4854- return payload
4852+ payload : Dict [str , Any ] = {}
4853+
48554854 raw = request .get_data (cache = True , as_text = True ) or ""
48564855 if raw :
48574856 try :
48584857 parsed = json .loads (raw )
4859- if isinstance (parsed , dict ) and parsed :
4860- return parsed
4858+ if isinstance (parsed , dict ):
4859+ payload . update ( parsed )
48614860 except Exception :
48624861 pass
4863- payload = {}
4862+
4863+ json_payload = request .get_json (silent = True )
4864+ if isinstance (json_payload , dict ):
4865+ payload .update (json_payload )
4866+
48644867 try :
48654868 for key in request .form .keys ():
4866- payload [str (key )] = request .form .get (key )
4869+ field_key = str (key )
4870+ field_value = request .form .get (key )
4871+ if field_key in {"payload" , "body" , "data" } and isinstance (field_value , str ) and field_value .strip ():
4872+ try :
4873+ nested = json .loads (field_value )
4874+ if isinstance (nested , dict ):
4875+ payload .update (nested )
4876+ continue
4877+ except Exception :
4878+ pass
4879+ if field_key not in payload :
4880+ payload [field_key ] = field_value
48674881 except Exception :
48684882 pass
4869- if not payload :
4870- try :
4871- for key in request .args .keys ():
4872- payload [str (key )] = request .args .get (key )
4873- except Exception :
4874- pass
4883+
4884+ try :
4885+ for key in request .args .keys ():
4886+ arg_key = str (key )
4887+ if arg_key not in payload :
4888+ payload [arg_key ] = request .args .get (key )
4889+ except Exception :
4890+ pass
4891+
48754892 return payload
48764893
48774894
@@ -4880,6 +4897,18 @@ def nowpayments_ipn_receive():
48804897 payload = parse_nowpayments_ipn_payload ()
48814898 bypass_enabled = str (os .getenv ("NOWPAYMENTS_IPN_TEST_BYPASS" , "0" )).strip ().lower () in {"1" , "true" , "yes" , "on" }
48824899 bypass_requested = str (request .args .get ("test_bypass" ) or "" ).strip ().lower () in {"1" , "true" , "yes" , "on" }
4900+ has_identifier = any (normalize_text (payload .get (key ), 120 ) for key in ("order_id" , "invoice_id" , "invoiceId" , "payment_id" , "id" , "purchase_id" ))
4901+ payment_status_value = normalize_text (payload .get ("payment_status" ) or payload .get ("status" ), 80 )
4902+ if not has_identifier or not payment_status_value :
4903+ raise ApiError (
4904+ "NOWPayments IPN payload is missing required fields." ,
4905+ 400 ,
4906+ code = "NOWPAYMENTS_IPN_PAYLOAD_INVALID" ,
4907+ details = {
4908+ "has_identifier" : bool (has_identifier ),
4909+ "has_payment_status" : bool (payment_status_value ),
4910+ },
4911+ )
48834912 if not (bypass_enabled and bypass_requested ):
48844913 signature = str (request .headers .get ("x-nowpayments-sig" ) or request .headers .get ("X-NOWPAYMENTS-SIG" ) or "" ).strip ()
48854914 if not signature :
0 commit comments