jieshun-parking 0.6.5 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68926a0aeaf9f28755c8f054a766714f1ebe50919458c8085bc69d09a3b4c150
4
- data.tar.gz: 1b625c14754f9dd1b34892d0f552412809d1cf4c67859ee24544f8a6269fcd90
3
+ metadata.gz: f757e64ca65f7ec73d955625d1c052aa27b22e0af7977f2ad05bdc7f46b9f94c
4
+ data.tar.gz: 2cc8c9a4f32e449bccfb78bcdc14c1ba5a6769ab83da82a88569f0d2781d93a5
5
5
  SHA512:
6
- metadata.gz: 2b27373583050c8574fbfbf209c03e2f8e44b06f4a65bb56e1873f526e1f8f04c64c3fdae520141654a4062b2b80594f73cdae843ca4d5806513c89e679abae2
7
- data.tar.gz: 3a1ab8e23b5b34339d65364835cb33872ad3a000156c24e557a85d7bd556dfaa43e87157bda9ff9517b76ca42c6bbc3082db60ba8a5e3e4e509ead55892dcc49
6
+ metadata.gz: 5006b6816f38df63885b73823958fb7724e8fffe230c8a069a8a4030497f48862d957f0a371bbceef4c562e5538aa33c4cb910f1c8e5650f5a94e64de727ae96
7
+ data.tar.gz: 5222ccafbfec4b0547127a15d3fe7c65b4cb6e43374ad8120967bd1ad6260eb188a7e17cc61c472deb0f82800b1ee1540101907d17cd5488b3e47cb5cfba8885
@@ -1,119 +1,127 @@
1
1
  require_relative "./redis/redis_client"
2
2
  require "json"
3
3
  require 'digest'
4
-
5
4
  module Jieshun
