something
This commit is contained in:
@@ -50,33 +50,53 @@ def healthz():
|
|||||||
# app.logger.exception("IPN verification failed: %s", e)
|
# app.logger.exception("IPN verification failed: %s", e)
|
||||||
# return jsonify({"errorCode": 0}), 200
|
# return jsonify({"errorCode": 0}), 200
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/payments/ipn")
|
@app.post("/api/payments/ipn")
|
||||||
def ipn():
|
def ipn():
|
||||||
# 1. Get the signature from the 'Verification-Token' header
|
token = request.headers.get('Verification-Token') or request.headers.get('X-Netopia-Signature')
|
||||||
token = request.headers.get('Verification-Token')
|
|
||||||
|
|
||||||
if token:
|
|
||||||
# This ignores the signature completely just so we can see what's inside
|
|
||||||
raw_data = jwt.decode(token, options={"verify_signature": False})
|
|
||||||
app.logger.info(f"UNVERIFIED JWT CONTENT: {raw_data}")
|
|
||||||
|
|
||||||
# 2. If it exists, inject it into the location the SDK expects
|
if not token:
|
||||||
if token:
|
app.logger.error("No token found")
|
||||||
request.headers.environ['HTTP_X_NETOPIA_SIGNATURE'] = token
|
return jsonify({"errorCode": 1, "error": "No token"}), 400
|
||||||
app.logger.info("Mapped Verification-Token to X-Netopia-Signature")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Now the SDK will find the signature in X-Netopia-Signature
|
# Get the clean key from your env/settings
|
||||||
data = verify_ipn(request)
|
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
|
||||||
|
decoded_data = jwt.decode(
|
||||||
|
token,
|
||||||
|
public_key,
|
||||||
|
algorithms=["RS256", "RS512"],
|
||||||
|
audience=settings.pos_signature,
|
||||||
|
leeway=30
|
||||||
|
)
|
||||||
|
|
||||||
# NOTE: Your log shows "status: 12" and "Invalid card number"
|
app.logger.info(f"VERIFIED DATA: {decoded_data}")
|
||||||
# The verification should now pass, even if the payment failed.
|
|
||||||
app.logger.info("IPN Verification Result: %s", 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}")
|
||||||
|
|
||||||
return jsonify({"errorCode": 0}), 200
|
return jsonify({"errorCode": 0}), 200
|
||||||
except Exception as e:
|
|
||||||
app.logger.exception("IPN verification failed: %s", e)
|
except jwt.ExpiredSignatureError:
|
||||||
return jsonify({"ok": False, "error": str(e)}), 400
|
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
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/payments/status")
|
@app.get("/api/payments/status")
|
||||||
|
|||||||
Reference in New Issue
Block a user