Class: Jieshun::Parking::DataCenterClient

Inherits:
Object
  • Object
show all
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

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

Returns:

  • (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_tokenObject



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未绑定

Raises:

  • (RuntimeError)


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_requiredObject



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 
	auth_token = get_auth_token
	if Jieshun::Parking. || 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.message}")
		ensure
			# 确保锁最终被释放
			@redis_client.redis_del(lock_key)
		end
	else
		yield(auth_token)
	end
end

#refresh_tokenObject



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)
	 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