jieshun-parking 0.2.0 → 0.3.1

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: 2cf30541d80208f34adca825b070430ab9c403a660ab8396041f3d03d6a9d297
4
- data.tar.gz: 40f8577ec4775ac3bcd9377cf0efc3d7b9c1f9a2115549f55121c4acaa1e7ed9
3
+ metadata.gz: dcff311fa412b01113a075ad7622765777928ad3aed9b23f04dc5e4c405b3f19
4
+ data.tar.gz: 278c470b20aa79112ba66894adaaeb4e3aac5b15ccf187ef165375d7ef38d95c
5
5
  SHA512:
6
- metadata.gz: 6d1b0b285e0dadaacbffdf3920abdc1044450716e89202ec4aa945697b90f445efd528f2576a3b1b30176f9864e707889549931ecd1bf0cad28aeafca8f6d0ef
7
- data.tar.gz: e4e4c0aa60c3200aa0abaa1850354504aa8ac1b057a53d8a8755011230744d37848f5e019283f0a25562e4a1a872640c7364de02061615757b0dd9ed069d3b4c
6
+ metadata.gz: 766149c652dfc911a6684baf6072f06a8e4c9d4c9b85b31c704efb02cd5f13b0df08bddc91db51a06a24780958fc27e4d2ccfb21d70b346b8327528f9e2b6746
7
+ data.tar.gz: 1f7a0b2961316ea2c081f2b1f9a8514e62791af84c0c3ecb0bc56e3454ddd32c38cf43aed86ddac314005d3f18b36ef833c3c2f8c3a9f1002586b97376d18dbb
@@ -1,38 +1,114 @@
1
+ require_relative "./redis/redis_client"
2
+ require "json"
3
+ require 'digest'
4
+
1
5
  module Jieshun
2
6
  module Parking
3
7
 
4
8
  class Client
5
9
 
10
+ REDIS_AUTH_KEY = 'jieshun.parking.auth.token'
11
+ @@max_notify_try_times = 10
12
+
6
13
  def initialize(configuration, http_client = StandardHttpClient.new)
7
14
  @configuration = configuration
8
15
  @http_client = http_client