6
- module Parking
7
-
8
- # 捷顺订单 API Client, 对应文档为 捷慧通云平台接口规范_2.1.doc 和 捷慧通云平台接口标准协议_http_V3.0.1.doc
9
- class Client
10
-
11
- REDIS_AUTH_KEY = 'jieshun.parking.auth.token'
12
- @@max_notify_try_times = 10
13
-
14
- def initialize(configuration, http_client = StandardHttpClient.new)
15
- @configuration = configuration
16
- @http_client = http_client
17
- @redis_client = RedisClient.new(@configuration.redis_config)
18
- end
19
-
20
-
21
- def get_auth_token
22
- @redis_client.redis_get(REDIS_AUTH_KEY)
23
- end
24
-
25
- def login_if_required
26
- auth_token = get_auth_token
27
- if Jieshun::Parking.always_login || auth_token.nil? || auth_token.empty?
28
- hash = { cid: @configuration.cid, usr: @configuration.usr, psw: @configuration.psw }
29
- @http_client.post_form("#{@configuration.server_url}/jsaims/login", {}, hash) do |result|
30
- auth_token = result.body['token']
31
- @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, 2 * 60 * 60 - 60) # token will be expired after 2 hours
32
- yield(auth_token)
33
- end
34
- else
35
- yield(auth_token)
36
- end
37
- end
38
-
39
- def create_order_by_car_no(park_code, car_no)
40
- payload = {
41
- "serviceId": "3c.pay.createorderbycarno",
42
- "requestType": "DATA",
43
- "attributes": {
44
- "businesserCode": @configuration.businesser_code,
45
- "parkCode": park_code,
46
- "orderType": "VNP",
47
- "carNo": car_no
48
- }
49
- }.to_json
50
- unify_call(payload) do |result|
51
- # 0:正常,正常订单
52
- # 1:安装验证失败,前端设备异常
53
- # 2:未入场
54
- # 5:非临时卡
55
- # 6:未设置收费标准,前端停车场异常
56
- # 9:已缴费,超时滞留时间内
57
- # 10:正常免费时间段内
58
- # 11:打折免费时间段内
59
- # 12:打折全免时间段内
60
- # 13:打折减免时间段内
61
- # 20:超时收费不能使用卡券
62
- # 3 1:已入场无需缴费
63
- # 9999:其它未知错误
64
- attributes = result.body['dataItems'].first['attributes']
65
- retcode = attributes['retcode']
66
- retmsg = attributes['retmsg']
67
- raise RuntimeError.new(retmsg) if retcode != '0'
68
- yield(result)
69
- end
70
- end
71
-
72
- def unify_call(payload)
73
- login_if_required do |auth_token|
74
- sn = generate_signature("#{payload}#{@configuration.sign_key}")
75
-
76
- hash = {
77
- cid: @configuration.cid,
78
- tn: auth_token,
79
- v: 2,
80
- sn: sn,
81
- p: payload
82
- }
83
-
84
- @http_client.post_form("#{@configuration.server_url}/jsaims/as", { }, hash) do |result|
85
- yield(result)
86
- end
87
-
88
- end
89
- end
90
-
91
- def generate_signature(payload)
92
- md5_string = Digest::MD5.hexdigest(payload)
93
- md5_string.upcase
94
- end
95
-
96
- def notify_order_result(order_no, pay_type, pay_time, transaction_id)
97
- Retry.with_retries(max_tries: 10, sleep_seconds: 1, business_info: { order_no: order_no }) do
98
- payload = {
99
- "serviceId": "3c.pay.notifyorderresult",
100
- "requestType":"DATA",
101
- "attributes":{
102
- "orderNo": order_no,
103
- "tradeStatus": 0,
104
- "isCallBack": 0,
105
- "payType": pay_type,
106
- "payTime": pay_time.strftime('%Y-%m-%d %H:%M:%S'),
107
- "transactionId": transaction_id
108
- }
109
- }.to_json
110
- unify_call(payload) do |result|
111
- yield(result)
112
- end
113
- end
114
- end
115
-
116
- end
117
-
118
- end
5
+ module Parking
6
+ # 捷顺订单 API Client, 对应文档为 捷慧通云平台接口规范_2.1.doc 和 捷慧通云平台接口标准协议_http_V3.0.1.doc
7
+ class Client
8
+ REDIS_AUTH_KEY = 'jieshun.parking.auth.token'
9
+ @@max_notify_try_times = 10
10
+
11
+ def initialize(configuration, http_client = StandardHttpClient.new)
12
+ @configuration = configuration
13
+ @http_client = http_client
14
+ @redis_client = RedisClient.new(@configuration.redis_config)
15
+ end
16
+
17
+ def get_auth_token
18
+ @redis_client.redis_get(REDIS_AUTH_KEY)
19
+ end
20
+
21
+ def login_if_required
22
+ auth_token = get_auth_token
23
+ if Jieshun::Parking.always_login || auth_token.nil? || auth_token.empty?
24
+ hash = { cid: @configuration.cid, usr: @configuration.usr, psw: @configuration.psw }
25
+ @http_client.post_form("#{@configuration.server_url}/jsaims/login",
26
+ {},
27
+ hash,
28
+ ->(response) {
29
+ auth_token = response['token']
30
+ @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, 2 * 60 * 60 - 60) # token will be expired after 2 hours
31
+ yield(auth_token)
32
+ },
33
+ ->(error) { handle_failure(error) })
34
+ else
35
+ yield(auth_token)
36
+ end
37
+ end
38
+
39
+ def create_order_by_car_no(park_code, car_no)
40
+ payload = {
41
+ "serviceId": "3c.pay.createorderbycarno",
42
+ "requestType": "DATA",
43
+ "attributes": {
44
+ "businesserCode": @configuration.businesser_code,
45
+ "parkCode": park_code,
46
+ "orderType": "VNP",
47
+ "carNo": car_no
48
+ }
49
+ }.to_json
50
+ unify_call(payload) do |result|
51
+ # 0:正常,正常订单
52
+ # 1:安装验证失败,前端设备异常
53
+ # 2:未入场
54
+ # 5:非临时卡
55
+ # 6:未设置收费标准,前端停车场异常
56
+ # 9:已缴费,超时滞留时间内
57
+ # 10:正常免费时间段内
58
+ # 11:打折免费时间段内
59
+ # 12:打折全免时间段内
60
+ # 13:打折减免时间段内
61
+ # 20:超时收费不能使用卡券
62
+ # 3 1:已入场无需缴费
63
+ # 9999:其它未知错误
64
+ attributes = result.body['dataItems'].first['attributes']
65
+ retcode = attributes['retcode']
66
+ retmsg = attributes['retmsg']
67
+ raise RuntimeError.new(retmsg) if retcode != '0'
68
+ yield(result)
69
+ end
70
+ end
71
+
72
+ def unify_call(payload)
73
+ login_if_required do |auth_token|
74
+ sn = generate_signature("#{payload}#{@configuration.sign_key}")
75
+ hash = {
76
+ cid: @configuration.cid,
77
+ tn: auth_token,
78
+ v: 2,
79
+ sn: sn,
80
+ p: payload
81
+ }
82
+ @http_client.post_form("#{@configuration.server_url}/jsaims/as",
83
+ {},
84
+ hash,
85
+ ->(response) { yield(response) },
86
+ ->(error) { handle_failure(error) })
87
+ end
88
+ end
89
+
90
+ def generate_signature(payload)
91
+ md5_string = Digest::MD5.hexdigest(payload)
92
+ md5_string.upcase
93
+ end
94
+
95
+ def notify_order_result(order_no, pay_type, pay_time, transaction_id)
96
+ Retry.with_retries(max_tries: 10, sleep_seconds: 1, business_info: { order_no: order_no }) do
97
+ payload = {
98
+ "serviceId": "3c.pay.notifyorderresult",
99
+ "requestType": "DATA",
100
+ "attributes": {
101
+ "orderNo": order_no,
102
+ "tradeStatus": 0,
103
+ "isCallBack": 0,
104
+ "payType": pay_type,
105
+ "payTime": pay_time.strftime('%Y-%m-%d %H:%M:%S'),
106
+ "transactionId": transaction_id
107
+ }
108
+ }.to_json
109
+ unify_call(payload) do |result|
110
+ yield(result)
111
+ end
112
+ end
113
+ end
114
+
115
+ # 捷慧通云平台接口规范_2.1.doc[4.7异常列表]
116
+ # 0:没有异常
117
+ # 6: 无效的令牌或令牌已过期
118
+ def handle_failure(error)
119
+ case error['resultCode']
120
+ when 6
121
+ @redis_client.redis_del(REDIS_AUTH_KEY)
122
+ end
123
+ raise RuntimeError.new("Unified error handling for client; resultCode:#{error['resultCode']}, message: #{error['message']}")
124
+ end
125
+ end
126
+ end
119
127
  end
