switch to polling for btcpay payment sessions because btcpay web hooks
are super duper slow
This commit is contained in:
		@ -15,6 +15,7 @@ from nanoid import generate
 | 
				
			|||||||
from capsulflask.metrics import durations as metric_durations
 | 
					from capsulflask.metrics import durations as metric_durations
 | 
				
			||||||
from capsulflask.auth import account_required
 | 
					from capsulflask.auth import account_required
 | 
				
			||||||
from capsulflask.db import get_model, my_exec_info_message
 | 
					from capsulflask.db import get_model, my_exec_info_message
 | 
				
			||||||
 | 
					from capsulflask.payment import poll_btcpay_session
 | 
				
			||||||
from capsulflask import cli
 | 
					from capsulflask import cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bp = Blueprint("console", __name__, url_prefix="/console")
 | 
					bp = Blueprint("console", __name__, url_prefix="/console")
 | 
				
			||||||
@ -277,6 +278,12 @@ def get_account_balance(vms, payments, as_of):
 | 
				
			|||||||
@bp.route("/account-balance")
 | 
					@bp.route("/account-balance")
 | 
				
			||||||
@account_required
 | 
					@account_required
 | 
				
			||||||
def account_balance():
 | 
					def account_balance():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  payment_sessions = get_model().list_payment_sessions_for_account(session['account'])
 | 
				
			||||||
 | 
					  for payment_session in payment_sessions:
 | 
				
			||||||
 | 
					    if payment_session['type'] == 'btcpay':
 | 
				
			||||||
 | 
					      poll_btcpay_session(payment_session['id'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  payments = get_payments()
 | 
					  payments = get_payments()
 | 
				
			||||||
  vms = get_vms()
 | 
					  vms = get_vms()
 | 
				
			||||||
  balance_1w = get_account_balance(vms, payments, datetime.utcnow() + timedelta(days=7)) 
 | 
					  balance_1w = get_account_balance(vms, payments, datetime.utcnow() + timedelta(days=7)) 
 | 
				
			||||||
 | 
				
			|||||||
@ -164,6 +164,17 @@ class DBModel:
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    self.connection.commit()
 | 
					    self.connection.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def list_payment_sessions_for_account(self, email):
 | 
				
			||||||
 | 
					    self.cursor.execute(""" 
 | 
				
			||||||
 | 
					      SELECT id, type, dollars, created
 | 
				
			||||||
 | 
					      FROM payment_sessions WHERE email = %s""", 
 | 
				
			||||||
 | 
					      (email, )
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    return list(map(
 | 
				
			||||||
 | 
					      lambda x: dict(id=x[0], type=x[1], dollars=x[2], created=x[3]), 
 | 
				
			||||||
 | 
					      self.cursor.fetchall()
 | 
				
			||||||
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def consume_payment_session(self, payment_type, id, dollars):
 | 
					  def consume_payment_session(self, payment_type, id, dollars):
 | 
				
			||||||
    self.cursor.execute("SELECT email, dollars FROM payment_sessions WHERE id = %s AND type = %s", (id, payment_type))
 | 
					    self.cursor.execute("SELECT email, dollars FROM payment_sessions WHERE id = %s AND type = %s", (id, payment_type))
 | 
				
			||||||
    row = self.cursor.fetchone()
 | 
					    row = self.cursor.fetchone()
 | 
				
			||||||
 | 
				
			|||||||
@ -77,23 +77,12 @@ def btcpay_payment():
 | 
				
			|||||||
  return render_template("btcpay.html", invoice_id=invoice_id)
 | 
					  return render_template("btcpay.html", invoice_id=invoice_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route("/btcpay/webhook", methods=("POST",))
 | 
					def poll_btcpay_session(invoice_id):
 | 
				
			||||||
def btcpay_webhook():
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  current_app.logger.info(f"got btcpay webhook")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # IMPORTANT! there is no signature or credential for the data sent into this webhook :facepalm:
 | 
					 | 
				
			||||||
  # its just a notification, thats all.
 | 
					 | 
				
			||||||
  request_data = json.loads(request.data)
 | 
					 | 
				
			||||||
  invoice_id = request_data['id']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  current_app.logger.info(f"got btcpay webhook with invoice_id={invoice_id}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # so you better make sure to get the invoice directly from the horses mouth! 
 | 
					  # so you better make sure to get the invoice directly from the horses mouth! 
 | 
				
			||||||
  invoice = current_app.config['BTCPAY_CLIENT'].get_invoice(invoice_id)
 | 
					  invoice = current_app.config['BTCPAY_CLIENT'].get_invoice(invoice_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if invoice['currency'] != "USD":
 | 
					  if invoice['currency'] != "USD":
 | 
				
			||||||
    abort(400, "invalid currency")
 | 
					    return [400, "invalid currency"]
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  dollars = invoice['price']
 | 
					  dollars = invoice['price']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,7 +99,21 @@ def btcpay_webhook():
 | 
				
			|||||||
  elif invoice['status'] == "expired" or invoice['status'] == "invalid":
 | 
					  elif invoice['status'] == "expired" or invoice['status'] == "invalid":
 | 
				
			||||||
    get_model().btcpay_invoice_resolved(invoice_id, False)
 | 
					    get_model().btcpay_invoice_resolved(invoice_id, False)
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  return {"msg": "ok"}, 200
 | 
					  return [200, "ok"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@bp.route("/btcpay/webhook", methods=("POST",))
 | 
				
			||||||
 | 
					def btcpay_webhook():
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  current_app.logger.info(f"got btcpay webhook")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # IMPORTANT! there is no signature or credential for the data sent into this webhook :facepalm:
 | 
				
			||||||
 | 
					  # its just a notification, thats all.
 | 
				
			||||||
 | 
					  request_data = json.loads(request.data)
 | 
				
			||||||
 | 
					  invoice_id = request_data['id']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  result = poll_btcpay_session(invoice_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  abort(result[0], result[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user