88import json
99import logging
1010import uuid
11+ from threading import Timer
1112
1213import backoff
1314
1415from tigeropen import __VERSION__
1516from tigeropen .common .consts import OPEN_API_SERVICE_VERSION , THREAD_LOCAL
1617from tigeropen .common .consts .params import P_TIMESTAMP , P_TIGER_ID , P_METHOD , P_CHARSET , P_VERSION , P_SIGN_TYPE , \
1718 P_DEVICE_ID , P_NOTIFY_URL , COMMON_PARAM_KEYS , P_SIGN
18- from tigeropen .common .consts .service_types import USER_LICENSE , PLACE_ORDER , CANCEL_ORDER , MODIFY_ORDER
19+ from tigeropen .common .consts .service_types import USER_LICENSE , PLACE_ORDER , CANCEL_ORDER , MODIFY_ORDER , \
20+ USER_TOKEN_REFRESH
1921from tigeropen .common .exceptions import ResponseException , RequestException
2022from tigeropen .common .request import OpenApiRequest
2123from tigeropen .common .response import TigerResponse
@@ -33,14 +35,21 @@ def get_mac_address():
3335SKIP_RETRY_SERVICES = {PLACE_ORDER , CANCEL_ORDER , MODIFY_ORDER }
3436
3537
38+ _SCHEDULE_STATE = {'is_running' : False }
39+ TOKEN_CHECK_INTERVAL = 300
40+
41+
3642class TigerOpenClient :
3743 """
3844 client_config:客户端配置,包含tiger_id、应用私钥、老虎公钥等
3945 logger:日志对象,客户端执行信息会通过此日志对象输出
4046 """
41-
4247 def __init__ (self , client_config , logger = None ):
4348 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' )
4453 if logger :
4554 if client_config .log_level :
4655 logger .setLevel (logging .getLevelName (client_config .log_level ))
@@ -58,6 +67,8 @@ def __init__(self, client_config, logger=None):
5867 self .__device_id = self .__get_device_id ()
5968 self .__init_license ()
6069 self .__refresh_server_info ()
70+ if self .__config .token and self .__config .license :
71+ self .__schedule_thread ()
6172
6273 def __init_license (self ):
6374 if self .__config .license is None and self .__config .enable_dynamic_domain :
@@ -156,6 +167,9 @@ def __parse_response(self, response_str, timestamp=None):
156167
157168 return response_content
158169
170+ def _update_header (self ):
171+ self .__headers ['Authorization' ] = self .__config .token
172+
159173 def _get_retry_deco (self , service ):
160174 if service not in SKIP_RETRY_SERVICES and self .__config .retry_max_tries > 0 :
161175 return backoff .on_exception (backoff .fibo ,
@@ -169,6 +183,8 @@ def _get_retry_deco(self, service):
169183 执行接口请求
170184 """
171185 def execute (self , request , url = None ):
186+ if self .__config .token :
187+ self ._update_header ()
172188 if url is None :
173189 url = self .__config .server_url
174190 THREAD_LOCAL .uuid = str (uuid .uuid1 ())
@@ -198,3 +214,42 @@ def query_license(self):
198214 if response .is_success ():
199215 return json .loads (response .data ).get ('license' )
200216 self .__logger .error (f"failed to query license, response: { response_content } " )
217+
218+ def refresh_token (self ):
219+ request = OpenApiRequest (method = USER_TOKEN_REFRESH )
220+
221+ response_content = None
222+ try :
223+ response_content = self .execute (request )
224+ except Exception as e :
225+ self .__logger .error (e , exc_info = True )
226+ if response_content :
227+ response = TigerResponse ()
228+ response .parse_response_content (response_content )
229+ if response .is_success ():
230+ return json .loads (response .data ).get ('token' )
231+ 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+
251+
252+ class RepeatTimer (Timer ):
253+ def run (self ):
254+ while not self .finished .wait (self .interval ):
255+ self .function (* self .args , ** self .kwargs )
0 commit comments