tochka_cyclops_api 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -8
  3. data/Rakefile +0 -4
  4. data/lib/tasks/methods.rake +11 -0
  5. data/lib/tochka_cyclops_api/data_processor.rb +44 -19
  6. data/lib/tochka_cyclops_api/generators/templates/tochka_cyclops_request_model_template.rb +1 -1
  7. data/lib/tochka_cyclops_api/generators/templates/tochka_cyclops_responses_migration_template.rb +1 -1
  8. data/lib/tochka_cyclops_api/methods.rb +198 -5
  9. data/lib/tochka_cyclops_api/request.rb +66 -31
  10. data/lib/tochka_cyclops_api/response.rb +27 -34
  11. data/lib/tochka_cyclops_api/result.rb +33 -0
  12. data/lib/tochka_cyclops_api/schemas/requests/activate_beneficiary.rb +22 -0
  13. data/lib/tochka_cyclops_api/schemas/requests/create_beneficiary_fl.rb +56 -0
  14. data/lib/tochka_cyclops_api/schemas/requests/create_beneficiary_ip.rb +22 -10
  15. data/lib/tochka_cyclops_api/schemas/requests/create_beneficiary_ul.rb +22 -10
  16. data/lib/tochka_cyclops_api/schemas/requests/deactivate_beneficiary.rb +22 -0
  17. data/lib/tochka_cyclops_api/schemas/requests/echo.rb +2 -0
  18. data/lib/tochka_cyclops_api/schemas/requests/get_beneficiary.rb +22 -0
  19. data/lib/tochka_cyclops_api/schemas/requests/list_beneficiary.rb +44 -0
  20. data/lib/tochka_cyclops_api/schemas/requests/update_beneficiary_fl.rb +51 -0
  21. data/lib/tochka_cyclops_api/schemas/requests/update_beneficiary_ip.rb +39 -0
  22. data/lib/tochka_cyclops_api/schemas/requests/update_beneficiary_ul.rb +38 -0
  23. data/lib/tochka_cyclops_api/schemas/responses/activate_beneficiary.rb +24 -0
  24. data/lib/tochka_cyclops_api/schemas/responses/create_beneficiary_fl.rb +24 -0
  25. data/lib/tochka_cyclops_api/schemas/responses/create_beneficiary_ip.rb +10 -1
  26. data/lib/tochka_cyclops_api/schemas/responses/create_beneficiary_ul.rb +9 -9
  27. data/lib/tochka_cyclops_api/schemas/responses/deactivate_beneficiary.rb +24 -0
  28. data/lib/tochka_cyclops_api/schemas/responses/echo.rb +1 -1
  29. data/lib/tochka_cyclops_api/schemas/responses/error.rb +5 -2
  30. data/lib/tochka_cyclops_api/schemas/responses/get_beneficiary.rb +48 -0
  31. data/lib/tochka_cyclops_api/schemas/responses/list_beneficiary.rb +38 -0
  32. data/lib/tochka_cyclops_api/schemas/responses/update_beneficiary_fl.rb +20 -0
  33. data/lib/tochka_cyclops_api/schemas/responses/update_beneficiary_ip.rb +20 -0
  34. data/lib/tochka_cyclops_api/schemas/responses/update_beneficiary_ul.rb +24 -0
  35. data/lib/tochka_cyclops_api/schemas/results/local_error.rb +0 -0
  36. data/lib/tochka_cyclops_api/test.rb +0 -0
  37. data/lib/tochka_cyclops_api/version.rb +1 -1
  38. data/lib/tochka_cyclops_api.rb +5 -2
  39. metadata +22 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2844cc465020d8597bfa869d80e33d850a2a33c26bd4f302adb7a620a9a71321
4
- data.tar.gz: 35ed83f97f6d37d24d72fdceff93f11ac2057ea8d3df5b20487e9cafeacb1155
3
+ metadata.gz: 36957c52f3476c825762fda41ec211a1a55d7eb15337c3eae48e32cb38d61419
4
+ data.tar.gz: d3d39943258ce772f1a8f949c5bcee9f1abb692d189775b67c0873d2ab98ebd4
5
5
  SHA512:
