From a584154c2f7ea3707e4fecb38da8ba5af3b8c892 Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Thu, 23 Dec 2021 18:46:39 +0000 Subject: [PATCH] Implement redis and store transaction data --- handler/app.py | 18 ++++++------ handler/db.py | 7 +++++ handler/settings.sample.py | 1 + handler/transactions.py | 59 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 handler/db.py create mode 100644 handler/transactions.py diff --git a/handler/app.py b/handler/app.py index 8056aa1..4318f1c 100755 --- a/handler/app.py +++ b/handler/app.py @@ -12,6 +12,7 @@ from json.decoder import JSONDecodeError # Project imports from settings import settings from revolut import Revolut +from transactions import Transactions class WebApp(object): @@ -23,13 +24,9 @@ class WebApp(object): def __init__(self): self.revolut = Revolut() + self.tx = Transactions() self.log = Logger("webapp") - @app.route("/refresh", methods=["GET"]) - def refresh(self, request): - rtrn = self.revolut.get_new_token() - return dumps({"success": rtrn}) - @app.route("/callback", methods=["POST"]) def callback(self, request): content = request.content.read() @@ -39,20 +36,21 @@ class WebApp(object): self.log.error("Failed to parse JSON callback: {content}", content=content) return dumps({"success": False}) self.log.info("Callback received: {parsed}", parsed=parsed) + self.tx.transaction(parsed) return dumps({"success": True}) -def start(webapp): +def start(handler): """ Schedule to refresh the API token once the reactor starts, and create LoopingCapp to refresh it periodically. """ - deferLater(reactor, 1, webapp.revolut.get_new_token) - deferLater(reactor, 4, webapp.revolut.setup_webhook) - lc = LoopingCall(webapp.revolut.get_new_token) + deferLater(reactor, 1, handler.get_new_token) + deferLater(reactor, 4, handler.setup_webhook) + lc = LoopingCall(handler.get_new_token) lc.start(settings.token_refresh_sec) if __name__ == "__main__": webapp = WebApp() - start(webapp) + start(webapp.revolut) webapp.app.run("127.0.0.1", 8080) diff --git a/handler/db.py b/handler/db.py new file mode 100644 index 0000000..0d433eb --- /dev/null +++ b/handler/db.py @@ -0,0 +1,7 @@ +# Other library imports +from redis import StrictRedis + +# Project imports +from settings import settings + +r = StrictRedis(unix_socket_path=settings.redis_socket, db=0) diff --git a/handler/settings.sample.py b/handler/settings.sample.py index 9d81bc2..c5512ae 100644 --- a/handler/settings.sample.py +++ b/handler/settings.sample.py @@ -4,6 +4,7 @@ pre_settings = { "token_refresh_sec": 100, "api_base": "https://sandbox-b2b.revolut.com/api/1.0", "webhook_url": "https://callback-sandbox.pathogen.is/callback", + "redis_socket": "/var/run/redis/redis.sock", "refresh_token": "", "access_token": "", "client_id": "", diff --git a/handler/transactions.py b/handler/transactions.py new file mode 100644 index 0000000..938b8f3 --- /dev/null +++ b/handler/transactions.py @@ -0,0 +1,59 @@ +# Twisted/Klein imports +from twisted.logger import Logger + +# Other library imports +from json import dumps + +# Project imports +from db import r + + +class Transactions(object): + """ + Handler class for incoming Revolut transactions. + """ + + def __init__(self): + self.log = Logger("transactions") + + def transaction(self, data): + """ + Store details of transaction. + """ + event = data["event"] + ts = data["timestamp"] + + inside = data["data"] + txid = inside["id"] + txtype = inside["type"] + state = inside["state"] + reference = inside["reference"] + + leg = inside["legs"][0] + + account_type = leg["counterparty"]["account_type"] + account_id = leg["counterparty"]["account_id"] + + amount = leg["amount"] + currency = leg["currency"] + description = leg["description"] + + to_store = { + "event": event, + "ts": ts, + "txid": txid, + "txtype": txtype, + "state": state, + "reference": reference, + "account_type": account_type, + "account_id": account_id, + "amount": amount, + "currency": currency, + "description": description, + } + + self.log.info("Transaction processed: {formatted}", formatted=dumps(to_store, indent=2)) + r.hmset(f"tx.{txid}", to_store) + + def find_tx(self, amount, reference): + pass