tochka_cyclops_api 0.3.0 → 0.4.0

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