Skip to content

Commit 814fd48

Browse files
committed
token file
1 parent d83579c commit 814fd48

File tree

4 files changed

+78
-19
lines changed

4 files changed

+78
-19
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 2.3.0 (2023-02-16)
2+
### New
3+
- 支持配置文件
4+
- 支持2FA token
5+
6+
17
## 2.2.9 (2023-02-09)
28
### Fix
39
- 修复tick数据推送报错的问题

tigeropen/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
55
@author: gaoan
66
"""
7-
__VERSION__ = '2.2.9'
7+
__VERSION__ = '2.3.0'

tigeropen/tiger_open_client.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import json
99
import logging
1010
import uuid
11+
from threading import Timer
1112

1213
import backoff
1314

@@ -34,14 +35,21 @@ def get_mac_address():
3435
SKIP_RETRY_SERVICES = {PLACE_ORDER, CANCEL_ORDER, MODIFY_ORDER}
3536

3637

38+
_SCHEDULE_STATE = {'is_running': False}
39+
TOKEN_CHECK_INTERVAL = 300
40+
41+
3742
class TigerOpenClient:
3843
"""
3944
client_config:客户端配置,包含tiger_id、应用私钥、老虎公钥等
4045
logger:日志对象,客户端执行信息会通过此日志对象输出
4146
"""
42-
4347
def __init__(self, client_config, logger=None):
4448
self.__config = client_config
49+
if not client_config.private_key:
50+
raise Exception('private key can not be empty')
51+
if not client_config.tiger_id:
52+
raise Exception('tiger id can not be empty')
4553
if logger:
4654
if client_config.log_level:
4755
logger.setLevel(logging.getLevelName(client_config.log_level))
@@ -59,7 +67,8 @@ def __init__(self, client_config, logger=None):
5967
self.__device_id = self.__get_device_id()
6068
self.__init_license()
6169
self.__refresh_server_info()
62-
self.__refresh_token()
70+
if self.__config.token and self.__config.license:
71+
self.__schedule_thread()
6372

6473
def __init_license(self):
6574
if self.__config.license is None and self.__config.enable_dynamic_domain:
@@ -174,7 +183,8 @@ def _get_retry_deco(self, service):
174183
执行接口请求
175184
"""
176185
def execute(self, request, url=None):
177-
self._update_header()
186+
if self.__config.token:
187+
self._update_header()
178188
if url is None:
179189
url = self.__config.server_url
180190
THREAD_LOCAL.uuid = str(uuid.uuid1())
@@ -205,7 +215,7 @@ def query_license(self):
205215
return json.loads(response.data).get('license')
206216
self.__logger.error(f"failed to query license, response: {response_content}")
207217

208-
def __refresh_token(self):
218+
def refresh_token(self):
209219
request = OpenApiRequest(method=USER_TOKEN_REFRESH)
210220

211221
response_content = None
@@ -219,4 +229,27 @@ def __refresh_token(self):
219229
if response.is_success():
220230
return json.loads(response.data).get('token')
221231
self.__logger.error(f"failed to refresh token, response: {response_content}")
232+
return None
233+
234+
def token_refresh_task(self):
235+
try:
236+
if self.__config.should_token_refresh():
237+
new_token = self.refresh_token()
238+
if new_token:
239+
self.__logger.info(f"refresh token, old:{self.__config.token}, new:{new_token}")
240+
self.__config.load_or_store_token(new_token)
241+
except Exception as e:
242+
self.__logger.error(e, exc_info=True)
243+
244+
def __schedule_thread(self):
245+
if not _SCHEDULE_STATE['is_running']:
246+
_SCHEDULE_STATE['is_running'] = True
247+
self.__logger.info('Starting schedule thread...')
248+
daemon = RepeatTimer(TOKEN_CHECK_INTERVAL, self.token_refresh_task)
249+
daemon.start()
250+
222251

252+
class RepeatTimer(Timer):
253+
def run(self):
254+
while not self.finished.wait(self.interval):
255+
self.function(*self.args, **self.kwargs)

