commit 81d2a308c23cb4b81be32a071dc320a0ee765741
parent f217a4fa41bf0d686dff664c429dfdf3e93c8a76
Author: NicholasFarrow <nicholas.w.farrow@gmail.com>
Date: Tue, 22 Dec 2020 20:50:57 +1100
Refactored code, improved invoice loading, status and response verbosity, and decreased code repetitiveness
Diffstat:
5 files changed, 81 insertions(+), 48 deletions(-)
diff --git a/demo.py b/demo.py
@@ -8,7 +8,6 @@ import config
import invoice
from pay import bitcoind
-
async_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
@@ -16,69 +15,98 @@ socket_ = SocketIO(app, async_mode=async_mode)
# thread = None
# thread_lock = Lock()
-
@app.route('/')
def index():
return render_template('index.html', async_mode=socket_.async_mode)
@socket_.on('initialise', namespace='/pay')
def test_message(message):
- emit('my_response', {'time_left': config.payment_timeout, 'response': message['data']})
+ emit('payresponse', {'time_left': -1, 'response': message['data']})
@socket_.on('payment', namespace='/pay')
-def make_payment(message):
- print("Requesting payment for {}".format(message['amount']))
+def make_payment(payload):
+ print("Requesting payment for {}".format(payload['amount']))
# Check the amount is a float
- amount = message['amount']
+ amount = payload['amount']
try:
amount = float(amount)
except:
- emit('my_response', {'status' : '', 'address' : '', 'amount' : '', 'time_left': 0, 'response': "Invalid payment mount.".format(unconf_paid)})
+ # emit('payresponse', {'status' : '', 'address' : '', 'amount' : '', 'time_left': 0, 'response': "Invalid payment mount.".format(unconf_paid)})
amount = None
return
# Validate amount is a positive float
if not (isinstance(amount, float) and amount >= 0):
- emit('my_response', {'status' : '', 'address' : '', 'amount' : '', 'time_left': 0, 'response': "Invalid payment mount.".format(unconf_paid)})
+ # emit('payresponse', {'status' : '', 'address' : '', 'amount' : '', 'time_left': 0, 'response': "Invalid payment mount.".format(unconf_paid)})
amount = None
return
+ # Need to check this is safe!
+ label = payload['label']
+
# Initialise this payment
- payment = create_invoice(amount, "USD", "wee")
- emit('my_response', {'status' : 'Awaiting payment.', 'address' : payment.address, 'amount' : payment.value, 'time_left': config.payment_timeout, 'response' : 'Awaiting payment.'})
+ payment = create_invoice(amount, "USD", label)
+
+ make_payment(payment)
+
+ if payment.paid:
+ payment.status = 'Payment finalised.'
+ payment.response = 'Payment finalised.'
+ update_status(payment)
+
+ ### DO SOMETHING
+ # Depends on config
+ # Get redirected?
+ # Nothing?
+ # Run custom script?
+
+def update_status(payment, console_status=True):
+ if console_status:
+ print(payment.status)
+
+ emit('payresponse', {'status' : payment.status, 'address' : payment.address, 'amount' : payment.value, 'time_left': payment.time_left, 'response': payment.response})
+ return
+
+def make_payment(payment):
+ payment.status = 'Awaiting payment.'
+ payment.response = 'Awaiting payment.'
+ update_status(payment)
# Track start_time for payment timeouts
- start_time = time.time()
- while (time_left := config.payment_timeout - (time.time() - start_time)) > 0:
- conf_paid, unconf_paid = payment.check_payment()
- print(conf_paid, unconf_paid)
+ payment.start_time = time.time()
+ while (time_left := config.payment_timeout - (time.time() - payment.start_time)) > 0:
+ payment.time_left = time_left
+ payment.confirmed_paid, payment.unconfirmed_paid = payment.check_payment()
- if conf_paid > payment.value:
- print("Invoice {} paid! {} BTC.".format(payment.label, conf_paid))
+ if payment.confirmed_paid > payment.value:
payment.paid = True
+ payment.status = "Payment successful! {} BTC".format(payment.confirmed_paid)
+ payment.response = "Payment successful! {} BTC".format(payment.confirmed_paid)
+ update_status(payment)
break
- elif unconf_paid > 0:
- emit('my_response', {'status' : 'Discovered {} BTC payment... Waiting for {} confirmations.'.format(config.required_confirmations), 'address' : payment.address, 'amount' : payment.value, 'time_left': time_left, 'response': "Discovered {} BTC payment, waiting for {} confirmations.".format(unconf_paid, config.required_confirmations)})
- socket_.sleep(15)
+ elif payment.unconfirmed_paid > 0:
+ payment.status = "Discovered {} BTC payment. Waiting for {} confirmations...".format(payment.unconfirmed_paid, config.required_confirmations)
+ payment.response = "Discovered {} BTC payment. Waiting for {} confirmations...".format(payment.unconfirmed_paid, config.required_confirmations)
+ update_status(payment)
+ socket_.sleep(config.pollrate)
else:
- emit('my_response', {'status' : 'Awaiting payment.', 'address' : payment.address, 'amount' : payment.value, 'time_left': time_left, 'response': 'Awaiting {} BTC payment...'.format(payment.value)})
- socket_.sleep(15)
+ payment.status = "Awaiting {} BTC payment...".format(payment.value)
+ payment.response = "Awaiting {} BTC payment...".format(payment.value)
+ update_status(payment)
+ socket_.sleep(config.pollrate)
else:
- emit('my_response', {'status' : 'EXPIRED', 'address' : payment.address, 'amount' : payment.value, 'time_left': 0, 'response':'INVOICE EXPIRED'})
- print("Invoice {} expired.".format(payment.label))
- payment.paid = False
+ payment.status = "Payment expired."
+ payment.status = "Payment expired."
+ update_status(payment)
- if payment.paid:
- print("PAID")
- emit('my_response', {'status' : 'Paid!', 'address' : payment.address, 'amount' : payment.value, 'time_left': time_left, 'response': 'Payment finalised.'})
+ return
-def create_invoice(amount, currency, label):
- inv = invoice.invoice(amount, currency, label)
- payment = bitcoind.btcd()
- payment.load_invoice(inv)
+def create_invoice(amount, currency, label):
+ payment_invoice = invoice.invoice(amount, currency, label)
+ payment = bitcoind.btcd(payment_invoice)
payment.get_address()
return payment
diff --git a/invoice/__init__.py b/invoice/__init__.py
@@ -1,8 +1,18 @@
+import uuid
+
+import config
from .price_feed import get_btc_value
+
class invoice():
def __init__(self, dollar_value, currency, label):
self.dollar_value = dollar_value
self.currency = currency
self.value = get_btc_value(dollar_value, currency)
self.label = label
+ self.id = str(uuid.uuid4)
+ self.status = 'Payment initialised.'
+ self.response = ''
+ self.time_left = config.payment_timeout
+ self.confirmed_paid = 0
+ self.unconfirmed_paid = 0
diff --git a/pay/bitcoind.py b/pay/bitcoind.py
@@ -2,7 +2,9 @@ import config
import subprocess
class btcd:
- def __init__(self):
+ def __init__(self, invoice):
+ self.__dict__ = invoice.__dict__.copy()
+
from bitcoinrpc.authproxy import AuthServiceProxy
connection_str = "http://{}:{}@{}:{}".format(config.username, config.password, config.host, config.rpcport)
@@ -21,12 +23,6 @@ class btcd:
except Exception as e:
print(e)
- def load_invoice(self, invoice):
- self.value = invoice.value
- self.label = invoice.label
- self.paid = False
- return
-
def check_payment(self):
self.address = "bc1qwxlwghumfmhwdc2deyn7h42syp2t496penax2y"
transactions = self.rpc.listtransactions()
diff --git a/server.py b/server.py
@@ -1,4 +1,5 @@
from flask import Flask, request, url_for, jsonify, render_template
+from flask_socketio import SocketIO
from markupsafe import escape
import time
@@ -8,13 +9,9 @@ import invoice
from pay import bitcoind
app = Flask(__name__)
+socketio = SocketIO(app)
-@app.route('/')
-def index():
- return render_template('payment.html')
-
-
-app.route('/invoice', methods=['GET'])
+@app.route('/invoice', methods=['GET'])
def invoice():
amount = request.values.get('amount')
@@ -92,6 +89,8 @@ def payment(amount, currency, label):
return False
+if __name__ == "__main__":
+ socketio.run(app, debug=True)
#with app.test_client() as c:
# resp = c.post('/pay', data=dict(amount=69))
diff --git a/templates/index.html b/templates/index.html
@@ -10,10 +10,10 @@
var socket = io(namespace);
socket.on('connect', function() {
- socket.emit('initialise', {data: 'initialising payment...'});
+ socket.emit('initialise', {'data': 'initialising payment...'});
});
- socket.on('my_response', function(msg, cb) {
+ socket.on('payresponse', function(msg, cb) {
console.log(msg.response);
$('#status').text(msg.status).html();
$('#address').text(msg.address).html();
@@ -25,7 +25,7 @@
});
$('form#pay').submit(function(event) {
- socket.emit('payment', {amount: $('#pay_data').val()});
+ socket.emit('payment', {'amount': $('#pay_data').val(), 'label' : null});
return false;
});
});
@@ -40,8 +40,8 @@
document.getElementById('timer').innerHTML = Math.round(currentTime - 1);
}, 1000)
</script>
-
</head>
+
<body style="background-color:white;">
<h1 style="background-color:white;">BTCPyServer</h1>