something
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user