tigeropen/tiger_open_config.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
55
@author: gaoan
66
"""
7+
import base64
78
import json
89
import logging
910
import os
11+
import time
1012

1113
from jproperties import Properties
1214
from pytz import timezone
@@ -51,10 +53,11 @@
5153

5254
DEFAULT_PROPS_FILE = 'tiger_openapi_config.properties'
5355
DEFAULT_TOKEN_FILE = 'tiger_openapi_token.properties'
56+
TOKEN_REFRESH_DURATION = 24 * 60 * 60 # seconds
5457

5558

5659
class TigerOpenClientConfig:
57-
def __init__(self, sandbox_debug=False, enable_dynamic_domain=True, props_path='.'):
60+
def __init__(self, sandbox_debug=None, enable_dynamic_domain=True, props_path='.'):
5861
# 开发者应用id
5962
self._tiger_id = ''
6063
# 授权账户
@@ -85,11 +88,6 @@ def __init__(self, sandbox_debug=False, enable_dynamic_domain=True, props_path='
8588
self._server_url = SERVER_URL
8689
self._quote_server_url = SERVER_URL
8790
self._socket_host_port = SOCKET_HOST_PORT
88-
if sandbox_debug:
89-
self._tiger_public_key = SANDBOX_TIGER_PUBLIC_KEY
90-
self._server_url = SANDBOX_SERVER_URL
91-
self._quote_server_url = SANDBOX_SERVER_URL
92-
self._socket_host_port = SANDBOX_SOCKET_HOST_PORT
9391

9492
self.log_level = None
9593
self.log_path = None
@@ -98,11 +96,16 @@ def __init__(self, sandbox_debug=False, enable_dynamic_domain=True, props_path='
9896
self.props_path = props_path
9997
self.token = None
10098
self._load_props()
101-
self._load_token()
99+
self.load_or_store_token()
102100

103101
self.domain_conf = dict()
104102
self.enable_dynamic_domain = enable_dynamic_domain
105-
if enable_dynamic_domain:
103+
if self._sandbox_debug:
104+
self._tiger_public_key = SANDBOX_TIGER_PUBLIC_KEY
105+
self._server_url = SANDBOX_SERVER_URL
106+
self._quote_server_url = SANDBOX_SERVER_URL
107+
self._socket_host_port = SANDBOX_SOCKET_HOST_PORT
108+
if self.enable_dynamic_domain:
106109
self.domain_conf = self.query_domains()
107110
self.refresh_server_info()
108111

@@ -239,11 +242,12 @@ def token(self, value):
239242
self._token = value
240243

241244
def _get_props_path(self, filename):
242-
if self.props_path is not None and os.path.exists(self.props_path):
245+
if self.props_path is not None:
243246
if os.path.isdir(self.props_path):
244247
full_path = os.path.join(self.props_path, filename)
245248
else:
246-
full_path = self.props_path
249+
dirname = os.path.dirname(self.props_path)
250+
full_path = os.path.join(dirname, filename)
247251
return full_path
248252
return None
249253

@@ -262,21 +266,37 @@ def _load_props(self):
262266
self.account = getattr(p.get('account'), 'data', '')
263267
if not self.license:
264268
self.license = getattr(p.get('license'), 'data', '')
269+
if not self._sandbox_debug:
270+
is_sandbox_env = getattr(p.get('env'), 'data', '').upper() == 'SANDBOX'
271+
self._sandbox_debug = is_sandbox_env
265272
except Exception as e:
266273
logging.error(e, exc_info=True)
267274

268-
def _load_token(self):
275+
def load_or_store_token(self, token=None):
269276
full_path = self._get_props_path(DEFAULT_TOKEN_FILE)
270277
if full_path and os.path.exists(full_path):
271278
try:
272279
p = Properties()
273280
with open(full_path, "r+b") as f:
274-
p.load(f, "utf-8")
275-
if not self.token:
276-
self.token = getattr(p.get('token'), 'data', '')
281+
if token:
282+
self.token = token
283+
p['token'] = token
284+
p.store(f, encoding='utf-8')
285+
else:
286+
p.load(f, "utf-8")
287+
if not self.token:
288+
self.token = getattr(p.get('token'), 'data', '')
277289
except Exception as e:
278290
logging.error(e, exc_info=True)
279291

292+
def should_token_refresh(self, duration=TOKEN_REFRESH_DURATION):
293+
if self.token:
294+
tokeninfo = base64.b64decode(self.token)
295+
gen_ts, expire_ts = tokeninfo[:27].decode('utf-8').split(',')
296+
if (int(time.time()) - int(gen_ts) // 1000) > duration:
297+
return True
298+
return False
299+
280300
def refresh_server_info(self):
281301
if self.enable_dynamic_domain and self.domain_conf:
282302
if self.license:

0 commit comments

Comments
 (0)