@@ -49,12 +49,16 @@ module Jieshun
49
49
 
50
50
  def refresh_token
51
51
  hash = { pno: @configuration.pno, secret: @configuration.secret }
52
- @http_client.post_json("#{@configuration.server_url}/api/login", {}, hash) do |result|
53
- auth_token = result.body['tn']
54
- expire_time = result.body['timeOut'] - 1000
55
- @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, expire_time) # token will be expired after 2 hours
56
- yield(auth_token)
57
- end
52
+ @http_client.post_json("#{@configuration.server_url}/api/login",
53
+ {},
54
+ hash,
55
+ ->(response) {
56
+ auth_token = response['tn']
57
+ expire_time = response['timeOut'] > 7200 ? response['timeOut'] - 7200 : response['timeOut'] # the token will expire 2 hours in advance
58
+ @redis_client.redis_set(REDIS_AUTH_KEY, auth_token, expire_time)
59
+ yield(auth_token)
60
+ },
61
+ ->(error) { handle_failure(error) })
58
62
  end
59
63
 
60
64
  def get_picture_base64(file_path)
@@ -91,10 +95,35 @@ module Jieshun
91
95
  sn: sn,
92
96
  dataItems: data_items
93
97
  }
94
- @http_client.post_json("#{@configuration.server_url}/#{api_path}", {}, hash) do |result|
95
- yield(result)
96
- end
98
+ @http_client.post_json("#{@configuration.server_url}/#{api_path}",
99
+ {},
100
+ hash,
101
+ ->(response) { yield(response) },
102
+ ->(error) { handle_failure(error) })
103
+ end
104
+ end
105
+
106
+ #0:成功
107
+ # 1:处理失败
108
+ # 100:参数为空
109
+ # 101:账号为空
110
+ # 102:密码为空
111
+ # 103:签名为空
112
+ # 104:令牌为空
113
+ # 105:dataItem为空
114
+ # 201:账号不存在
115
+ # 202:密码错误
116
+ # 203:令牌过期
117
+ # 204:格式错误
118
+ # 205:验签失败
119
+ #
120
+ # 301:IP未绑定
121
+ def handle_failure(error)
122
+ case error['resultCode']
123
+ when 203
124
+ @redis_client.redis_del(REDIS_AUTH_KEY)
97
125
  end