16
+ @redis_client = RedisClient.new(@configuration.redis_config)
17
+ end
18
+
19
+
20
+ def get_auth_token
21
+ @redis_client.redis_get(REDIS_AUTH_KEY)
22
+ end
23
+
24
+ def login_if_required
25
+ auth_token = get_auth_token
26
+ if Jieshun::Parking.always_login || auth_token.nil? || auth_token.empty?
27
+ hash = { cid: @configuration.cid, usr: @configuration.usr, psw: @configuration.psw }
28
+ @http_client.post_form("#{@configuration.server_url}/jsaims/login", {}, hash) do |result|
29
+ auth_token = result.body['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
+ end
33
+ else
34
+ yield(auth_token)
35
+ end
9
36
  end
10
37
 
11
- def create_payment_order(park_code, car_no)
12
- headers = { }
13
- hash = {
14
- serviceId: '3c.pay.createorderbycarno',
15
- requestType: 'DATA',
16
- attributes: {
17
- businesserCode: @configuration.businesser_code,
18
- parkCode: park_code,
19
- orderType: 'VNP',
20
- carNo: car_no
38
+ def create_order_by_car_no(park_code, car_no)
39
+ payload = {
40
+ "serviceId": "3c.pay.createorderbycarno",
41
+ "requestType": "DATA",
42
+ "attributes": {
43
+ "businesserCode": @configuration.businesser_code,
44
+ "parkCode": park_code,
45
+ "orderType": "VNP",
46
+ "carNo": car_no
21
47
  }
22
- }
23
- @http_client.post_json(@configuration.server_url, headers, hash) do |result|
24
- unless result.successful
25
- message = "Error result : #{result.inspect}"
26
- Jieshun::Parking.logger.error(message)
27
- raise RuntimeError.new(message)
48
+ }.to_json
49
+ unify_call(payload) do |result|
50
+ # 0:正常,正常订单
51
+ # 1:安装验证失败,前端设备异常
52
+ # 2:未入场
53
+ # 5:非临时卡
54
+ # 6:未设置收费标准,前端停车场异常
55
+ # 9:已缴费,超时滞留时间内
56
+ # 10:正常免费时间段内
57
+ # 11:打折免费时间段内
58
+ # 12:打折全免时间段内
59
+ # 13:打折减免时间段内
60
+ # 20:超时收费不能使用卡券
61
+ # 3 1:已入场无需缴费
62
+ # 9999:其它未知错误
63
+ attributes = result.body['dataItems'].first['attributes']
64
+ retcode = attributes['retcode']
65
+ retmsg = attributes['retmsg']
66
+ raise RuntimeError.new(retmsg) if retcode != '0'
67
+ yield(result)
68
+ end
69
+ end
70
+
71
+ def unify_call(payload)
72
+ login_if_required do |auth_token|
73
+ sn = generate_signature("#{payload}#{@configuration.sign_key}")
74
+
75
+ hash = {
76
+ cid: @configuration.cid,
77
+ tn: auth_token,
78
+ v: 2,
79
+ sn: sn,
80
+ p: payload
81
+ }
82
+
83
+ @http_client.post_form("#{@configuration.server_url}/jsaims/as", { }, hash) do |result|
84
+ yield(result)
28
85
  end
29
- result_code = result.body[:resultCode]
30
- if result_code != 0
31
- message = "Error resultCode #{result_code}, body: #{result[:body]}"
32
- Jieshun::Parking.logger.error(message)
33
- raise RuntimeError.new(message)
86
+
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)
34
111
  end
35
- yield(result)
36
112
  end
37
113
  end
38
114
 
@@ -3,11 +3,16 @@ module Jieshun
3
3
 
4
4
  class Configuration
5
5
 
6
- attr_reader :server_url, :businesser_code
6
+ attr_reader :server_url, :businesser_code, :cid, :usr, :psw, :sign_key, :redis_config
7
7
 
8
- def initialize(server_url, businesser_code)
8
+ def initialize(server_url, businesser_code, cid, usr, psw, sign_key, redis_config)
9
9
  @server_url = server_url
10
10
  @businesser_code = businesser_code
11
+ @cid = cid
12
+ @usr = usr
13
+ @psw = psw
14
+ @sign_key = sign_key
15
+ @redis_config = redis_config
11
16
  end
12
17
 
13
18
  end
@@ -0,0 +1,29 @@
1
+ class Retry
2
+
3
+ def self.with_retries(options)
4
+ sleep_seconds = options[:sleep_seconds]
5
+ sleep_seconds ||= 1
6
+ max_tries = options[:max_tries]
7
+ max_tries ||= 10
8
+ tried_times = 0
9
+ begin
10
+ yield
11
+ rescue Exception => e
12
+ if Jieshun::Parking.logger
13
+ Jieshun::Parking.logger.error("Failed to execute operation, business_info: #{options[:business_info]}, error: #{e}")
14
+ end
15
+ if tried_times < max_tries
16
+ sleep(sleep_seconds)
17
+ tried_times = tried_times + 1
18
+ if Jieshun::Parking.logger
19
+ Jieshun::Parking.logger.info("Retrying operation, business_info: #{options[:business_info]}, tried_times: #{tried_times}")
20
+ end
21
+ retry
22
+ else
23
+ Jieshun::Parking.logger.error("Retried #{tried_times} times, aborted.")
24
+ end
25
+ end
26
+ end
27
+
28
+
29
+ end
@@ -4,6 +4,10 @@ module Jieshun
4
4
 
5
5
  class HttpClient
6
6
 
7
+ def post_form(server_url, headers, hash)
8
+ raise NotImplementedError.new("You must implement this method.")
9
+ end
10
+
7
11
  def post_json(server_url, headers, hash)
8
12
  raise NotImplementedError.new("You must implement this method.")
9
13
  end
@@ -7,23 +7,54 @@ module Jieshun
7
7
  require 'uri'
8
8
  require 'json'
9
9
 
10
+ def post_form(server_url, headers, hash)
11
+ post(server_url, 'application/x-www-form-urlencoded', headers, hash) do |result|
12
+ yield(result)
13
+ end
14
+ end
15
+
10
16
  def post_json(server_url, headers, hash)
17
+ post(server_url, 'application/json', headers, hash) do |result|
18
+ yield(result)
19
+ end
20
+ end
21
+
22
+ def post(server_url, content_type, headers, hash)
11
23
  uri = URI.parse(server_url)
12
24
  req = Net::HTTP::Post.new(uri)
13
25
  headers.each { |k, v| req[k] = v }
14
- req["Content-Type"] = "application/json"
26
+ req["Content-Type"] = content_type
15
27
  Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
16
28
  if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
17
- Jieshun::Parking.logger.debug("Jieshun Parking Request #{hash}")
29
+ Jieshun::Parking.logger.debug("Jieshun Parking Request, url: #{server_url}, body: #{JSON.pretty_generate(hash)}")
18
30
  end
19
- req.body = hash.to_json
31
+ if content_type == 'application/json'
32
+ req.body = hash.to_json
33
+ elsif content_type == 'application/x-www-form-urlencoded'
34
+ req.set_form_data(hash)
35
+ else
36
+ raise RuntimeError.new("Unsupported content type #{content_type}")
37
+ end
38
+
20
39
  res = http.request(req)
21
40
  if Jieshun::Parking.debug_mode && Jieshun::Parking.logger
22
- Jieshun::Parking.logger.debug("Jieshun Parking Response #{res}")
41
+ Jieshun::Parking.logger.debug("Jieshun Parking Response #{JSON.pretty_generate(JSON.parse(res.body))}")
23
42
  end
24
43
  successful = res.kind_of?(Net::HTTPSuccess)
44
+ unless successful
45
+ message = "Got error response from jieshun #{res.status}"
46
+ Jieshun::Parking.logger.error(message)
47
+ raise RuntimeError.new(message)
48
+ end
25
49
  json = JSON.parse(res.body)
26
- result = Jieshun::Parking::Result.new(successful, ActiveSupport::HashWithIndifferentAccess.new(json.to_hash))
50
+ result_code = json['resultCode']
51
+ unless result_code.zero?
52
+ message = "Got invalid result code jieshun resultCode: #{result_code}, message: #{json['message']}"
53
+ Jieshun::Parking.logger.error(message)
54
+ raise RuntimeError.new(message)
55
+ end
56
+
57
+ result = Jieshun::Parking::Result.new(successful, json.to_hash)
27
58
  yield result
28
59
  end
29
60
  end
@@ -0,0 +1,40 @@
1
+ require "redis"
2
+
3
+ module Jieshun
4
+ module Parking
5
+ class RedisClient
6
+
7
+ def initialize(redis_config)
8
+ unless $redis
9
+ $redis = Redis.new(redis_config)
10
+ end
11
+ $redis
12
+ end
13
+
14
+ def redis_client
15
+ $redis
16
+ end
17
+
18
+ def redis_set(key, value, expire_time = 60)
19
+ # Rails.logger.debug "redis_client #{redis_client}"
20
+ redis_client.set key, value
21
+ if expire_time > 0
22
+ redis_client.expire key, expire_time
23
+ end
24
+ end
25
+
26
+ def redis_get(key)
27
+ redis_client.get key
28
+ end
29
+
30
+ def redis_del(key)
31
+ redis_client.del key
32
+ end
33
+
34
+ def redis_ttl(key)
35
+ redis_client.ttl key
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jieshun
4
4
  module Parking
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.1"
6
6
  end
7
7
  end
@@ -6,6 +6,8 @@ require_relative "parking/client"
6
6
  require_relative "parking/result"
7
7
  require_relative "parking/http/http_client"
8
8
  require_relative "parking/http/standard_http_client"
9
+ require_relative "parking/redis/redis_client"
10
+ require_relative "parking/helpers/retry"
9
11
  require 'logger'
10
12
 
11
13
 
@@ -13,8 +15,9 @@ module Jieshun
13
15
  module Parking
14
16
  @logger = Logger.new(STDOUT)
15
17
  @debug_mode = true
18
+ @always_login = false
16
19
  class<< self
17
- attr_accessor :logger, :debug_mode
20
+ attr_accessor :logger, :debug_mode, :always_login
18
21
  end
19
22
  end
20
23
  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.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
- - JamesWang
7
+ - LCola
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-09 00:00:00.000000000 Z
11
+ date: 2023-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
27
41
  description: 捷顺停车场 API, 非官方, Provided by 小可乐科技
28
42
  email:
29
43
  - james.wang.z81@gmail.com
@@ -36,8 +50,10 @@ files:
36
50
  - lib/jieshun/parking.rb
37
51
  - lib/jieshun/parking/client.rb
38
52
  - lib/jieshun/parking/configuration.rb
53
+ - lib/jieshun/parking/helpers/retry.rb
39
54
  - lib/jieshun/parking/http/http_client.rb
40
55
  - lib/jieshun/parking/http/standard_http_client.rb
56
+ - lib/jieshun/parking/redis/redis_client.rb
41
57
  - lib/jieshun/parking/result.rb
42
58
  - lib/jieshun/parking/version.rb
43
59
  homepage: http://rubygems.org/gems/jieshun-parking