from flask import Flask, request, jsonify import base64, hashlib, hmac, rsa app = Flask(__name__) # โš™๏ธ Replace this with your real PayerMax private key (PEM string) PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCDS2Bp66DKBHgW CYs9ujP8N0Y60HDRcKmhApoCCI3qK4UE8KuaI/bobAbFr4f7bIU3WUnjtiuP1OUh udr5ywdOZ76e6fxCAEJ/TJWtywDvclzqrVjRfe8F3mzF7/1yK0H/WY9IWHMO1sRV WhbNBNYFQ7sLWysJaslD6peZF/vM+N5270nL8e+0p8S18+INFK9Gk5EW8BYLXD8 q28T5L74oL48dgkkLpy1EFDqhmEAJhZQPDpI5VFD7NSs5D0eU+AIYk9qsBX+A7qy 4O/U6SpL/JnaE6uLiQBc3zj4ZWtgw52eAx4fQ7cJgbzwsSbCHScvW0cgpiCZ1+B1 RdeBX9S3lAgMBAAECggEAClZc+Pn8ZuuDKPkHZYzLmwgfF3Jh75uXP34c8hwKUG2 sw37PhAtg3VvkDJyNcFZTBtCY6LznISP6BnXDr/c0VBAHCiwSGIA8vBkjj9Nz92Z hunh7jcMElsm0dsE2i06sm5ZJmcCdDoYKX04AjZPb5f43M+WxtcQapKZL2VnyEWl Jj3iui/ixoLiCXTBCvRAu2WWpKC3YELxFZ7yx24PKOlBcmUOHea/b88eBcSkcaOQ XiU+i/jfJF/qOA2e/0h5mm9tLnXA2leIzscLylRjFsPownEr1T2+J3e+q+ygC5m4 JiEZcASr46hDDC9ReXsKXXxqAQezDyvpFvOkkXL7PAQKBgQDZlDi+pSD7HzBKcrk Lil7jkBS8s9aOoO6QjvArnqN/SH1ThokgBaJF7kZC9vFOT09ZXSeCiBewbcavSXr 8ydDjV8SsgSk8wkmjDsQlOpXlzeE3H4fDS7lf/YLR+T5tvQZbgSxlG+0tQx+DcJz vPMngc+51CVStzYITdXked3z+3QKBgQCaep09hoGx1aiKQLfdZAEDM0uAv6B2a2d shmIxWw+7MoUKSyjAYVbIMk8Y+RyMBZkJNhxt3SegKtHO/S9R2Fa2QbUC3nc/qfe DtdbaUOdXYBxJymtg9SUDjsIMusDUGu1aRXczzBK8jfKX9aaxQoOVkmxJYXC0/9/ 5oIINZHrGqQKBgQDHfD1WleGaPGszJuH/8bq0G6rXpG8IUAbKpTMQWx9+GMFHLmd U47V3NlJXHT/6035l6aHK7OoDSXLLzawkTwjlF9hrbPSZD20iQeyWUZOToeJmftM jvK7WkoE58LJLPO6yQMmqXiNjx1ICWeKY+fwBfWlZBtgLjgs/ugn1ZApHRQKBgHH yvAXkL8rTxYyljHq8B5sqvSjtMRnow9NjlQ6/Eu2MqGIdaqPtqSvnID1Vk98dSfN nfLT1iwM0UqsSS1Nd9yhdc334R5Iod7Ep8p/7SYpEFNnBfE96xKDJLw5gu1g5vJb 34qPMho2bTzUUOK9MVu9/oGzIeXCpxbbG1Oe4FHBxAoGATTFW0o6ZILHqrquBbzm ze9xf2dwPk4ixR4vfra64TdV1iISkJU0tBCO3VFxvlnaVXi+QsXZayKfdYj0MXLE 0GucYWVKgwA84NsgJA8JeOifriooIAX4ZqHFIG9OyO4VBz2iOCWUzanYGeBMxA4D xO3lVx0gqIZWOjCqjqBKPG6U= -----END RSA PRIVATE KEY-----""" # โœ… 1. PayerMax callback endpoint @app.route("/payermax", methods=["POST", "GET"]) def payermax_notify(): try: print("โœ… PayerMax callback received") data = request.get_json(force=True, silent=True) print("๐Ÿงพ Data:", data) return "success", 200 except Exception as e: print("๐Ÿ”ฅ Error in PayerMax callback:", str(e)) return "success", 200 # โœ… 2. FlutterFlow test endpoint @app.route("/test", methods=["POST"]) def test_endpoint(): try: data = request.get_json(force=True, silent=True) print("๐Ÿงช FlutterFlow test data:", data) return jsonify({ "status": "ok", "message": "Received test data successfully!", "echo": data }), 200 except Exception as e: print("๐Ÿ”ฅ Error in test endpoint:", str(e)) return jsonify({"status": "error", "message": str(e)}), 500 # โœ… 3. Signature generator endpoint @app.route("/sign", methods=["POST"]) def sign_payload(): """ Generate RSA-SHA256 signature for a given string payload. Body: { "payload": "string-to-sign" } Returns: { "sign": "base64_signature" } """ try: import base64 from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 data = request.get_json(force=True) payload = data.get("payload", "") if not payload: return jsonify({"error": "Missing 'payload' field"}), 400 # Load your PEM private key private_key = RSA.import_key(PRIVATE_KEY) # Compute SHA256 hash of the exact payload string h = SHA256.new(payload.encode('utf-8')) # Sign it signature = pkcs1_15.new(private_key).sign(h) # Return base64-encoded signature as 'sign' (what your custom action expects) signature_b64 = base64.b64encode(signature).decode('utf-8') return jsonify({"sign": signature_b64}), 200 except Exception as e: print("๐Ÿ”ฅ Error generating signature:", str(e)) return jsonify({"error": str(e)}), 500 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)