atol 0.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 +7 -0
- data/.gitignore +44 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +83 -0
- data/LICENSE +21 -0
- data/README.md +211 -0
- data/Rakefile +9 -0
- data/atol-rb.gemspec +30 -0
- data/lib/atol.rb +18 -0
- data/lib/atol/config.rb +19 -0
- data/lib/atol/errors.rb +48 -0
- data/lib/atol/request.rb +3 -0
- data/lib/atol/request/get_document_state.rb +26 -0
- data/lib/atol/request/get_token.rb +39 -0
- data/lib/atol/request/post_document.rb +51 -0
- data/lib/atol/request/post_document/item/body.rb +30 -0
- data/lib/atol/request/post_document/sell/body.rb +65 -0
- data/lib/atol/transaction.rb +3 -0
- data/lib/atol/transaction/get_document_state.rb +33 -0
- data/lib/atol/transaction/get_token.rb +38 -0
- data/lib/atol/transaction/post_document.rb +40 -0
- data/lib/atol/version.rb +6 -0
- metadata +151 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: a35130c2b24a2235ab61ca8135a28607468376cc
|
|
4
|
+
data.tar.gz: f632f78dd9e2ac5899a8a63afc0b49039b110e02
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 02c9af08ea790284f7978c6d2d13de131fc70c9043282001aadcd2cb9b61afa7a696269020d066f2954b160cb913ce578e1f4b7c273fe95b172e8b2c30f2e452
|
|
7
|
+
data.tar.gz: 49f616f868970df6decce8cbd327daa785fd41bb3b7957f73dc37222caeb10f7c6205dfae85529392c89466922941e8ecb2031841a8abf89bd168773909a2077
|
data/.gitignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
*.rbc
|
|
2
|
+
capybara-*.html
|
|
3
|
+
/log
|
|
4
|
+
/tmp
|
|
5
|
+
/db/*.sqlite3
|
|
6
|
+
/db/*.sqlite3-journal
|
|
7
|
+
/public/system
|
|
8
|
+
/coverage/
|
|
9
|
+
/spec/tmp
|
|
10
|
+
*.orig
|
|
11
|
+
rerun.txt
|
|
12
|
+
pickle-email-*.html
|
|
13
|
+
.idea
|
|
14
|
+
|
|
15
|
+
# TODO Comment out this rule if you are OK with secrets being uploaded to the repo
|
|
16
|
+
config/initializers/secret_token.rb
|
|
17
|
+
|
|
18
|
+
# Only include if you have production secrets in this file, which is no longer a Rails default
|
|
19
|
+
# config/secrets.yml
|
|
20
|
+
|
|
21
|
+
# dotenv
|
|
22
|
+
# TODO Comment out this rule if environment variables can be committed
|
|
23
|
+
.env
|
|
24
|
+
|
|
25
|
+
## Environment normalization:
|
|
26
|
+
/.bundle
|
|
27
|
+
/vendor/bundle
|
|
28
|
+
|
|
29
|
+
# these should all be checked in to normalize the environment:
|
|
30
|
+
# Gemfile.lock, .ruby-version, .ruby-gemset
|
|
31
|
+
|
|
32
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
33
|
+
.rvmrc
|
|
34
|
+
|
|
35
|
+
# if using bower-rails ignore default bower_components path bower.json files
|
|
36
|
+
/vendor/assets/bower_components
|
|
37
|
+
*.bowerrc
|
|
38
|
+
bower.json
|
|
39
|
+
|
|
40
|
+
# Ignore pow environment settings
|
|
41
|
+
.powenv
|
|
42
|
+
|
|
43
|
+
# Ignore Byebug command history file.
|
|
44
|
+
.byebug_history
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper --format documentation --color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
atol (0.1)
|
|
5
|
+
anyway_config (~> 1.0)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
addressable (2.5.2)
|
|
11
|
+
public_suffix (>= 2.0.2, < 4.0)
|
|
12
|
+
anyway_config (1.1.3)
|
|
13
|
+
ast (2.3.0)
|
|
14
|
+
coveralls (0.8.21)
|
|
15
|
+
json (>= 1.8, < 3)
|
|
16
|
+
simplecov (~> 0.14.1)
|
|
17
|
+
term-ansicolor (~> 1.3)
|
|
18
|
+
thor (~> 0.19.4)
|
|
19
|
+
tins (~> 1.6)
|
|
20
|
+
crack (0.4.3)
|
|
21
|
+
safe_yaml (~> 1.0.0)
|
|
22
|
+
diff-lcs (1.3)
|
|
23
|
+
docile (1.1.5)
|
|
24
|
+
hashdiff (0.3.7)
|
|
25
|
+
json (2.1.0)
|
|
26
|
+
parallel (1.12.1)
|
|
27
|
+
parser (2.4.0.2)
|
|
28
|
+
ast (~> 2.3)
|
|
29
|
+
powerpack (0.1.1)
|
|
30
|
+
public_suffix (3.0.1)
|
|
31
|
+
rainbow (3.0.0)
|
|
32
|
+
rake (10.5.0)
|
|
33
|
+
rspec (3.7.0)
|
|
34
|
+
rspec-core (~> 3.7.0)
|
|
35
|
+
rspec-expectations (~> 3.7.0)
|
|
36
|
+
rspec-mocks (~> 3.7.0)
|
|
37
|
+
rspec-core (3.7.1)
|
|
38
|
+
rspec-support (~> 3.7.0)
|
|
39
|
+
rspec-expectations (3.7.0)
|
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
41
|
+
rspec-support (~> 3.7.0)
|
|
42
|
+
rspec-mocks (3.7.0)
|
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
44
|
+
rspec-support (~> 3.7.0)
|
|
45
|
+
rspec-support (3.7.0)
|
|
46
|
+
rubocop (0.52.1)
|
|
47
|
+
parallel (~> 1.10)
|
|
48
|
+
parser (>= 2.4.0.2, < 3.0)
|
|
49
|
+
powerpack (~> 0.1)
|
|
50
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
51
|
+
ruby-progressbar (~> 1.7)
|
|
52
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
53
|
+
ruby-progressbar (1.9.0)
|
|
54
|
+
safe_yaml (1.0.4)
|
|
55
|
+
simplecov (0.14.1)
|
|
56
|
+
docile (~> 1.1.0)
|
|
57
|
+
json (>= 1.8, < 3)
|
|
58
|
+
simplecov-html (~> 0.10.0)
|
|
59
|
+
simplecov-html (0.10.2)
|
|
60
|
+
term-ansicolor (1.6.0)
|
|
61
|
+
tins (~> 1.0)
|
|
62
|
+
thor (0.19.4)
|
|
63
|
+
tins (1.16.3)
|
|
64
|
+
unicode-display_width (1.3.0)
|
|
65
|
+
webmock (3.2.1)
|
|
66
|
+
addressable (>= 2.3.6)
|
|
67
|
+
crack (>= 0.3.2)
|
|
68
|
+
hashdiff
|
|
69
|
+
|
|
70
|
+
PLATFORMS
|
|
71
|
+
ruby
|
|
72
|
+
|
|
73
|
+
DEPENDENCIES
|
|
74
|
+
atol!
|
|
75
|
+
bundler (~> 1.15)
|
|
76
|
+
coveralls
|
|
77
|
+
rake (~> 10.0)
|
|
78
|
+
rspec (~> 3.0)
|
|
79
|
+
rubocop (~> 0.52)
|
|
80
|
+
webmock (~> 3.0)
|
|
81
|
+
|
|
82
|
+
BUNDLED WITH
|
|
83
|
+
1.15.1
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 George
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+

|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
[](https://travis-ci.org/GeorgeGorbanev/atol-rb) [](https://codeclimate.com/github/GeorgeGorbanev/atol-rb/maintainability) [](https://coveralls.io/github/GeorgeGorbanev/atol-rb?branch=master)
|
|
5
|
+
|
|
6
|
+
# atol-rb
|
|
7
|
+
|
|
8
|
+
Пакет содержит набор классов для работы с [KaaS-сервисом АТОЛ-онлайн](https://online.atol.ru/) по [описанному протоколу](https://online.atol.ru/files/%D0%90%D0%A2%D0%9E%D0%9B%20%D0%9E%D0%BD%D0%BB%D0%B0%D0%B8%CC%86%D0%BD._%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB%D0%B0.pdf).
|
|
9
|
+
|
|
10
|
+
##### Совместимость
|
|
11
|
+
|
|
12
|
+
Для корректной работы необходим интерпретатор Руби версии 2.2 и выше. Пакет работает с версией протокола v3.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Использование
|
|
16
|
+
|
|
17
|
+
### Установка пакета
|
|
18
|
+
|
|
19
|
+
Необходимо добавить в Gemfile проекта строчку:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
gem 'weekends'
|
|
23
|
+
```
|
|
24
|
+
И запустить команду:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
$ bundle install
|
|
28
|
+
```
|
|
29
|
+
### Конфигурация
|
|
30
|
+
|
|
31
|
+
Для обращения к сервису необходимы данные учетной записи.
|
|
32
|
+
|
|
33
|
+
При инициализации приложение попытается найти необходимые параметры в константе ENV.
|
|
34
|
+
|
|
35
|
+
Для корректной инициализации потребуются следующие переменные окружения:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# .env
|
|
39
|
+
ATOL_INN=123456789010
|
|
40
|
+
ATOL_LOGIN=example-login
|
|
41
|
+
ATOL_PASSWORD=example-password
|
|
42
|
+
ATOL_PAYMENT_ADDRESS="г. Москва, ул. Ленина, д.1 к.2"
|
|
43
|
+
ATOL_GROUP_CODE=example-group-code
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Для Rails-приложений так же можно создать файл инициализации и задать параметры непосредственно в коде:
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
# config/initializers/atol.rb
|
|
51
|
+
|
|
52
|
+
Rails.application.config.after_initialize do
|
|
53
|
+
Atol.config.tap do |config|
|
|
54
|
+
config.inn = '123456789010'
|
|
55
|
+
config.login = 'example-login'
|
|
56
|
+
config.password = 'example-password'
|
|
57
|
+
config.payment_address = 'г. Москва, ул. Ленина, д.1 к.2'
|
|
58
|
+
config.group_code = 'example-group-code'
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Для класса конфигурации используется класс из гема [anyway-config](https://github.com/palkan/anyway_config). Другие способы задания конфигурации можно найти в его документации.
|
|
64
|
+
|
|
65
|
+
### Получение токена
|
|
66
|
+
|
|
67
|
+
Для создания документа в системе АТОЛ необходимо получить токен авторизации. Вот как это можно сделать:
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
token = Atol::Transaction::GetToken.new.call
|
|
71
|
+
# => 'example-token-string'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Токен можно будет использовать в течение 24 часов после первого запроса.
|
|
75
|
+
|
|
76
|
+
Сервис АТОЛ не предоставляет информации о сроке жизни токена, поэтому его механизм его кеширования полностью зависит от приложения.
|
|
77
|
+
|
|
78
|
+
### Регистрация документа
|
|
79
|
+
|
|
80
|
+
#### Создание тела запроса
|
|
81
|
+
|
|
82
|
+
Тело запроса должно соответствовать схеме. Для упрощения кода создан класс `Atol::Request::PostDocument::Sell::Body`.
|
|
83
|
+
|
|
84
|
+
Конструктор в качестве обязательных аргументов принимает `external_id`, один из аргументов `phone` или `email` и `items`.
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
body = Atol::Request::PostDocument::Sell::Body.new(
|
|
88
|
+
external_id: 123,
|
|
89
|
+
email: 'example@example.com',
|
|
90
|
+
items: [
|
|
91
|
+
...
|
|
92
|
+
]
|
|
93
|
+
).to_json
|
|
94
|
+
```
|
|
95
|
+
Массив `items` должен включать в себя объекты, которые так же соответствуют схеме.
|
|
96
|
+
|
|
97
|
+
Для создания `items` можно использовать класс `Atol::Request::PostDocument::Item::Body`.
|
|
98
|
+
|
|
99
|
+
Его конструктор принимает обязательные аргументы `name`, `price` и опциональный `quantity` (по умолчанию 1).
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
item = Atol::Request::PostDocument::Item::Body.new(
|
|
103
|
+
name: 'product name',
|
|
104
|
+
price: 100,
|
|
105
|
+
quantity: 2
|
|
106
|
+
).to_h
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Тогда создание всего тела запроса будет выглядеть так:
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
body = Atol::Request::PostDocument::Sell::Body.new(
|
|
113
|
+
external_id: 123,
|
|
114
|
+
email: 'example@example.com',
|
|
115
|
+
items: [
|
|
116
|
+
Atol::Request::PostDocument::Item::Body.new(
|
|
117
|
+
name: 'number 9',
|
|
118
|
+
price: 50,
|
|
119
|
+
quantity: 2
|
|
120
|
+
).to_h,
|
|
121
|
+
Atol::Request::PostDocument::Item::Body.new(
|
|
122
|
+
name: 'number 9 large',
|
|
123
|
+
price: 100
|
|
124
|
+
).to_h,
|
|
125
|
+
Atol::Request::PostDocument::Item::Body.new(
|
|
126
|
+
name: 'number 6',
|
|
127
|
+
price: 60
|
|
128
|
+
).to_h
|
|
129
|
+
]
|
|
130
|
+
).to_json
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Результат:
|
|
134
|
+
```json
|
|
135
|
+
|
|
136
|
+
{
|
|
137
|
+
"receipt":{
|
|
138
|
+
"attributes":{
|
|
139
|
+
"sno":"usn_income_outcome",
|
|
140
|
+
"email":"example@example.com"
|
|
141
|
+
},
|
|
142
|
+
"items":[
|
|
143
|
+
{
|
|
144
|
+
"name":"number 9",
|
|
145
|
+
"price":50.0,
|
|
146
|
+
"quantity":2.0,
|
|
147
|
+
"sum":100.0,
|
|
148
|
+
"tax":"none"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name":"number 9 large",
|
|
152
|
+
"price":100.0,
|
|
153
|
+
"quantity":1.0,
|
|
154
|
+
"sum":100.0,
|
|
155
|
+
"tax":"none"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name":"number 6",
|
|
159
|
+
"price":60.0,
|
|
160
|
+
"quantity":1.0,
|
|
161
|
+
"sum":60.0,
|
|
162
|
+
"tax":"none"
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
"payments":[
|
|
166
|
+
{
|
|
167
|
+
"sum":260.0,
|
|
168
|
+
"type":1
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"total":260.0
|
|
172
|
+
},
|
|
173
|
+
"service":{
|
|
174
|
+
"inn":"123456789010",
|
|
175
|
+
"payment_address":"г. Москва, ул. Ленина, д.1 к.2"
|
|
176
|
+
},
|
|
177
|
+
"timestamp":"06.02.2018 12:35:00",
|
|
178
|
+
"external_id":123
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
#### Отправка документа
|
|
183
|
+
|
|
184
|
+
Когда токен и тело запроса составлены, остается только сделать post-запрос.
|
|
185
|
+
|
|
186
|
+
Для этого используем класс `Atol::Transaction::PostDocument`, принимающий название операции, токен и тело запроса:
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
Atol::Transaction::PostDocument.new(
|
|
190
|
+
operation: :sell,
|
|
191
|
+
token: token,
|
|
192
|
+
body: body
|
|
193
|
+
).call
|
|
194
|
+
```
|
|
195
|
+
Объект возьмет на себя составление URL, добавит необходимые параметры из конфигурации, отправит запрос и вернет объект http-ответа.
|
|
196
|
+
|
|
197
|
+
В случае возникновения ошибок он вернет исключение специальных классов.
|
|
198
|
+
|
|
199
|
+
Для логгирования конструктор принимает необязательные аргументы `req_logger` и `res_logger`.
|
|
200
|
+
|
|
201
|
+
Этими аргументами должны быть объекты, отвечающие на `#call` и принимающие один аргумент, объект запроса или ответа:
|
|
202
|
+
|
|
203
|
+
```Ruby
|
|
204
|
+
Atol::Transaction::PostDocument.new(
|
|
205
|
+
operation: :sell,
|
|
206
|
+
token: token,
|
|
207
|
+
body: body,
|
|
208
|
+
req_logger: lambda { |req| puts req.body },
|
|
209
|
+
res_logger: lambda { |res| puts res.body }
|
|
210
|
+
).call
|
|
211
|
+
```
|
data/Rakefile
ADDED
data/atol-rb.gemspec
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require 'atol/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'atol'
|
|
7
|
+
spec.version = Atol::Version::LIB
|
|
8
|
+
spec.authors = ['GeorgeGorbanev']
|
|
9
|
+
spec.email = ['GeorgeGorbanev@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'ATOL KaaS client for Ruby'
|
|
12
|
+
spec.homepage = 'https://github.com/GeorgeGorbanev/atol-rb'
|
|
13
|
+
spec.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
spec.bindir = 'exe'
|
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
21
|
+
spec.require_paths = ['lib']
|
|
22
|
+
|
|
23
|
+
spec.add_dependency 'anyway_config', '~> 1.0'
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.52'
|
|
29
|
+
spec.add_development_dependency 'webmock', '~> 3.0'
|
|
30
|
+
end
|
data/lib/atol.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'atol/version'
|
|
2
|
+
require 'atol/config'
|
|
3
|
+
require 'atol/request'
|
|
4
|
+
require 'atol/transaction'
|
|
5
|
+
|
|
6
|
+
module Atol
|
|
7
|
+
URL = "http://online.atol.ru/possystem/#{Atol::Version::API}".freeze
|
|
8
|
+
ENCODING = 'utf-8'.freeze
|
|
9
|
+
TIMESTAMP_FORMAT = '%d.%m.%Y %H:%M:%S'.freeze
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_writer :config
|
|
13
|
+
|
|
14
|
+
def config
|
|
15
|
+
@config ||= Atol::Config.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/atol/config.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'anyway'
|
|
2
|
+
|
|
3
|
+
module Atol
|
|
4
|
+
class Config < Anyway::Config
|
|
5
|
+
DEFAULT_REQ_TRIES_NUMBER = 3
|
|
6
|
+
DEFAULT_PAYMENT_TYPE = 1
|
|
7
|
+
|
|
8
|
+
attr_config :login,
|
|
9
|
+
:password,
|
|
10
|
+
:inn,
|
|
11
|
+
:group_code,
|
|
12
|
+
:payment_address,
|
|
13
|
+
:default_sno,
|
|
14
|
+
:default_tax,
|
|
15
|
+
:callback_url,
|
|
16
|
+
req_tries_number: DEFAULT_REQ_TRIES_NUMBER,
|
|
17
|
+
default_payment_type: DEFAULT_PAYMENT_TYPE
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/atol/errors.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Atol
|
|
2
|
+
class MissingConfigError < StandardError; end
|
|
3
|
+
class AuthBadRequestError < StandardError; end
|
|
4
|
+
class AuthUserOrPasswordError < StandardError; end
|
|
5
|
+
class ConfigExpectedError < StandardError; end
|
|
6
|
+
class UnknownOperationError < StandardError; end
|
|
7
|
+
class BadJSONError < StandardError; end
|
|
8
|
+
class IncomingBadRequestError < StandardError; end
|
|
9
|
+
class IncomingOperationNotSupportError < StandardError; end
|
|
10
|
+
class IncomingMissingTokenError < StandardError; end
|
|
11
|
+
class IncomingNotExistTokenError < StandardError; end
|
|
12
|
+
class IncomingExpiredTokenError < StandardError; end
|
|
13
|
+
class IncomingExistExternalIdError < StandardError; end
|
|
14
|
+
class GroupCodeToTokenError < StandardError; end
|
|
15
|
+
class IsNullExternalIdError < StandardError; end
|
|
16
|
+
class EmptyClientContactError < StandardError; end
|
|
17
|
+
class EmptySellItemsError < StandardError; end
|
|
18
|
+
class IncomingQueueTimeoutError < StandardError; end
|
|
19
|
+
class IncomingValidationError < StandardError; end
|
|
20
|
+
class IncomingQueueError < StandardError; end
|
|
21
|
+
class StateBadRequestError < StandardError; end
|
|
22
|
+
class StateMissingTokenError < StandardError; end
|
|
23
|
+
class StateNotExistTokenError < StandardError; end
|
|
24
|
+
class StateExpiredTokenError < StandardError; end
|
|
25
|
+
class StateMissingUuidError < StandardError; end
|
|
26
|
+
class StateNotFoundError < StandardError; end
|
|
27
|
+
|
|
28
|
+
ERRORS = Hash[
|
|
29
|
+
1 => BadJSONError,
|
|
30
|
+
2 => IncomingBadRequestError,
|
|
31
|
+
3 => IncomingOperationNotSupportError,
|
|
32
|
+
4 => IncomingMissingTokenError,
|
|
33
|
+
5 => IncomingNotExistTokenError,
|
|
34
|
+
6 => IncomingExpiredTokenError,
|
|
35
|
+
7 => IncomingQueueTimeoutError,
|
|
36
|
+
8 => IncomingValidationError,
|
|
37
|
+
9 => IncomingQueueError,
|
|
38
|
+
10 => IncomingExistExternalIdError,
|
|
39
|
+
11 => StateBadRequestError,
|
|
40
|
+
12 => StateMissingTokenError,
|
|
41
|
+
13 => StateNotExistTokenError,
|
|
42
|
+
14 => StateExpiredTokenError,
|
|
43
|
+
15 => StateMissingUuidError,
|
|
44
|
+
16 => StateNotFoundError,
|
|
45
|
+
22 => GroupCodeToTokenError,
|
|
46
|
+
23 => IsNullExternalIdError
|
|
47
|
+
].freeze
|
|
48
|
+
end
|
data/lib/atol/request.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'atol'
|
|
2
|
+
require 'atol/errors'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
|
|
5
|
+
module Atol
|
|
6
|
+
module Request
|
|
7
|
+
class GetDocumentState
|
|
8
|
+
def initialize(uuid:, token:, config: nil)
|
|
9
|
+
@config = config || Atol.config
|
|
10
|
+
raise(Atol::ConfigExpectedError) unless @config.is_a?(Atol::Config)
|
|
11
|
+
raise(Atol::MissingConfigError, 'group_code missing') if @config.group_code.nil?
|
|
12
|
+
|
|
13
|
+
@url = "#{Atol::URL}/#{@config.group_code}/report/#{uuid}?tokenid=#{token}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
uri = URI(url)
|
|
18
|
+
Net::HTTP.get_response(uri)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_reader :url
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'atol'
|
|
2
|
+
require 'atol/errors'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
|
|
5
|
+
module Atol
|
|
6
|
+
module Request
|
|
7
|
+
class GetToken
|
|
8
|
+
PATH = '/getToken'.freeze
|
|
9
|
+
|
|
10
|
+
def initialize(config: nil)
|
|
11
|
+
@config = config || Atol.config
|
|
12
|
+
raise(Atol::ConfigExpectedError) unless @config.is_a?(Atol::Config)
|
|
13
|
+
|
|
14
|
+
if @config.login.nil? || @config.login.empty?
|
|
15
|
+
raise(Atol::MissingConfigError, 'login missing')
|
|
16
|
+
else
|
|
17
|
+
@login = @config.login
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if @config.password.nil? || @config.login.empty?
|
|
21
|
+
raise(Atol::MissingConfigError, 'password missing')
|
|
22
|
+
else
|
|
23
|
+
@password = @config.password
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def call
|
|
28
|
+
uri = URI(Atol::URL + PATH)
|
|
29
|
+
uri.query = URI.encode_www_form(login: login, pass: password)
|
|
30
|
+
|
|
31
|
+
Net::HTTP.get_response(uri)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
attr_reader :login, :password
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'atol'
|
|
2
|
+
require 'atol/errors'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'atol/request/post_document/item/body'
|
|
5
|
+
require 'atol/request/post_document/sell/body'
|
|
6
|
+
|
|
7
|
+
module Atol
|
|
8
|
+
module Request
|
|
9
|
+
class PostDocument
|
|
10
|
+
OPERATIONS = %i[sell sell_refund sell_correction buy buy_refund buy_correction].freeze
|
|
11
|
+
HEADERS = { 'Content-Type' => 'application/json' }.freeze
|
|
12
|
+
|
|
13
|
+
def initialize(operation:, token:, body:, config: nil, req_logger: nil, res_logger: nil)
|
|
14
|
+
@config = config || Atol.config
|
|
15
|
+
|
|
16
|
+
raise(Atol::ConfigExpectedError) unless @config.is_a?(Atol::Config)
|
|
17
|
+
raise(Atol::MissingConfigError, 'group_code missing') if @config.group_code.empty?
|
|
18
|
+
raise(Atol::UnknownOperationError, operation.to_s) unless OPERATIONS.include?(operation.to_sym)
|
|
19
|
+
|
|
20
|
+
@url = "#{Atol::URL}/#{@config.group_code}/#{operation}?tokenid=#{token}"
|
|
21
|
+
@body = body
|
|
22
|
+
@req_logger = req_logger
|
|
23
|
+
@res_logger = res_logger
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def call
|
|
27
|
+
uri = URI(url)
|
|
28
|
+
req = Net::HTTP::Post.new(uri, HEADERS)
|
|
29
|
+
req.body = body
|
|
30
|
+
|
|
31
|
+
if req_logger.respond_to?(:call)
|
|
32
|
+
req_logger.call(req)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
|
36
|
+
http.request(req)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if res_logger.respond_to?(:call)
|
|
40
|
+
res_logger.call(res)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
res
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
attr_reader :url, :body, :req_logger, :res_logger
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'atol/errors'
|
|
2
|
+
|
|
3
|
+
module Atol
|
|
4
|
+
module Request
|
|
5
|
+
class PostDocument
|
|
6
|
+
module Item
|
|
7
|
+
class Body
|
|
8
|
+
def initialize(name:, price:, quantity: 1, config: nil)
|
|
9
|
+
@config = config || Atol.config
|
|
10
|
+
|
|
11
|
+
@body = Hash[]
|
|
12
|
+
@body[:name] = name
|
|
13
|
+
@body[:price] = price.to_f
|
|
14
|
+
@body[:quantity] = quantity.to_f
|
|
15
|
+
@body[:sum] = @body[:price] * @body[:quantity]
|
|
16
|
+
@body[:tax] = @config.default_tax
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_h
|
|
20
|
+
body.clone
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
attr_reader :body
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'atol/errors'
|
|
2
|
+
|
|
3
|
+
module Atol
|
|
4
|
+
module Request
|
|
5
|
+
class PostDocument
|
|
6
|
+
module Sell
|
|
7
|
+
class Body
|
|
8
|
+
def initialize(external_id:, phone: '', email: '', items:, config: nil)
|
|
9
|
+
raise(Atol::EmptyClientContactError) if phone.empty? && email.empty?
|
|
10
|
+
raise(Atol::EmptySellItemsError) if items.empty?
|
|
11
|
+
@config = config || Atol.config
|
|
12
|
+
|
|
13
|
+
@body = body_template
|
|
14
|
+
@body[:external_id] = external_id
|
|
15
|
+
@body[:receipt][:attributes][:email] = email unless email.empty?
|
|
16
|
+
@body[:receipt][:attributes][:phone] = phone unless phone.empty?
|
|
17
|
+
@body[:service][:callback_url] = @config.callback_url if @config.callback_url
|
|
18
|
+
|
|
19
|
+
total = items.inject(0) do |sum, item|
|
|
20
|
+
sum += item[:sum]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@body[:receipt][:total] = @body[:receipt][:payments][0][:sum] = total
|
|
24
|
+
@body[:receipt][:items] = items
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_h
|
|
28
|
+
body.clone
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_json
|
|
32
|
+
body.to_json
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
attr_reader :config, :body
|
|
38
|
+
|
|
39
|
+
def body_template
|
|
40
|
+
Hash[
|
|
41
|
+
receipt: {
|
|
42
|
+
attributes: {
|
|
43
|
+
sno: config.default_sno
|
|
44
|
+
},
|
|
45
|
+
items: [],
|
|
46
|
+
payments: [
|
|
47
|
+
{
|
|
48
|
+
sum: 0,
|
|
49
|
+
type: config.default_payment_type
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
service: {
|
|
54
|
+
inn: config.inn,
|
|
55
|
+
payment_address: config.payment_address
|
|
56
|
+
},
|
|
57
|
+
timestamp: Time.now.strftime(Atol::TIMESTAMP_FORMAT),
|
|
58
|
+
total: 0
|
|
59
|
+
]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'atol/request/get_document_state'
|
|
2
|
+
require 'atol/errors'
|
|
3
|
+
|
|
4
|
+
module Atol
|
|
5
|
+
module Transaction
|
|
6
|
+
class GetDocumentState
|
|
7
|
+
def initialize(uuid:, token:, config: nil)
|
|
8
|
+
@config = config || Atol.config
|
|
9
|
+
raise(Atol::ConfigExpectedError) unless @config.is_a?(Atol::Config)
|
|
10
|
+
@params = Hash[uuid: uuid, token: token, config: @config]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
request = Atol::Request::GetDocumentState.new(params)
|
|
15
|
+
response = request.call
|
|
16
|
+
encoded_body = response.body.force_encoding(Atol::ENCODING)
|
|
17
|
+
json = JSON.parse(encoded_body)
|
|
18
|
+
|
|
19
|
+
if response.code == '200' && json['error'].nil?
|
|
20
|
+
json
|
|
21
|
+
elsif Atol::ERRORS[json['error']['code']]
|
|
22
|
+
raise(Atol::ERRORS[json['error']['code']], encoded_body)
|
|
23
|
+
else
|
|
24
|
+
raise(encoded_body)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
attr_reader :params
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'atol/request/get_token'
|
|
2
|
+
require 'atol/errors'
|
|
3
|
+
|
|
4
|
+
module Atol
|
|
5
|
+
module Transaction
|
|
6
|
+
class GetToken
|
|
7
|
+
def initialize(config: nil)
|
|
8
|
+
@config = config || Atol.config
|
|
9
|
+
raise(Atol::ConfigExpectedError) unless @config.is_a?(Atol::Config)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
@config.req_tries_number.times do |i|
|
|
14
|
+
request = Atol::Request::GetToken.new(config: @config)
|
|
15
|
+
response = request.call
|
|
16
|
+
encoded_body = response.body.encode(Atol::ENCODING)
|
|
17
|
+
json = JSON.parse(encoded_body)
|
|
18
|
+
|
|
19
|
+
case response.code
|
|
20
|
+
when '200'
|
|
21
|
+
return json['token']
|
|
22
|
+
when '400'
|
|
23
|
+
case json['code']
|
|
24
|
+
when 19
|
|
25
|
+
raise Atol::AuthUserOrPasswordError
|
|
26
|
+
when 17
|
|
27
|
+
raise Atol::AuthBadRequestError
|
|
28
|
+
end
|
|
29
|
+
when '500'
|
|
30
|
+
next
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
raise "#{response.code} #{response.body}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'atol/request/post_document'
|
|
2
|
+
require 'atol/errors'
|
|
3
|
+
|
|
4
|
+
module Atol
|
|
5
|
+
module Transaction
|
|
6
|
+
class PostDocument
|
|
7
|
+
def initialize(operation:, token:, body:, config: nil, req_logger: nil, res_logger: nil)
|
|
8
|
+
@config = config || Atol.config
|
|
9
|
+
raise(Atol::ConfigExpectedError) unless @config.is_a?(Atol::Config)
|
|
10
|
+
@params = Hash[
|
|
11
|
+
operation: operation,
|
|
12
|
+
token: token,
|
|
13
|
+
body: body,
|
|
14
|
+
config: config,
|
|
15
|
+
req_logger: req_logger,
|
|
16
|
+
res_logger: res_logger
|
|
17
|
+
]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def call
|
|
21
|
+
request = Atol::Request::PostDocument.new(params)
|
|
22
|
+
response = request.call
|
|
23
|
+
encoded_body = response.body.force_encoding(Atol::ENCODING)
|
|
24
|
+
json = JSON.parse(encoded_body)
|
|
25
|
+
|
|
26
|
+
if response.code == '200' && json['error'].nil?
|
|
27
|
+
json
|
|
28
|
+
elsif ERRORS[json['error']['code']]
|
|
29
|
+
raise(ERRORS[json['error']['code']], encoded_body)
|
|
30
|
+
else
|
|
31
|
+
raise(encoded_body)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
attr_reader :params
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/atol/version.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: atol
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: '0.1'
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- GeorgeGorbanev
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-02-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: anyway_config
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.15'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.15'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '10.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '10.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rubocop
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.52'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.52'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: webmock
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '3.0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '3.0'
|
|
97
|
+
description:
|
|
98
|
+
email:
|
|
99
|
+
- GeorgeGorbanev@gmail.com
|
|
100
|
+
executables: []
|
|
101
|
+
extensions: []
|
|
102
|
+
extra_rdoc_files: []
|
|
103
|
+
files:
|
|
104
|
+
- ".gitignore"
|
|
105
|
+
- ".rspec"
|
|
106
|
+
- ".travis.yml"
|
|
107
|
+
- Gemfile
|
|
108
|
+
- Gemfile.lock
|
|
109
|
+
- LICENSE
|
|
110
|
+
- README.md
|
|
111
|
+
- Rakefile
|
|
112
|
+
- atol-rb.gemspec
|
|
113
|
+
- lib/atol.rb
|
|
114
|
+
- lib/atol/config.rb
|
|
115
|
+
- lib/atol/errors.rb
|
|
116
|
+
- lib/atol/request.rb
|
|
117
|
+
- lib/atol/request/get_document_state.rb
|
|
118
|
+
- lib/atol/request/get_token.rb
|
|
119
|
+
- lib/atol/request/post_document.rb
|
|
120
|
+
- lib/atol/request/post_document/item/body.rb
|
|
121
|
+
- lib/atol/request/post_document/sell/body.rb
|
|
122
|
+
- lib/atol/transaction.rb
|
|
123
|
+
- lib/atol/transaction/get_document_state.rb
|
|
124
|
+
- lib/atol/transaction/get_token.rb
|
|
125
|
+
- lib/atol/transaction/post_document.rb
|
|
126
|
+
- lib/atol/version.rb
|
|
127
|
+
homepage: https://github.com/GeorgeGorbanev/atol-rb
|
|
128
|
+
licenses:
|
|
129
|
+
- MIT
|
|
130
|
+
metadata: {}
|
|
131
|
+
post_install_message:
|
|
132
|
+
rdoc_options: []
|
|
133
|
+
require_paths:
|
|
134
|
+
- lib
|
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '0'
|
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0'
|
|
145
|
+
requirements: []
|
|
146
|
+
rubyforge_project:
|
|
147
|
+
rubygems_version: 2.6.10
|
|
148
|
+
signing_key:
|
|
149
|
+
specification_version: 4
|
|
150
|
+
summary: ATOL KaaS client for Ruby
|
|
151
|
+
test_files: []
|