126
+ raise RuntimeError.new("Unified error handling for data center clients; resultCode:#{error['resultCode']}, message: #{error['message']}")
98
127
  end
99
128
 
100
129
  def generate_signature(payload)
@@ -4,11 +4,11 @@ module Jieshun
4
4
 
5
5
  class HttpClient
6
6
 
7
- def post_form(server_url, headers, hash)
7
+ def post_form(server_url, headers, hash, success_callback, failure_callback)
8
8
  raise NotImplementedError.new("You must implement this method.")
9
9
  end
10
10
 
11
- def post_json(server_url, headers, hash)
11
+ def post_json(server_url, headers, hash, success_callback, failure_callback)
12
12
  raise NotImplementedError.new("You must implement this method.")
13
13
  end
14
14
 
@@ -1,68 +1,68 @@
1
1
  module Jieshun
2
- module Parking
2
+ module Parking
3
+ class StandardHttpClient < HttpClient
4
+ require 'net/http'
5
+ require 'uri'
6
+ require 'json'
7
+ # 设置连接和读取的超时时间(以秒为单位)
8
+ TIMEOUT = 30 # 例如,30 秒超时
9
+ def post_form(server_url, headers, hash, success_callback, failure_callback)
10
+ post(server_url, 'application/x-www-form-urlencoded', headers, hash) do |result|
11
+ if result.successful
12
+ success_callback.call(result.body)
13
+ else
14
+ failure_callback.call(result.body)
15
+ end
16
+ end
17
+ end
3
18
 
4
- class StandardHttpClient < HttpClient
19
+ def post_json(server_url, headers, hash, success_callback, failure_callback)
20
+ post(server_url, 'application/json', headers, hash) do |result|
21
+ if result.successful
22
+ success_callback.call(result.body)
23
+ else
24
+ failure_callback.call(result.body)
25
+ end
26
+ end
27
+ end
5
28
 
