Move code into classes

This commit is contained in:
Mark Veidemanis 2021-12-23 16:59:35 +00:00
parent ffd035dfbf
commit 57e5616531
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
3 changed files with 107 additions and 78 deletions

102
handler/app.py Normal file → Executable file
View File

@ -1,96 +1,58 @@
#!/usr/sbin/env python3
# Twisted/Klein imports
from twisted.logger import Logger from twisted.logger import Logger
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.task import LoopingCall, deferLater from twisted.internet.task import LoopingCall, deferLater
from klein import Klein from klein import Klein
# Other library imports
from json import dumps, loads from json import dumps, loads
from json.decoder import JSONDecodeError from json.decoder import JSONDecodeError
import pprint # Project imports
import requests from settings import settings
from revolut import Revolut
from settings import refresh_token, client_id, jwt
token_refresh_sec = 30 class WebApp(object):
"""
Our Klein webapp.
"""
api_base = "https://sandbox-b2b.revolut.com/api/1.0"
webhook_url = "https://callback-sandbox.pathogen.is/callback"
# SYSTEM VARIABLES BELOW #
app = Klein() app = Klein()
access_token = "" def __init__(self):
self.revolut = Revolut()
log = Logger() self.log = Logger("webapp")
pp = pprint.PrettyPrinter(indent=2)
def get_new_token():
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {
"grant_type": "refresh_token",
"refresh_token": refresh_token,
"client_id": client_id,
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": jwt,
}
r = requests.post(f"{api_base}/auth/token", data=data, headers=headers)
parsed = r.json()
if r.status_code == 200:
if "access_token" in parsed.keys():
access_token = parsed["access_token"]
if len(access_token) == len(refresh_token):
log.info("Refreshed access token")
return True
else:
log.error(f"Token refresh didn't contain access token: {parsed}", parsed=parsed)
return False
else:
log.error(f"Cannot refresh token: {parsed}", parsed=parsed)
return False
def transaction(sender, source_currency, dest_currency, source_amount, dest_amount):
pass
def setup_webhook():
log.info("Setting up webhook")
headers = {"Authorization": f"Bearer {access_token}"}
data = {
"url": webhook_url
}
r = requests.post (f"{api_base}/webhook", data=data, headers=headers)
parsed = r.json()
if r.status_code == 200:
log.info("Set up webhook")
return dumps({"success": True})
else:
log.info("Failed setting up webhook")
@app.route("/refresh", methods=["GET"]) @app.route("/refresh", methods=["GET"])
def refresh(request): def refresh(self, request):
rtrn = get_new_token() rtrn = self.revolut.get_new_token()
return dumps({"success": rtrn}) return dumps({"success": rtrn})
@app.route("/callback", methods=["POST"]) @app.route("/callback", methods=["POST"])
def callback(request): def callback(self, request):
content = request.content.read() content = request.content.read()
try: try:
parsed = loads(content) parsed = loads(content)
except JSONDecodeError: except JSONDecodeError:
log.error("Failed to parse JSON callback: {content}", content=content) self.log.error("Failed to parse JSON callback: {content}", content=content)
return dumps({"success": False}) return dumps({"success": False})
log.info("Callback received: {parsed}", parsed=parsed) self.log.info("Callback received: {parsed}", parsed=parsed)
return dumps({"success": True}) return dumps({"success": True})
# Set up loop to refresh token, but get one first def start(webapp):
deferLater(reactor, 1, get_new_token) """
deferLater(reactor, 2, setup_webhook) Schedule to refresh the API token once the reactor starts, and create LoopingCapp to refresh it periodically.
lc = LoopingCall(get_new_token) """
lc.start(token_refresh_sec) deferLater(reactor, 1, webapp.revolut.get_new_token)
resource = app.resource deferLater(reactor, 4, webapp.revolut.setup_webhook)
app.run("127.0.0.1", 8080) lc = LoopingCall(webapp.revolut.get_new_token)
lc.start(settings.token_refresh_sec)
if __name__ == "__main__":
webapp = WebApp()
start(webapp)
webapp.app.run("127.0.0.1", 8080)

54
handler/revolut.py Normal file
View File

@ -0,0 +1,54 @@
# Twisted/Klein imports
from twisted.logger import Logger
# Other library imports
from json import dumps
import requests
# Project imports
from settings import settings
class Revolut(object):
"""
Class to handle Revolut API calls.
"""
def __init__(self):
self.log = Logger("revolut")
def get_new_token(self):
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {
"grant_type": "refresh_token",
"refresh_token": settings.refresh_token,
"client_id": settings.client_id,
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": settings.jwt,
}
r = requests.post(f"{settings.api_base}/auth/token", data=data, headers=headers)
parsed = r.json()
if r.status_code == 200:
if "access_token" in parsed.keys():
settings.access_token = parsed["access_token"]
if len(settings.access_token) == len(settings.refresh_token):
self.log.info("Refreshed access token: {access_token}", access_token=settings.access_token)
return True
else:
self.log.error(f"Token refresh didn't contain access token: {parsed}", parsed=parsed)
return False
else:
self.log.error(f"Cannot refresh token: {parsed}", parsed=parsed)
return False
def setup_webhook(self):
self.log.info("Setting up webhook: {url}", url=settings.webhook_url)
headers = {"Authorization": f"Bearer {settings.access_token}"}
data = {"url": settings.webhook_url}
r = requests.post(f"{settings.api_base}/webhook", data=dumps(data), headers=headers)
if r.status_code == 204:
self.log.info("Set up webhook: {url}", url=settings.webhook_url)
return dumps({"success": True})
else:
parsed = r.json()
self.log.info("Failed setting up webhook: {parsed}", parsed=parsed)

View File

@ -0,0 +1,13 @@
from types import SimpleNamespace
pre_settings = {
"token_refresh_sec": 100,
"api_base": "https://sandbox-b2b.revolut.com/api/1.0",
"webhook_url": "https://callback-sandbox.pathogen.is/callback",
"refresh_token": "",
"access_token": "",
"client_id": "",
"jwt": "",
}
settings = SimpleNamespace(**pre_settings)