-
Notifications
You must be signed in to change notification settings - Fork 3
/
banking.py
114 lines (94 loc) · 2.83 KB
/
banking.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from abc import ABC, abstractmethod
from utils import loginrequired
import requests
import json
class Banking(ABC):
class AuthenticationError(Exception):
"""
Raised when an error occurs during authentication.
"""
pass
class AuthenticationFailure(Exception):
"""
Raised when an authentication error occurs during a request
for which the user should already be authenticated.
"""
pass
class RequestException(Exception):
"""
Raised when an error occurs during a request to the
backend.
"""
pass
@property
@classmethod
@abstractmethod
def ENROLL_URL(cls):
return NotImplementedError
@property
@classmethod
@abstractmethod
def PROFILE_URL(cls):
return NotImplementedError
@property
@classmethod
@abstractmethod
def BALANCE_URL(cls):
return NotImplementedError
@property
@classmethod
@abstractmethod
def CARD_URL(cls):
return NotImplementedError
@property
@classmethod
@abstractmethod
def MOVEMENTS_URL(cls):
return NotImplementedError
def __init__(self):
self.token = None
self._session = requests.Session()
super().__init__()
def _api_request(self, **kwargs):
"""
Wrapper for requests to the backend. Checks if the request was
successful, then returns the response data.
"""
r = self._session.request(**kwargs)
try:
data = r.json()
except json.decoder.JSONDecodeError:
raise self.RequestException("Failed to parse response: " + r.text)
if "responseCode" not in data:
raise self.RequestException("Missing response code from response: " + r.text)
if data["responseCode"] in ("401", "007"):
raise self.AuthenticationFailure
elif data["responseCode"] != "200":
raise self.RequestException("Server returned response {responseCode}: {responseDescr}".format(**data))
return data["data"]
@abstractmethod
def login(self, *args, **kwargs):
pass
@abstractmethod
def otp2fa(self, *args, **kwargs):
"""
OTP code verification for two-factor authentication.
"""
pass
@abstractmethod
def renew(self, *args, **kwargs):
pass
@loginrequired
def get_profile_info(self):
return self._api_request(method="GET", url=self.PROFILE_URL)
@loginrequired
def get_balance(self):
return self._api_request(method="GET", url=self.BALANCE_URL)
@loginrequired
def get_card_info(self):
return self._api_request(method="GET", url=self.CARD_URL)
@abstractmethod
def get_movements(self, *args, **kwargs):
pass