6
- require 'net/http'
7
- require 'uri'
8
- require 'json'
9
-
10
- # 设置连接和读取的超时时间(以秒为单位)
11
- TIMEOUT = 30 # 例如,30 秒超时
12
-
13
- def post_form(server_url, headers, hash)
14
- post(server_url, 'application/x-www-form-urlencoded', headers, hash) do |result|
15
- yield(result)
16
- end
17
- end
18
-
19
- def post_json(server_url, headers, hash)
20
- post(server_url, 'application/json', headers, hash) do |result|
21
- yield(result)
22
- end
23
- end
24
-
25
- def post(server_url, content_type, headers, hash)
26
- uri = URI.parse(server_url)
27
- req = Net::HTTP::Post.new(uri)
28
- headers.each { |k, v| req[k] = v }
29
- req["Content-Type"] = content_type
30
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', read_timeout: TIMEOUT, open_timeout: TIMEOUT) do |http|
31
- if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
32
- Jieshun::Parking.logger.debug("Jieshun Parking Request, url: #{server_url}, body: #{JSON.pretty_generate(hash)}")
33
- end
34
- if content_type == 'application/json'
35
- req.body = hash.to_json
36
- elsif content_type == 'application/x-www-form-urlencoded'
37
- req.set_form_data(hash)
38
- else
39
- raise RuntimeError.new("Unsupported content type #{content_type}")
40
- end
41
-
42
- res = http.request(req)
43
- if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
44
- Jieshun::Parking.logger.debug("Jieshun Parking Response #{JSON.pretty_generate(JSON.parse(res.body))}")
45
- end
46
- successful = res.kind_of?(Net::HTTPSuccess)
47
- unless successful
48
- message = "Got error response from jieshun #{res.status}"
49
- Jieshun::Parking.logger.error(message)
50
- raise RuntimeError.new(message)
51
- end
52
- json = JSON.parse(res.body)
53
- result_code = json['resultCode']
54
- unless result_code.zero?
55
- message = "Got invalid result code jieshun resultCode: #{result_code}, message: #{json['message']}"
56
- Jieshun::Parking.logger.error(message)
57
- raise RuntimeError.new(json['message'])
58
- end
59
-
60
- result = Jieshun::Parking::Result.new(successful, json.to_hash)
61
- yield result
62
- end
63
- end
64
-
65
- end
66
-
67
- end
29
+ def post(server_url, content_type, headers, hash)
30
+ uri = URI.parse(server_url)
31
+ req = Net::HTTP::Post.new(uri)
32
+ headers.each { |k, v| req[k] = v }
33
+ req["Content-Type"] = content_type
34
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', read_timeout: TIMEOUT, open_timeout: TIMEOUT) do |http|
35
+ if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
36
+ Jieshun::Parking.logger.debug("Jieshun Parking Request, url: #{server_url}, body: #{JSON.pretty_generate(hash)}")
37
+ end
38
+ if content_type == 'application/json'
39
+ req.body = hash.to_json
40
+ elsif content_type == 'application/x-www-form-urlencoded'
41
+ req.set_form_data(hash)
42
+ else
43
+ raise RuntimeError.new("Unsupported content type #{content_type}")
44
+ end
45
+ res = http.request(req)
46
+ if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
47
+ Jieshun::Parking.logger.debug("Jieshun Parking Response #{JSON.pretty_generate(JSON.parse(res.body))}")
48
+ end
49
+ successful = res.kind_of?(Net::HTTPSuccess)
50
+ unless successful
51
+ message = "Got error response from jieshun #{res.status}"
52
+ Jieshun::Parking.logger.error(message)
53
+ raise RuntimeError.new(message)
54
+ end
55
+ json = JSON.parse(res.body)
56
+ result_code = json['resultCode']
57
+ # unless result_code.zero?
58
+ # message = "Got invalid result code jieshun resultCode: #{result_code}, message: #{json['message']}"
59
+ # Jieshun::Parking.logger.error(message)
60
+ # raise RuntimeError.new(json)
61
+ # end
62
+ result = Jieshun::Parking::Result.new(result_code.zero?, json.to_hash)
63
+ yield result
64
+ end
65
+ end
66
+ end
67
+ end
68
68
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jieshun
4
4
  module Parking
5
- VERSION = "0.6.5"
5
+ VERSION = "0.6.6"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jieshun-parking
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - LCola
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-06 00:00:00.000000000 Z
11
+ date: 2024-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport