Class: Jieshun::Parking::DataCenterClient
- Inherits:
-
Object
- Object
- Jieshun::Parking::DataCenterClient
- Defined in:
- lib/jieshun/parking/data_center_client.rb
Overview
捷顺数据中心 Client, 目前主要用来获取图片, 对应文档为 QX205_数据中心标准推送协议-1.1.6(1)
Constant Summary collapse
- REDIS_AUTH_KEY =
'jieshun.parking.datacenter.auth.token'
- REDIS_AUTH_KEY_LOCK =
'jieshun.parking.datacenter.auth.token.lock'
- MAX_RETRY_COUNT =
定义refresh_token 最大重试次数
3
Instance Method Summary collapse
- #content_matches?(base64_content, prefixes) ⇒ Boolean
- #detect_mime_type(base64_content) ⇒ Object
- #generate_signature(payload) ⇒ Object
- #get_auth_token ⇒ Object
- #get_picture_base64(file_path) ⇒ Object
-
#handle_failure(error) ⇒ Object
0:成功 1:处理失败 100:参数为空 101:账号为空 102:密码为空 103:签名为空 104:令牌为空 105:dataItem为空 201:账号不存在 202:密码错误 203:令牌过期 204:格式错误 205:验签失败.
-
#initialize(configuration, http_client = StandardHttpClient.new) ⇒ DataCenterClient
constructor
A new instance of DataCenterClient.
- #login_if_required ⇒ Object
- #refresh_token ⇒ Object
- #unify_call(api_path, data_items) ⇒ Object
Constructor Details
#initialize(configuration, http_client = StandardHttpClient.new) ⇒ DataCenterClient
Returns a new instance of DataCenterClient.
8 9 10 11 12 |
# File 'lib/jieshun/parking/data_center_client.rb', line 8 def initialize(configuration, http_client = StandardHttpClient.new) @configuration = configuration @http_client = http_client @redis_client = RedisClient.new(@configuration.redis_config) end |
Instance Method Details
#content_matches?(base64_content, prefixes) ⇒ Boolean
87 88 89 |
# File 'lib/jieshun/parking/data_center_client.rb', line 87 def content_matches?(base64_content, prefixes) prefixes.any? { |prefix| base64_content.start_with?(prefix) } end |
#detect_mime_type(base64_content) ⇒ Object
78 79 80 81 82 83 84 85 |
# File 'lib/jieshun/parking/data_center_client.rb', line 78 def detect_mime_type(base64_content) return "application/pdf" if content_matches?(base64_content, ['JVBERi0']) return "image/gif" if content_matches?(base64_content, ['R0lGODdh', 'R0lGODlh']) return "image/png" if content_matches?(base64_content, ['iVBORw0KGgo']) return "image/jpg" if content_matches?(base64_content, ['/9j/']) return "image/bmp" if content_matches?(base64_content, ['Qk']) "application/octet-stream" end |
#generate_signature(payload) ⇒ Object
138 139 140 141 |
# File 'lib/jieshun/parking/data_center_client.rb', line 138 def generate_signature(payload) md5_string = Digest::MD5.hexdigest(payload) md5_string.upcase end |
#get_auth_token ⇒ Object
14 15 16 |
# File 'lib/jieshun/parking/data_center_client.rb', line 14 def get_auth_token @redis_client.redis_get(REDIS_AUTH_KEY) end |
#get_picture_base64(file_path) ⇒ Object
68 69 70 71 72 73 74 75 76 |
# File 'lib/jieshun/parking/data_center_client.rb', line 68 def get_picture_base64(file_path) data_items = [] data_items << { filePath: file_path } unify_call("/api/pic/picSearch", data_items.to_json) do |result| image = result.body['dataItems'].first['image'] mime_type = detect_mime_type(image) yield({ mime_type_prefix: "data:#{mime_type};base64,", content: image }) end end |
#handle_failure(error) ⇒ Object
0:成功 1:处理失败 100:参数为空 101:账号为空 102:密码为空 103:签名为空 104:令牌为空 105:dataItem为空 201:账号不存在 202:密码错误 203:令牌过期 204:格式错误 205:验签失败
301:IP未绑定
130 131 132 133 134 135 136 |
# File 'lib/jieshun/parking/data_center_client.rb', line 130 def handle_failure(error) case error.body['resultCode'] when 203 @redis_client.redis_del(REDIS_AUTH_KEY) end raise RuntimeError.new("Unified error handling for data center clients; resultCode:#{error.body['resultCode']}, message: #{error.body['message']}") end |
#login_if_required ⇒ Object
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 |
# File 'lib/jieshun/parking/data_center_client.rb', line 18 def login_if_required auth_token = get_auth_token if Jieshun::Parking.always_login || auth_token.nil? || auth_token.empty? # 使用 Redis 锁来避免并发刷新 lock_key = REDIS_AUTH_KEY_LOCK begin # 设置一个5秒过期的锁 if @redis_client.redis_set_nx_lock(lock_key, 5) # 重试机制 Retry.with_retries(max_tries: MAX_RETRY_COUNT, sleep_seconds: 1) do # 过程中遇到错误重试时, 检查本地token是否存在 auth_token = get_auth_token if auth_token yield(auth_token) else refresh_token do |auth_token| yield(auth_token) end end end end rescue StandardError => e Jieshun::Parking.logger.info("Failed to refresh token;error: #{e.}") ensure # 确保锁最终被释放 @redis_client.redis_del(lock_key) end else yield(auth_token) end end |
#refresh_token ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/jieshun/parking/data_center_client.rb', line 50 def refresh_token hash = { pno: @configuration.pno, secret: @configuration.secret } @http_client.post_json("#{@configuration.server_url}/api/login", {}, hash, ->(callback) { if callback.successful response = callback.body auth_token = response['tn'] expire_time = response['timeOut'] > 7200 ? response['timeOut'] - 7200 : response['timeOut'] # the token will expire 2 hours in advance @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, expire_time) yield(auth_token) else handle_failure(callback) end }) end |
#unify_call(api_path, data_items) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/jieshun/parking/data_center_client.rb', line 91 def unify_call(api_path, data_items) login_if_required do |auth_token| ts = Time.now.strftime("%Y%m%d%H%M%S%L") sn = generate_signature("#{@configuration.secret}#{ts}#{data_items}") hash = { pno: @configuration.pno, tn: auth_token, ts: ts, sn: sn, dataItems: data_items } @http_client.post_json("#{@configuration.server_url}/#{api_path}", {}, hash, ->(callback) { if callback.successful yield(callback) else handle_failure(callback) end }) end end |