6
- metadata.gz: 3bf2d583aa03a2e6758e6f5cd9d04a34f97baf307bb83244e07524256b61b7ab94337ac2e05aff8206a10f3ff83a7ecffce77d156c6392879da02b1bd753d447
7
- data.tar.gz: 8a9f1760504c78697fd2e9d9f7691530d7270e0ec9a2cab87bba1611b8dcc88e15eceaff60a297507330b1d09601cfd0f46b819525ab741c48a1edc69f62e103
6
+ metadata.gz: '096c88b4842314462b00977f267448bb6a3ee4043dc0b3d0efd921806f14be7655d43122b2e476216df9775b93fdf2cc214d119f95177c80cc6dad3ab41a43a1'
7
+ data.tar.gz: 9ebfe7d51a013072ddfa6b6ba33dcb767262a93eb1f57fd4c59aa1147422cf4377bcbe1f2683625c6e2d7495b48b348f882c844781fabe8a7c9cb495c1e0a1d0
data/README.md CHANGED
@@ -8,6 +8,7 @@ A simple way to interact with the ["Tochka" bank's api][api_source_page]
8
8
  - [Installation](#installation)
9
9
  - [Settings](#settings)
10
10
  - [Usage](#usage)
11
+ - [Rake tasks](#rake)
11
12
 
12
13
  ## Getting started
13
14
 
@@ -16,19 +17,26 @@ A simple way to interact with the ["Tochka" bank's api][api_source_page]
16
17
  Add this line to your application's Gemfile:
17
18
 
18
19
  ```sh
19
- bundle add tochka_cylops_api
20
+ bundle add tochka_cyclops_api
20
21
  ```
21
22
 
22
- and run commands bellow to create the initializer, models and migrations:
23
+ and run commands bellow to create models, migrations and the initializer:
23
24
 
24
25
  ```sh
25
26
  rails generate tochka_cyclops_api:models
26
27
  rails generate tochka_cyclops_api:initializer
27
28
  ```
28
29
 
30
+ to use rake tasks you should also add the following lines to Rakefile of your Rails project:
31
+
32
+ ```ruby
33
+ spec = Gem::Specification.find_by_name 'tochka_cyclops_api'
34
+ load "#{spec.gem_dir}/lib/tasks/methods.rake"
35
+ ```
36
+
29
37
  ### Settings
30
38
 
31
- You have to set the settings in the initializer file (_config/initializers/healthcheck.rb_):
39
+ You have to set the settings in the initializer file (_config/initializers/tochka_cyclops_api.rb_):
32
40
 
33
41
  ```ruby
34
42
  # frozen_string_literal: true
@@ -50,11 +58,58 @@ TochkaCyclopsApi.send_request(method, data)
50
58
  method - name of the method defined on the bank side point;
51
59
  data - hash of the value required to fulfill the request.
52
60
 
53
- For example:
61
+ There are special rake tasks to get information about available methods:
62
+
63
+ ```sh
64
+ bundle exec rake methods:list
65
+ bundle exec rake methods:desc method=method_name
66
+ ```
67
+
68
+ Examples
69
+ ```sh
70
+ > bundle exec rake methods:list
71
+ # ** Invoke methods:list (first_time)
72
+ # ** Execute methods:list
73
+ # echo
74
+ # create_beneficiary_ul
75
+ # create_beneficiary_ip
76
+ # ...
77
+
78
+ > bundle exec rake methods:desc method=create_beneficiary_ul
79
+ # ** Invoke methods:desc (first_time)
80
+ # ** Execute methods:desc
81
+ # inn | mandatory | string
82
+ # nominal_account_code | optional | string
83
+ # nominal_account_bic | optional | string
84
+ # beneficiary_data | mandatory | {
85
+ # name | mandatory | string
86
+ # kpp | mandatory | string
87
+ # ogrn | optional | string
88
+ # }
89
+ #
90
+ # ================================================================================
91
+ #
92
+ # EXAMPLE
93
+ #
94
+ # {
95
+ # inn: '7743745038',
96
+ # nominal_account_code: '40702810338170022645',
97
+ # nominal_account_bic: '044525225',
98
+ # beneficiary_data: {
99
+ # name: 'ООО «ТК ИнжСтройКомплект»',
100
+ # kpp: '773401001',
101
+ # ogrn: '1097746324169'
102
+ # }
103
+ # }
104
+ ```
105
+
106
+ Example of sending request:
54
107
  ```ruby
55
- TochkaCyclopsApi.send(
56
- inicialize_beneficiary_ul,
57
- {
108
+ TochkaCyclopsApi.send_request(
109
+ # Method contains the name of the TochkaCyclopsApi method
110
+ method: 'create_beneficiary_ul',
111
+ # Data is value for the "params" field of request body
112
+ data: {
58
113
  inn: "7925930371",
59
114
  nominal_account_code: "000000000000000000000",
60
115
  nominal_account_bic: "0000000000",
@@ -62,7 +117,9 @@ TochkaCyclopsApi.send(
62
117
  name: "ООО \"Рога и Копыта\"",
63
118
  kpp: "246301001"
64
119
  }
65
- }
120
+ },
121
+ # Layer have to has one of the following values: :stage, :pre, :prod
122
+ layer: :stage
66
123
  )
67
124
  ```
68
125
 
data/Rakefile CHANGED
@@ -8,7 +8,3 @@ require_relative 'lib/tochka_cyclops_api/methods'
8
8
  RuboCop::RakeTask.new
9
9
 
10
10
  task default: :rubocop
11
-
12
- task :methods do
13
- puts TochkaCyclopsApi::METHODS
14
- end
@@ -0,0 +1,11 @@
1
+ desc "Displays a list of available methods."
2
+
3
+ namespace :methods do
4
+ task :list do
5
+ puts TochkaCyclopsApi::Methods::METHODS
6
+ end
7
+
8
+ task :desc do
9
+ puts TochkaCyclopsApi::Methods.get_method(ENV['method'])
10
+ end
11
+ end
@@ -6,56 +6,81 @@ require 'securerandom'
6
6
  require 'json'
7
7
 
8
8
  require_relative 'request'
9
+ require_relative 'result'
9
10
  require_relative 'schemas/requests/echo'
10
11
 
11
12
  module TochkaCyclopsApi
12
13
  # Module for input data validation and subsequent request invocation
13
- module DataProcessor
14
- def send_request(method, data)
14
+ class DataProcessor
15
+ def self.send_request(method:, data:, layer: )
15
16
  @method = method
16
17
  @data = data
17
- @id = SecureRandom.uuid
18
+ @layer = layer
19
+ @errors = {}
20
+ @url = url_for
21
+ @request_id = SecureRandom.uuid
22
+ schemas
23
+ validation = @request_schema&.call(@data.deep_symbolize_keys)
24
+ @validation_errors = validation&.errors.to_h
18
25
 
19
- return @errors.map { |k, v| [k, v].join(' ') }.join(', ') unless valid_params?
20
-
21
- send_data
26
+ call
22
27
  end
23
28
 
24
29
  private
25
30
 
26
- def valid_params?
27
- if shape
28
- result = shape.call(@data.deep_symbolize_keys)
29
- @errors = result.errors.to_h
31
+ def self.call
32
+ @errors[:url] = "Layer you called for is not exist" if @url.nil?
33
+ @errors[:request_schema] = "Request schema for method #{@method} is not found" if @request_schema.nil?
34
+ @errors[:response_schema] = "Response schema for method #{@method} is not found" if @response_schema.nil?
35
+
36
+ @errors[:validation] = @validation_errors if @request_schemas.present?
37
+
38
+ if @errors.keys.any?
39
+ Result.failure(@errors)
40
+ else
41
+ TochkaCyclopsApi::Request.send_request(method: @method, body: body, url: @url)
30
42
  end
43
+ end
31
44
 
32
- @errors.empty?
45
+ def self.url_for
46
+ {
47
+ stage: 'https://stage.tochka.com/api/v1/cyclops',
48
+ pre: 'https://pre.tochka.com/api/v1/cyclops',
49
+ prod: 'https://api.tochka.com/api/v1/cyclops'
50
+ }.fetch(@layer, nil)
33
51
  end
34
52
 
35
- def send_data
36
- TochkaCyclopsApi::Request.send(body, @method)
53
+ def self.schemas
54
+ @request_schema = request_schema
55
+ @response_schema = response_schema
37
56
  end
38
57
 
39
- def shape
58
+ def self.request_schema
40
59
  require_relative "schemas/requests/#{@method}"
41
60
  schema = ['TochkaCyclopsApi', 'Schemas', 'Requests', camel_case_method].join('::').constantize
42
61
 
43
62
  schema.new
44
63
  rescue => e
45
- @errors = { error: e.message }
46
- false
64
+ nil
65
+ end
66
+
67
+ def self.response_schema
68
+ require_relative "schemas/responses/#{@method}"
69
+ schema = ['TochkaCyclopsApi', 'Schemas', 'Responses', camel_case_method].join('::').constantize
70
+ rescue => e
71
+ nil
47
72
  end
48
73
 
49
- def camel_case_method
74
+ def self.camel_case_method
50
75
  @method.split('_').map(&:capitalize).join
51
76
  end
52
77
 
53
- def body
78
+ def self.body
54
79
  {
55
80
  "jsonrpc": '2.0',
56
81
  "method": @method,
57
82
  "params": @data,
58
- "id": @id
83
+ "id": @request_id
59
84
  }.to_json
60
85
  end
61
86
  end
@@ -3,5 +3,5 @@
3
3
  # RequestModel generator
4
4
  class TochkaCyclopsRequest < ActiveRecord::Base
5
5
  belongs_to :result, polymorphic: true
6
- enum :status, %w[initialized failed finished]
6
+ enum :status, %w[initialized failure success]
7
7
  end
@@ -3,7 +3,7 @@
3
3
  # ResponsesMigration generator
4
4
  class CreateTochkaCyclopsResponses < ActiveRecord::Migration[6.0]
5
5
  def change
6
- create_table :tochka_cyclops_response do |t|
6
+ create_table :tochka_cyclops_responses do |t|
7
7
  t.jsonb :body
8
8
  t.jsonb :result
9
9
  t.timestamps
@@ -1,9 +1,202 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'dry/schema'
4
+
5
+ Undefined = Dry::Schema::Undefined
6
+
7
+ module Types
8
+ include Dry.Types()
9
+ end
10
+
11
+ class DocCompiler
12
+ def visit(node)
13
+ meth, rest = node
14
+ public_send(:"visit_#{meth}", rest)
15
+ end
16
+
17
+ def visit_set(nodes)
18
+ nodes.map { |node| visit(node) }.flatten(1)
19
+ end
20
+
21
+ def visit_and(node)
22
+ left, right = node
23
+ [visit(left), visit(right)].compact
24
+ end
25
+
26
+ def visit_key(node)
27
+ name, rest = node
28
+
29
+ predicates = visit(rest).flatten
30
+
31
+ if predicates[0].is_a? Symbol
32
+ validations = predicate_description(predicates[0], predicates[1])
33
+
34
+ { key: name, validations: validations }
35
+ else
36
+ { key: name, validations: predicates }
37
+ end
38
+ end
39
+
40
+ def visit_implication(node)
41
+ _, right = node.map(&method(:visit))
42
+ right.merge(optional: true)
43
+ end
44
+
45
+ def visit_predicate(node)
46
+ name, args = node
47
+
48
+ return if name.equal?(:key?)
49
+
50
+ { name => args.map(&:last).reject { |v| v.equal?(Dry::Schema::Undefined) } }
51
+ end
52
+
53
+ def predicate_description(name, args)
54
+ case name
55
+ when :str? then "string"
56
+ when :bool? then "true/false"
57
+ when :filled? then "filled"
58
+ when :int? then "integer"
59
+ when :gt? then "greater than #{args[0]}"
60
+ else
61
+ raise NotImplementedError, "#{name} not supported yet"
62
+ end
63
+ end
64
+ end
65
+
3
66
  module TochkaCyclopsApi
4
- METHODS = %w[
5
- echo
6
- create_beneficiary_ul
7
- create_beneficiary_ip
8
- ]
67
+ class Methods
68
+ METHODS = %w[
69
+ echo
70
+ create_beneficiary_ul
71
+ create_beneficiary_ip
72
+ create_beneficiary_fl
73
+ update_beneficiary_ul
74
+ update_beneficiary_ip
75
+ update_beneficiary_fl
76
+ get_beneficiary
77
+ list_beneficiary
78
+ activate_beneficiary
79
+ deactivate_beneficiary
80
+ ]
81
+
82
+ DIVIDER = ["\n", "="*80, "\n"]
83
+
84
+ def self.get_method(method)
85
+ return unless method_exists? method
86
+
87
+ require_relative "schemas/requests/#{method}"
88
+
89
+ @method = method
90
+
91
+ define_schema_class
92
+ define_schema_ast
93
+ parse_schema_ast
94
+ @formatted_schema_ast = format_schema_ast
95
+ show_schema
96
+
97
+ puts @method.split('_').map(&:capitalize).join
98
+ puts @formatted_schema_ast
99
+ puts DIVIDER
100
+ puts ['EXAMPLE', "\n"]
101
+ puts @schema_class.const_get('EXAMPLE')
102
+ end
103
+
104
+ private
105
+
106
+ def self.method_exists?(method)
107
+ return true if method.in? METHODS
108
+
109
+ puts "Method #{method} is not found"
110
+ false
111
+ end
112
+
113
+ def self.define_schema_class
114
+ @schema_class = [
115
+ "TochkaCyclopsApi",
116
+ "Schemas",
117
+ "Requests",
118
+ camel_case(@method)].join('::').constantize
119
+ end
120
+
121
+ def self.define_schema_ast
122
+ @schema_ast = @schema_class.new.schema.ast
123
+ end
124
+
125
+ def self.parse_schema_ast
126
+ compiler = DocCompiler.new
127
+
128
+ @schema_ast = compiler.visit(@schema_ast).map do |row|
129
+ key = row[:key]
130
+ validations = row[:validations]
131
+ optional = row[:optional] ? 'optional' : 'mandatory'
132
+
133
+ if validations.is_a? Array
134
+ validations = validations.map do |validation|
135
+ v_key = validation[:key]
136
+ v_validations = validation[:validations]
137
+ v_optional = validation[:optional] ? 'optional' : 'mandatory'
138
+
139
+ [v_key, v_optional, v_validations]
140
+ end
141
+ end
142
+ [key, optional, validations]
143
+ end
144
+ end
145
+
146
+ def self.column_sizes(array)
147
+ sizes = []
148
+ 3.times do |index|
149
+ size = array.map do |row|
150
+ next if row[index].is_a? Array
151
+
152
+ row[index].to_s.length
153
+ end
154
+ sizes << size.compact.max
155
+ end
156
+ sizes
157
+ end
158
+
159
+ def self.format_schema_ast(array = @schema_ast)
160
+ sizes = column_sizes(array)
161
+ array.map do |sub_array|
162
+ sub_array.each_with_index.map { |row, index| format_row(row, sizes[index]) }
163
+ end
164
+ end
165
+
166
+ def self.format_row(row, indent)
167
+ if row.is_a? Array
168
+ format_schema_ast(row)
169
+ else
170
+ row.to_s.ljust(indent)
171
+ end
172
+ end
173
+
174
+ def self.show_schema
175
+ @formatted_schema_ast.map! do |row|
176
+ array = row.select { |element| element.is_a? Array }.last
177
+ if array.present?
178
+ max_first_element_size = array.map { |row| row[0].strip.to_s.length }.max
179
+
180
+ # 9 is size of 2 dividers (" | ") and 1 brace
181
+ row_indent = row[0].size + row[1].size + 7
182
+
183
+ # 2 is 2 spaces indent
184
+ array.map! do |row|
185
+ row[0] = row[0].rjust(row_indent + max_first_element_size + 2)
186
+ row.join(' | ')
187
+ end
188
+
189
+ array = ["{"] + array + ["}".rjust(row_indent)]
190
+
191
+ row[-1] = array.join("\n")
192
+ end
193
+ row.join(' | ')
194
+ end
195
+ end
196
+
197
+
198
+ def self.camel_case(string)
199
+ string.split('_').map(&:capitalize).join
200
+ end
201
+ end
9
202
  end
@@ -6,53 +6,88 @@ require_relative 'response'
6
6
 
7
7
  module TochkaCyclopsApi
8
8
  # Module for sending requests to the bank's api
9
- module Request
10
- def self.send(body, method)
9
+ class Request
10
+ def self.send_request(body:, method:, url: )
11
11
  @method = method
12
- initialize_request(body)
12
+ @body = body
13
+ @uri = URI(url)
14
+ @request_object = initialize_request_object
15
+ @post_request = initialize_post_request
16
+ @adapter = initialize_adapter
13
17
 
14
- uri = URI('https://pre.tochka.com/api/v1/cyclops/v2/jsonrpc')
15
- http = Net::HTTP.new(uri.host, uri.port)
16
- http.use_ssl = true
18
+ call
19
+ end
17
20
 
18
- request = Net::HTTP::Post.new(uri, {
19
- 'sign-data' => signature(body),
20
- 'sign-thumbprint' => TochkaCyclopsApi.configuration.sign_thumbprint,
21
- 'sign-system' => TochkaCyclopsApi.configuration.sign_system,
22
- 'Content-Type' => 'application/pdf'
23
- })
24
- request.body = body
21
+ private
25
22
 
26
- response = http.request(request)
23
+ def self.call
24
+ get_response
25
+ response = handle_response
27
26
 
28
- case response.code.to_i
29
- when (200..299)
30
- @request.update(status: 'finished')
31
- TochkaCyclopsApi::Response.create(@request, response, method)
32
- when (400..499)
33
- -> { 'Our server error' }[]
27
+ case response[:status]
28
+ when :error
29
+ Result.failure(response[:data])
34
30
  else
35
- @request.update(status: 'failed')
36
- -> { 'Their server error' }[]
31
+ Response.new(request: @request_object, response: response[:data], method: @method)
37
32
  end
38
33
  end
39
34
 
40
- def self.signature(body)
41
- digest = OpenSSL::Digest.new('sha256')
42
- private_key = OpenSSL::PKey::RSA.new(TochkaCyclopsApi.configuration.private_key)
43
- signature_key = private_key.sign(digest, body)
44
- base64_signature = Base64.strict_encode64(signature_key)
45
- base64_signature.gsub("\n", '')
35
+ def self.initialize_adapter
36
+ adapter = Net::HTTP.new(@uri.host, @uri.port)
37
+ adapter.use_ssl = true
38
+ adapter
46
39
  end
47
40
 
48
- def self.initialize_request(body)
49
- @request = TochkaCyclopsRequest.create(
41
+ def self.initialize_request_object
42
+ TochkaCyclopsRequest.create(
50
43
  method: @method,
51
- body: body,
44
+ body: @body,
52
45
  request_identifier: @id,
53
46
  # idempotency_key:
54
47
  status: 'initialized'
55
48
  )
56
49
  end
50
+
51
+ def self.initialize_post_request
52
+ post_request = Net::HTTP::Post.new(@uri, {
53
+ 'sign-data' => signature,
54
+ 'sign-thumbprint' => TochkaCyclopsApi.configuration.sign_thumbprint,
55
+ 'sign-system' => TochkaCyclopsApi.configuration.sign_system,
56
+ 'Content-Type' => 'application/json'
57
+ })
58
+ post_request.body = @body
59
+ post_request
60
+ end
61
+
62
+ def self.get_response
63
+ @response = @adapter.request(@post_request)
64
+ rescue => e
65
+ @error = { request_error: e }
66
+ end
67
+
68
+ def self.handle_response
69
+ return { status: :error, data: @error } if @error
70
+
71
+ status = case @response.code.to_i
72
+ when (200..299)
73
+ {
74
+ status: :ok,
75
+ data: @response
76
+ }
77
+ else
78
+ {
79
+ status: :error,
80
+ data: { request_error: @response }
81
+ }
82
+ end
83
+ end
84
+
85
+ def self.signature
86
+ digest = OpenSSL::Digest.new('sha256')
87
+ private_key = OpenSSL::PKey::RSA.new(TochkaCyclopsApi.configuration.private_key)
88
+ signature_key = private_key.sign(digest, @body)
89
+ base64_signature = Base64.strict_encode64(signature_key)
90
+ base64_signature.gsub("\n", '')
91
+ end
57
92
  end
58
93
  end
@@ -1,63 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'schemas/responses/echo'
3
+ require_relative 'schemas/responses/error'
4
4
 
5
5
  module TochkaCyclopsApi
6
6
  # Class for processing the response received from the api bank
7
7
  class Response
8
- def self.create(request, response, method)
9
- @method = method
8
+ def self.create(request: ,response: ,method:)
10
9
  @request = request
11
- @response = response
12
- parse
10
+ @method = method
11
+ @body = JSON.parse(response.body)
12
+ @response_schema = "TochkaCyclopsApi::Schemas::Responses::#{camel_case_method}".constantize
13
+ @error_schema = 'TochkaCyclopsApi::Schemas::Responses::Error'.constantize
13
14
 
14
- {
15
- response_struct: @response_struct,
16
- result: @result
17
- }
15
+ call
18
16
  end
19
17
 
20
- def self.parse
21
- @body = JSON.parse(@response.body)
22
- if @body.key? 'result'
23
- parse_result
24
- elsif @body.key? 'error'
18
+ private
19
+
20
+ def self.call
21
+ @result = @body['result']
22
+ @error = @body['error']
23
+
24
+ if @error.present?
25
25
  parse_error
26
+ else
27
+ parse_result
26
28
  end
27
29
  end
28
30
 
29
31
  def self.parse_result
30
- @result = @body['result']
31
- response_schema = schema || -> { "Schema for #{@method} is not found" }[]
32
+ return nil if @result.nil?
32
33
 
33
- @response = TochkaCyclopsResponse.create(body: @body, result: @result)
34
- @request.update(result: @response)
34
+ response = TochkaCyclopsResponse.create(body: @body, result: @result)
35
+ @request.update(result: response, status: 'success')
35
36
  @result.deep_symbolize_keys if @result.is_a? Hash
36
- @response_struct = response_schema.new(@result)
37
+ response_struct = @response_schema.new(@result)
38
+
39
+ Result.success(response_struct)
37
40
  end
38
41
 
39
42
  def self.parse_error
40
- @error = @body['error']
41
- require_relative 'schemas/responses/error'
42
- response_schema = 'TochkaCyclopsApi::Schemas::Responses::Error'.constantize
43
+ return nil if @error.nil?
43
44
 
44
- @response = TochkaCyclopsError.create(
45
+ response = TochkaCyclopsError.create(
45
46
  body: @body,
46
47
  code: @error['code'],
47
48
  message: @error['message']
48
49
  )
50
+ @request.update(result: response, status: 'failure')
51
+ response_struct = @error_schema.new(@error.deep_symbolize_keys)
49
52
 
50
- @request.update(result: @response)
51
-
52
- @response_struct = response_schema.new(@error.deep_symbolize_keys)
53
- end
54
-
55
- def self.schema
56
- require_relative "schemas/responses/#{@method}"
57
- "TochkaCyclopsApi::Schemas::Responses::#{camel_case_method}".constantize
58
- rescue StandardError => e
59
- @errors = { error: e.message }
60
- false
53
+ Result.success(response_struct)
61
54
  end
62
55
 
63
56
  def self.camel_case_method