tochka_cyclops_api 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +67 -10
- data/Rakefile +0 -4
- data/lib/tasks/methods.rake +11 -0
- data/lib/tochka_cyclops_api/data_processor.rb +46 -22
- data/lib/tochka_cyclops_api/generators/initializer_generator.rb +5 -5
- data/lib/tochka_cyclops_api/generators/{model_generator.rb → models_generator.rb} +8 -9
- data/lib/tochka_cyclops_api/generators/templates/tochka_cyclops_request_model_template.rb +1 -1
- data/lib/tochka_cyclops_api/generators/templates/tochka_cyclops_responses_migration_template.rb +1 -1
- data/lib/tochka_cyclops_api/methods.rb +198 -5
- data/lib/tochka_cyclops_api/request.rb +66 -31
- data/lib/tochka_cyclops_api/response.rb +27 -34
- data/lib/tochka_cyclops_api/result.rb +33 -0
- data/lib/tochka_cyclops_api/schemas/requests/activate_beneficiary.rb +22 -0
- data/lib/tochka_cyclops_api/schemas/requests/create_beneficiary_fl.rb +56 -0
- data/lib/tochka_cyclops_api/schemas/requests/create_beneficiary_ip.rb +22 -10
- data/lib/tochka_cyclops_api/schemas/requests/create_beneficiary_ul.rb +22 -10
- data/lib/tochka_cyclops_api/schemas/requests/deactivate_beneficiary.rb +22 -0
- data/lib/tochka_cyclops_api/schemas/requests/echo.rb +2 -0
- data/lib/tochka_cyclops_api/schemas/requests/get_beneficiary.rb +22 -0
- data/lib/tochka_cyclops_api/schemas/requests/list_beneficiary.rb +44 -0
- data/lib/tochka_cyclops_api/schemas/requests/update_beneficiary_fl.rb +51 -0
- data/lib/tochka_cyclops_api/schemas/requests/update_beneficiary_ip.rb +39 -0
- data/lib/tochka_cyclops_api/schemas/requests/update_beneficiary_ul.rb +38 -0
- data/lib/tochka_cyclops_api/schemas/responses/activate_beneficiary.rb +24 -0
- data/lib/tochka_cyclops_api/schemas/responses/create_beneficiary_fl.rb +24 -0
- data/lib/tochka_cyclops_api/schemas/responses/create_beneficiary_ip.rb +10 -1
- data/lib/tochka_cyclops_api/schemas/responses/create_beneficiary_ul.rb +9 -9
- data/lib/tochka_cyclops_api/schemas/responses/deactivate_beneficiary.rb +24 -0
- data/lib/tochka_cyclops_api/schemas/responses/echo.rb +1 -1
- data/lib/tochka_cyclops_api/schemas/responses/error.rb +5 -2
- data/lib/tochka_cyclops_api/schemas/responses/get_beneficiary.rb +48 -0
- data/lib/tochka_cyclops_api/schemas/responses/list_beneficiary.rb +38 -0
- data/lib/tochka_cyclops_api/schemas/responses/update_beneficiary_fl.rb +20 -0
- data/lib/tochka_cyclops_api/schemas/responses/update_beneficiary_ip.rb +20 -0
- data/lib/tochka_cyclops_api/schemas/responses/update_beneficiary_ul.rb +24 -0
- data/lib/tochka_cyclops_api/schemas/results/local_error.rb +0 -0
- data/lib/tochka_cyclops_api/test.rb +0 -0
- data/lib/tochka_cyclops_api/version.rb +1 -1
- data/lib/tochka_cyclops_api.rb +8 -2
- metadata +23 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36957c52f3476c825762fda41ec211a1a55d7eb15337c3eae48e32cb38d61419
|
4
|
+
data.tar.gz: d3d39943258ce772f1a8f949c5bcee9f1abb692d189775b67c0873d2ab98ebd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
20
|
+
bundle add tochka_cyclops_api
|
20
21
|
```
|
21
22
|
|
22
|
-
and run commands bellow to create
|
23
|
+
and run commands bellow to create models, migrations and the initializer:
|
23
24
|
|
24
25
|
```sh
|
25
|
-
rails generate
|
26
|
-
rails generate
|
26
|
+
rails generate tochka_cyclops_api:models
|
27
|
+
rails generate tochka_cyclops_api:initializer
|
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"
|
27
35
|
```
|
28
36
|
|
29
37
|
### Settings
|
30
38
|
|
31
|
-
You have to set the settings in the initializer file (_config/initializers/
|
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
|
-
|
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.
|
56
|
-
|
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
@@ -6,57 +6,81 @@ require 'securerandom'
|
|
6
6
|
require 'json'
|
7
7
|
|
8
8
|
require_relative 'request'
|
9
|
-
require_relative '
|
10
|
-
require_relative '
|
9
|
+
require_relative 'result'
|
10
|
+
require_relative 'schemas/requests/echo'
|
11
11
|
|
12
12
|
module TochkaCyclopsApi
|
13
13
|
# Module for input data validation and subsequent request invocation
|
14
|
-
|
15
|
-
def send_request(method
|
14
|
+
class DataProcessor
|
15
|
+
def self.send_request(method:, data:, layer: )
|
16
16
|
@method = method
|
17
17
|
@data = data
|
18
|
-
@
|
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
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
send_data
|
26
|
+
call
|
23
27
|
end
|
24
28
|
|
25
29
|
private
|
26
30
|
|
27
|
-
def
|
28
|
-
if
|
29
|
-
|
30
|
-
|
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)
|
31
42
|
end
|
43
|
+
end
|
32
44
|
|
33
|
-
|
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)
|
34
51
|
end
|
35
52
|
|
36
|
-
def
|
37
|
-
|
53
|
+
def self.schemas
|
54
|
+
@request_schema = request_schema
|
55
|
+
@response_schema = response_schema
|
38
56
|
end
|
39
57
|
|
40
|
-
def
|
41
|
-
require_relative "
|
58
|
+
def self.request_schema
|
59
|
+
require_relative "schemas/requests/#{@method}"
|
42
60
|
schema = ['TochkaCyclopsApi', 'Schemas', 'Requests', camel_case_method].join('::').constantize
|
43
61
|
|
44
62
|
schema.new
|
45
63
|
rescue => e
|
46
|
-
|
47
|
-
|
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
|
48
72
|
end
|
49
73
|
|
50
|
-
def camel_case_method
|
74
|
+
def self.camel_case_method
|
51
75
|
@method.split('_').map(&:capitalize).join
|
52
76
|
end
|
53
77
|
|
54
|
-
def body
|
78
|
+
def self.body
|
55
79
|
{
|
56
80
|
"jsonrpc": '2.0',
|
57
81
|
"method": @method,
|
58
82
|
"params": @data,
|
59
|
-
"id": @
|
83
|
+
"id": @request_id
|
60
84
|
}.to_json
|
61
85
|
end
|
62
86
|
end
|
@@ -2,7 +2,7 @@ require 'rails/generators/base'
|
|
2
2
|
|
3
3
|
module TochkaCyclopsApi
|
4
4
|
module Generators
|
5
|
-
class
|
5
|
+
class InitializerGenerator < Rails::Generators::Base
|
6
6
|
desc 'It creates an initializer to set config data'
|
7
7
|
def create_initializer_file
|
8
8
|
create_file(
|
@@ -11,10 +11,10 @@ module TochkaCyclopsApi
|
|
11
11
|
# frozen_string_literal: true
|
12
12
|
|
13
13
|
TochkaCyclopsApi.configure do |config|
|
14
|
-
config.certificate = File.read(PATH TO TOCHKA CERTIFICATE
|
15
|
-
config.private_key = File.read(PATH TO TOCHKA PRIVATE KEY
|
16
|
-
config.sign_thumbprint = YOUR THUMBPRINT
|
17
|
-
config.sign_system = YOUR SYSTEM
|
14
|
+
config.certificate = File.read() # PATH TO TOCHKA CERTIFICATE
|
15
|
+
config.private_key = File.read() # PATH TO TOCHKA PRIVATE KEY
|
16
|
+
config.sign_thumbprint = '' # YOUR THUMBPRINT
|
17
|
+
config.sign_system = '' # YOUR SYSTEM
|
18
18
|
end
|
19
19
|
TOCHKA_CYCLOPS_API_INITIALIZER_TEXT
|
20
20
|
)
|
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# lib/generators/model_generator.rb
|
4
|
-
|
5
3
|
require 'rails/generators'
|
6
4
|
require 'rails/generators/migration'
|
7
5
|
|
8
|
-
require_relative '
|
9
|
-
require_relative '
|
10
|
-
require_relative '
|
11
|
-
require_relative '
|
12
|
-
require_relative '
|
13
|
-
require_relative '
|
6
|
+
require_relative 'templates/tochka_cyclops_error_model_template'
|
7
|
+
require_relative 'templates/tochka_cyclops_request_model_template'
|
8
|
+
require_relative 'templates/tochka_cyclops_response_model_template'
|
9
|
+
require_relative 'templates/tochka_cyclops_errors_migration_template'
|
10
|
+
require_relative 'templates/tochka_cyclops_requests_migration_template'
|
11
|
+
require_relative 'templates/tochka_cyclops_responses_migration_template'
|
14
12
|
|
15
13
|
module TochkaCyclopsApi
|
16
14
|
module Generators
|
@@ -29,7 +27,8 @@ module TochkaCyclopsApi
|
|
29
27
|
end
|
30
28
|
|
31
29
|
def create_migration_file
|
32
|
-
migration_template 'tochka_cyclops_errors_migration_template.rb',
|
30
|
+
migration_template 'tochka_cyclops_errors_migration_template.rb',
|
31
|
+
'db/migrate/create_tochka_cyclops_errors.rb'
|
33
32
|
migration_template 'tochka_cyclops_requests_migration_template.rb',
|
34
33
|
'db/migrate/create_tochka_cyclops_requests.rb'
|
35
34
|
migration_template 'tochka_cyclops_responses_migration_template.rb',
|
@@ -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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
10
|
-
def self.
|
9
|
+
class Request
|
10
|
+
def self.send_request(body:, method:, url: )
|
11
11
|
@method = method
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
http.use_ssl = true
|
18
|
+
call
|
19
|
+
end
|
17
20
|
|
18
|
-
|
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
|
-
|
23
|
+
def self.call
|
24
|
+
get_response
|
25
|
+
response = handle_response
|
27
26
|
|
28
|
-
case response
|
29
|
-
when
|
30
|
-
|
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
|
-
|
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.
|
41
|
-
|
42
|
-
|
43
|
-
|
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.
|
49
|
-
|
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
|