Skip to content

Commit 662bd30

Browse files
committed
fix: update version to 0.2.8 and add timeout and capcha retry parameters in MBBank classes from pull requests #14
1 parent 1d603fe commit 662bd30

File tree

3 files changed

+50
-21
lines changed

3 files changed

+50
-21
lines changed

mbbank/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
from .wasm_helper import wasm_encrypt
44
from .capcha_ocr import CapchaProcessing, CapchaOCR
55

6-
__version__ = '0.2.7'
6+
__version__ = '0.2.8'

mbbank/main.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ class MBBank:
4646
password (str): MBBank Account Password
4747
proxy (str, optional): Proxy url. Example: "http://127.0.0.1:8080". Defaults to None.
4848
ocr_class (CapchaProcessing, optional): instance of CapchaProcessing class. Defaults to CapchaOCR().
49+
retry_times (int, optional): number of retry times for capcha processing. Defaults to 30 ( worst case ).
50+
timeout (Union[float, Tuple[float, float]], optional): request timeout in seconds or (connect timeout, read timeout) or None for no timeout. Defaults to None.
4951
"""
5052

5153
FPR = "c7a1beebb9400375bb187daa33de9659"
5254

53-
def __init__(self, *, username: str, password: str, proxy: typing.Optional[str] = None, ocr_class: typing.Optional[CapchaProcessing] = None):
55+
def __init__(self, *, username: str, password: str, proxy: typing.Optional[str] = None,
56+
ocr_class: typing.Optional[CapchaProcessing] = None,
57+
retry_times: int = 30,
58+
timeout: typing.Union[float, typing.Tuple[float, float], None] = None):
5459
self._userid = username
5560
self._password = password
5661
self._wasm_cache = None
@@ -68,6 +73,8 @@ def __init__(self, *, username: str, password: str, proxy: typing.Optional[str]
6873
self._userinfo = None
6974
self._temp = {}
7075
self.deviceIdCommon = f'abi2jojr-mbib-0000-0000-{self._get_now_time()}'
76+
self.retry_times = retry_times
77+
self.timeout = timeout
7178

7279
def _get_now_time(self):
7380
now = datetime.datetime.now()
@@ -93,10 +100,9 @@ def _req(self, url, *, json=None, headers=None):
93100
headers["X-Request-Id"] = rid
94101
headers["RefNo"] = rid
95102
headers["DeviceId"] = self.deviceIdCommon
96-
with requests.Session() as s:
97-
with s.post(url, headers=headers, json=json_data,
98-
proxies=self.proxy) as r:
99-
data_out = r.json()
103+
with requests.post(url, headers=headers, json=json_data,
104+
proxies=self.proxy) as r:
105+
data_out = r.json()
100106
if data_out["result"] is None:
101107
self.getBalance()
102108
elif data_out["result"]["ok"]:
@@ -112,7 +118,7 @@ def _get_wasm_file(self):
112118
if self._wasm_cache is not None:
113119
return self._wasm_cache
114120
file_data = requests.get("https://online.mbbank.com.vn/assets/wasm/main.wasm",
115-
proxies=self.proxy).content
121+
proxies=self.proxy, timeout=self.timeout).content
116122
self._wasm_cache = file_data
117123
return file_data
118124

@@ -134,8 +140,8 @@ def get_capcha_image(self) -> bytes:
134140
headers["Deviceid"] = self.deviceIdCommon
135141
headers["Refno"] = rid
136142
with requests.post("https://online.mbbank.com.vn/api/retail-internetbankingms/getCaptchaImage",
137-
headers=headers, json=json_data,
138-
proxies=self.proxy) as r:
143+
headers=headers, json=json_data,
144+
proxies=self.proxy, timeout=self.timeout) as r:
139145
data_out = r.json()
140146
return base64.b64decode(data_out["imageString"])
141147

@@ -161,8 +167,8 @@ def login(self, captcha_text: str):
161167
wasm_bytes = self._get_wasm_file()
162168
data_encrypt = wasm_encrypt(wasm_bytes, payload)
163169
with requests.post("https://online.mbbank.com.vn/api/retail_web/internetbanking/v2.0/doLogin",
164-
headers=headers_default, json={"dataEnc": data_encrypt},
165-
proxies=self.proxy) as r:
170+
headers=headers_default, json={"dataEnc": data_encrypt},
171+
proxies=self.proxy, timeout=self.timeout) as r:
166172
data_out = r.json()
167173
if data_out["result"]["ok"]:
168174
self.sessionId = data_out["sessionId"]
@@ -186,7 +192,7 @@ def _authenticate(self):
186192
if e.code == "GW283":
187193
continue # capcha error, try again
188194
raise e
189-
195+
190196
def _verify_biometric_check(self):
191197
self._req("https://online.mbbank.com.vn/api/retail-go-ekycms/v1.0/verify-biometric-nfc-transaction")
192198

mbbank/mbasync.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
from .main import MBBankError, MBBank
1212
from .wasm_helper import wasm_encrypt
1313
from .main import headers_default
14-
from .modals import BalanceResponseModal, BalanceLoyaltyResponseModal, BankListResponseModal, BeneficiaryListResponseModal, CardListResponseModal, AccountByPhoneResponseModal, UserInfoResponseModal, LoanListResponseModal, SavingListResponseModal, InterestRateResponseModal, TransactionHistoryResponseModal, CardTransactionsResponseModal, SavingDetailResponseModal
14+
from .modals import BalanceResponseModal, BalanceLoyaltyResponseModal, BankListResponseModal, \
15+
BeneficiaryListResponseModal, CardListResponseModal, AccountByPhoneResponseModal, UserInfoResponseModal, \
16+
LoanListResponseModal, SavingListResponseModal, InterestRateResponseModal, TransactionHistoryResponseModal, \
17+
CardTransactionsResponseModal, SavingDetailResponseModal
18+
19+
pool = concurrent.futures.ThreadPoolExecutor() # thread pool for blocking tasks like OCR and wasm
1520

16-
pool = concurrent.futures.ThreadPoolExecutor() # thread pool for blocking tasks like OCR and wasm
1721

1822
class MBBankAsync(MBBank):
1923
"""Core Async class
@@ -27,23 +31,40 @@ class MBBankAsync(MBBank):
2731
password (str): MBBank Account Password
2832
proxy (str, optional): Proxy url. Example: "http://127.0.0.1:8080". Defaults to None.
2933
ocr_class (CapchaProcessing, optional): CapchaProcessing class. Defaults to CapchaOCR().
34+
retry_times (int, optional): number of retry times for capcha processing. Defaults to 30 ( worst case ).
35+
timeout (Union[float, Tuple[float, float]], optional): request timeout in seconds or (connect timeout, read timeout) or None for no timeout. Defaults to None.
3036
"""
3137

32-
def __init__(self, *, username: str, password: str, proxy: typing.Optional[str] = None, ocr_class: typing.Optional[CapchaProcessing] =None):
33-
super().__init__(username=username, password=password, proxy=proxy, ocr_class=ocr_class)
38+
def __init__(self, *, username: str, password: str, proxy: typing.Optional[str] = None,
39+
ocr_class: typing.Optional[CapchaProcessing] = None,
40+
retry_times: int = 30,
41+
timeout: typing.Union[float, typing.Tuple[float, float], None] = None):
42+
super().__init__(username=username, password=password, ocr_class=ocr_class, retry_times=retry_times)
3443
# convert proxy dict by requests to aiohttp format
3544
if proxy is not None:
3645
self.proxy = proxy
3746
else:
3847
self.proxy = None
48+
if timeout is not None:
49+
if isinstance(timeout, tuple) and len(timeout) == 2:
50+
self.timeout = aiohttp.ClientTimeout(connect=timeout[0], sock_read=timeout[1])
51+
else:
52+
self.timeout = aiohttp.ClientTimeout(total=timeout)
53+
else:
54+
self.timeout = None
3955

4056
def _create_session(self) -> aiohttp.ClientSession:
4157
ssl_ctx = ssl.create_default_context()
4258
ssl_ctx.set_ciphers("DEFAULT:@SECLEVEL=1") # make it look like a normal browser request or requests
4359
connector = aiohttp.TCPConnector(
4460
ssl=ssl_ctx
4561
)
46-
return aiohttp.ClientSession(connector=connector)
62+
session_args = {
63+
"connector": connector,
64+
}
65+
if self.timeout is not None:
66+
session_args["timeout"] = self.timeout
67+
return aiohttp.ClientSession(**session_args)
4768

4869
async def _get_wasm_file(self):
4970
if self._wasm_cache is not None:
@@ -111,7 +132,7 @@ async def login(self, captcha_text: str):
111132
return
112133
else:
113134
raise MBBankError(data_out["result"])
114-
135+
115136
async def _verify_biometric_check(self):
116137
await self._req("https://online.mbbank.com.vn/api/retail-go-ekycms/v1.0/verify-biometric-nfc-transaction")
117138

@@ -128,7 +149,7 @@ async def _authenticate(self):
128149
return await self.login(text)
129150
except MBBankError as e:
130151
if e.code == "GW283":
131-
continue # capcha error, try again
152+
continue # capcha error, try again
132153
raise e
133154

134155
async def _req(self, url, *, json=None, headers=None):
@@ -164,7 +185,8 @@ async def _req(self, url, *, json=None, headers=None):
164185
raise MBBankError(data_out["result"])
165186
return data_out
166187

167-
async def getTransactionAccountHistory(self, *, accountNo: typing.Optional[str] = None, from_date: datetime.datetime,
188+
async def getTransactionAccountHistory(self, *, accountNo: typing.Optional[str] = None,
189+
from_date: datetime.datetime,
168190
to_date: datetime.datetime) -> TransactionHistoryResponseModal:
169191
"""
170192
Get account transaction history
@@ -323,7 +345,8 @@ async def getLoanList(self) -> LoanListResponseModal:
323345
data_out = await self._req("https://online.mbbank.com.vn/api/retail-onlineloanms/loan/getList")
324346
return LoanListResponseModal.model_validate(data_out, strict=True)
325347

326-
async def getCardTransactionHistory(self, cardNo: str, from_date: datetime.datetime, to_date: datetime.datetime) -> CardTransactionsResponseModal:
348+
async def getCardTransactionHistory(self, cardNo: str, from_date: datetime.datetime,
349+
to_date: datetime.datetime) -> CardTransactionsResponseModal:
327350
"""
328351
Get card transaction history
329352

0 commit comments

Comments
 (0)