monobank 0.2.3 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9e91f8a19ff3ec21d27e4665dc1b94b73fe69735621411340e5d56c83827e63
4
- data.tar.gz: '048ba2327b532c52be70e1ee376ac98c8003e5ab736ae49b06fdb8ee1c48a54d'
3
+ metadata.gz: 15be031b6729c65effbd0495c54824eea911e9162101b373f0b3cf35b598f851
4
+ data.tar.gz: e4c51fd2a95aab6bbe4313be5e5f65c6c45f0a0f8eb67a527d7e530519a10ded
5
5
  SHA512:
6
- metadata.gz: d3aa68afc8bcf9019ea4dcb1a55c41a91fa9f9a930c750797301197c24245e1730775f5016c09efddf86b1d7b0bf9c9955204c927cc948150811be25573117a1
7
- data.tar.gz: fab711e63c1d203afe8172dfc570578f6e74a7acc478fd9c2f21c69e7aa44167a9f32d03d56f6ab6d322be8c26cdb757ebbf8f6da9f18219fed41cdbabece532
6
+ metadata.gz: 7cdfec02d3d6c96ca18565af5db3e779b479b77722db0d170f3aa7ff144c4229112a57736809faec916010d96c474072911fbc7e1790299a52c4db50b6e40e90
7
+ data.tar.gz: c9cf70b27da7289cec013e577fe194feebfea8d9c05b09e2a690feba1036a04d582631cc774643cc32069f90347008db3311d3895bfbd16d74c6739e0d11c844
@@ -0,0 +1,35 @@
1
+ module Monobank
2
+ module Auth
3
+ class Corporate
4
+ def initialize(private_key:, key_id: nil, request_id: nil)
5
+ @private_key = init_key(private_key:)
6
+ @key_id = key_id
7
+ @request_id = request_id
8
+ end
9
+
10
+ def to_headers(pathname:)
11
+ time = Time.now.to_i
12
+
13
+ {
14
+ 'X-Time' => time.to_s,
15
+ 'X-Sign' => Base64.strict_encode64(sign(pathname:, time:))
16
+ }.tap do |headers|
17
+ headers['X-Key-Id'] = key_id unless key_id.nil?
18
+ headers['X-Request-Id'] = request_id unless request_id.nil?
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_accessor :private_key, :key_id, :request_id
25
+
26
+ def init_key(private_key:)
27
+ OpenSSL::PKey::EC.new(private_key)
28
+ end
29
+
30
+ def sign(pathname:, time:)
31
+ private_key.sign(OpenSSL::Digest::SHA256.new, "#{time}#{request_id}#{pathname}")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ module Monobank
2
+ module Auth
3
+ class Private
4
+ def initialize(token:)
5
+ @token = token
6
+ end
7
+
8
+ def to_headers(*)
9
+ { 'X-Token' => token }
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :token
15
+ end
16
+ end
17
+ end
@@ -1,4 +1,5 @@
1
1
  require 'monobank/connection'
2
+ require 'monobank/auth/private'
2
3
  require 'monobank/bank/currency'
3
4
  require 'monobank/personal/client_info'
4
5
  require 'monobank/personal/statement'
@@ -11,15 +12,21 @@ module Monobank
11
12
  end
12
13
 
13
14
  def client_info(token:)
14
- Personal::ClientInfo.new(token: token).call
15
+ Personal::ClientInfo.new(auth: auth(token:)).call
15
16
  end
16
17
 
17
18
  def statement(token:, account_id:, from:, to: nil)
18
- Personal::Statement.new(token: token, account_id: account_id, from: from, to: to).call
19
+ Personal::Statement.new(account_id:, from:, to:, auth: auth(token:)).call
19
20
  end
20
21
 
21
22
  def set_webhook(token:, url:)
22
- Personal::Webhook.new(token: token, url: url).call
23
+ Personal::Webhook.new(url:, auth: auth(token:)).call
24
+ end
25
+
26
+ private
27
+
28
+ def auth(token:)
29
+ Auth::Private.new(token:)
23
30
  end
24
31
  end
25
32
  end
@@ -0,0 +1,60 @@
1
+ require 'monobank/auth/corporate'
2
+ require 'monobank/personal/registration'
3
+ require 'monobank/personal/registration_status'
4
+ require 'monobank/personal/corporate_webhook'
5
+ require 'monobank/personal/settings'
6
+ require 'monobank/personal/auth_request'
7
+ require 'monobank/personal/auth_check'
8
+ require 'monobank/personal/client_info'
9
+ require 'monobank/personal/statement'
10
+
11
+ module Monobank
12
+ module Corporate
13
+ class Client
14
+ def initialize(private_key:, key_id:)
15
+ @private_key = private_key
16
+ @key_id = key_id
17
+ end
18
+
19
+ def registration(public_key:, name:, description:, contact_person:, phone:, email:, logo:)
20
+ Personal::Registration.new(public_key:, name:, description:, contact_person:, phone:, email:, logo:, auth:).call
21
+ end
22
+
23
+ def registration_status(public_key:)
24
+ Personal::RegistrationStatus.new(public_key:, auth:).call
25
+ end
26
+
27
+ def set_webhook(url:)
28
+ Personal::CorporateWebhook.new(url: url, auth:).call
29
+ end
30
+
31
+ def settings
32
+ Personal::Settings.new(auth:).call
33
+ end
34
+
35
+ def auth_request(callback: nil)
36
+ Personal::AuthRequest.new(callback:, auth:).call
37
+ end
38
+
39
+ def auth_check(request_id:)
40
+ Personal::AuthCheck.new(auth: auth(request_id:)).call
41
+ end
42
+
43
+ def client_info(request_id:)
44
+ Personal::ClientInfo.new(auth: auth(request_id:)).call
45
+ end
46
+
47
+ def statement(request_id:, account_id:, from:, to: nil)
48
+ Personal::Statement.new(account_id:, from:, to:, auth: auth(request_id:)).call
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :private_key, :key_id
54
+
55
+ def auth(request_id: nil)
56
+ Auth::Corporate.new(private_key:, key_id:, request_id:)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,21 @@
1
+ require 'forwardable'
2
+ require 'monobank/corporate/client'
3
+
4
+ module Monobank
5
+ module Corporate
6
+ extend SingleForwardable
7
+ def_delegators \
8
+ :client, :registration, :registration_status, :set_webhook, :settings,
9
+ :auth_request, :auth_check, :client_info, :statement
10
+
11
+ def self.configure(private_key:, key_id: nil)
12
+ @private_key = private_key
13
+ @key_id = key_id
14
+ @client = nil
15
+ end
16
+
17
+ def self.client
18
+ @client ||= Client.new(private_key: @private_key, key_id: @key_id)
19
+ end
20
+ end
21
+ end
@@ -3,6 +3,10 @@ require 'monobank/resources/error'
3
3
  module Monobank
4
4
  module Methods
5
5
  class Base
6
+ def initialize(auth: nil)
7
+ @auth = auth
8
+ end
9
+
6
10
  def call
7
11
  attributes = response
8
12
  return define_resources(attributes) if attributes.code == 200
@@ -12,7 +16,11 @@ module Monobank
12
16
 
13
17
  private
14
18
 
15
- attr_reader :token
19
+ attr_reader :auth
20
+
21
+ def pathname
22
+ raise NotImplementedError
23
+ end
16
24
 
17
25
  def response
18
26
  raise NotImplementedError
@@ -20,11 +28,15 @@ module Monobank
20
28
 
21
29
  def options
22
30
  {
23
- headers: { 'X-Token' => token.to_s },
31
+ headers: (headers || {}).merge(auth&.to_headers(pathname:) || {}),
24
32
  body: body.to_json
25
33
  }
26
34
  end
27
35
 
36
+ def headers
37
+ {}
38
+ end
39
+
28
40
  def body; end
29
41
 
30
42
  def connection
@@ -0,0 +1,22 @@
1
+ require 'monobank/methods/get'
2
+ require 'monobank/resources/personal/auth_check'
3
+
4
+ module Monobank
5
+ module Personal
6
+ class AuthCheck < Methods::Get
7
+ ENDPOINT = '/personal/auth/request'.freeze
8
+
9
+ private
10
+
11
+ attr_reader :request_id
12
+
13
+ def pathname
14
+ ENDPOINT
15
+ end
16
+
17
+ def define_resources(attributes)
18
+ Monobank::Resources::Personal::AuthCheck.new(attributes)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ require 'monobank/methods/post'
2
+ require 'monobank/resources/personal/auth_request'
3
+
4
+ module Monobank
5
+ module Personal
6
+ class AuthRequest < Methods::Post
7
+ ENDPOINT = '/personal/auth/request'.freeze
8
+
9
+ def initialize(callback: nil, **rest)
10
+ super(**rest)
11
+ @callback = callback
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :callback
17
+
18
+ def pathname
19
+ ENDPOINT
20
+ end
21
+
22
+ def headers
23
+ {'X-Callback' => callback} if callback
24
+ end
25
+
26
+ def define_resources(attributes)
27
+ Monobank::Resources::Personal::AuthRequest.new(attributes)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -6,10 +6,6 @@ module Monobank
6
6
  class ClientInfo < Methods::Get
7
7
  ENDPOINT = '/personal/client-info'.freeze
8
8
 
9
- def initialize(token:)
10
- @token = token
11
- end
12
-
13
9
  private
14
10
 
15
11
  def pathname
@@ -0,0 +1,15 @@
1
+ require 'monobank/personal/webhook'
2
+
3
+ module Monobank
4
+ module Personal
5
+ class CorporateWebhook < Webhook
6
+ ENDPOINT = '/personal/corp/webhook'.freeze
7
+
8
+ private
9
+
10
+ def pathname
11
+ ENDPOINT
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ require 'monobank/methods/post'
2
+ require 'monobank/resources/personal/registration'
3
+
4
+ module Monobank
5
+ module Personal
6
+ class Registration < Methods::Post
7
+ ENDPOINT = '/personal/auth/registration'.freeze
8
+
9
+ def initialize(public_key:, name:, description:, contact_person:, phone:, email:, logo:, **rest)
10
+ super(**rest)
11
+
12
+ @public_key = public_key
13
+ @name = name
14
+ @description = description
15
+ @contact_person = contact_person
16
+ @phone = phone
17
+ @email = email
18
+ @logo = logo
19
+ end
20
+
21
+ def pathname
22
+ ENDPOINT
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :public_key, :name, :description, :contact_person, :phone, :email, :logo
28
+
29
+ def body
30
+ {
31
+ pubkey: public_key,
32
+ name:,
33
+ description:,
34
+ contactPerson: contact_person,
35
+ phone:,
36
+ email:,
37
+ logo:
38
+ }
39
+ end
40
+
41
+ def define_resources(attributes)
42
+ Resources::Personal::Registration.new(attributes)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ require 'monobank/methods/post'
2
+ require 'monobank/resources/personal/registration_status'
3
+
4
+ module Monobank
5
+ module Personal
6
+ class RegistrationStatus < Methods::Post
7
+ ENDPOINT = '/personal/auth/registration/status'.freeze
8
+
9
+ def initialize(public_key:, **rest)
10
+ super(**rest)
11
+
12
+ @public_key = public_key
13
+ end
14
+
15
+ def pathname
16
+ ENDPOINT
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :public_key
22
+
23
+ def body
24
+ { pubkey: public_key }
25
+ end
26
+
27
+ def define_resources(attributes)
28
+ Resources::Personal::RegistrationStatus.new(attributes)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ require 'monobank/methods/post'
2
+ require 'monobank/resources/personal/settings'
3
+
4
+ module Monobank
5
+ module Personal
6
+ class Settings < Methods::Post
7
+ ENDPOINT = '/personal/corp/settings'.freeze
8
+
9
+ def pathname
10
+ ENDPOINT
11
+ end
12
+
13
+ private
14
+
15
+ def define_resources(attributes)
16
+ Resources::Personal::Settings.new(attributes)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -6,8 +6,9 @@ module Monobank
6
6
  class Statement < Methods::Get
7
7
  ENDPOINT = '/personal/statement'.freeze
8
8
 
9
- def initialize(token:, account_id:, from:, to:)
10
- @token = token
9
+ def initialize(account_id:, from:, to:, **rest)
10
+ super(**rest)
11
+
11
12
  @account_id = account_id
12
13
  @from = from
13
14
  @to = to
@@ -30,4 +31,4 @@ module Monobank
30
31
  end
31
32
  end
32
33
  end
33
- end
34
+ end
@@ -6,8 +6,9 @@ module Monobank
6
6
  class Webhook < Methods::Post
7
7
  ENDPOINT = '/personal/webhook'.freeze
8
8
 
9
- def initialize(token:, url:)
10
- @token = token
9
+ def initialize(url:, **rest)
10
+ super(**rest)
11
+
11
12
  @url = url
12
13
  end
13
14
 
@@ -0,0 +1,11 @@
1
+ require 'monobank/resources/base'
2
+
3
+ module Monobank
4
+ module Resources
5
+ module Personal
6
+ class AuthCheck < Base
7
+ define_fields %w[status]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'monobank/resources/base'
2
+
3
+ module Monobank
4
+ module Resources
5
+ module Personal
6
+ class AuthRequest < Base
7
+ define_fields %w[accept_url]
8
+
9
+ def request_id
10
+ @attributes['token_request_id']
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'monobank/resources/base'
2
+
3
+ module Monobank
4
+ module Resources
5
+ module Personal
6
+ class Registration < Base
7
+ define_fields %w[status]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'monobank/resources/base'
2
+
3
+ module Monobank
4
+ module Resources
5
+ module Personal
6
+ class RegistrationStatus < Base
7
+ define_fields %w[key_id status]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'monobank/resources/base'
2
+
3
+ module Monobank
4
+ module Resources
5
+ module Personal
6
+ class Settings < Base
7
+ define_fields %w[name permissions webhook]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module Monobank
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/monobank.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'monobank/version'
2
2
  require 'monobank/client'
3
+ require 'monobank/corporate'
3
4
  require 'forwardable'
4
5
 
5
6
  module Monobank
@@ -0,0 +1,290 @@
1
+ describe Monobank::Corporate do
2
+ let(:key_id) { nil }
3
+
4
+ before do
5
+ allow(Time).to receive(:now).and_return(Time.parse('2024-01-31'))
6
+
7
+ fake_private_key = OpenSSL::PKey::EC.new
8
+ allow(fake_private_key).to(receive(:sign)) { |_, args| "__SIGNED__#{args}" }
9
+ allow_any_instance_of(Monobank::Auth::Corporate).to receive(:init_key).and_return(fake_private_key)
10
+
11
+ allow(Base64).to(receive(:strict_encode64)) { |arg| "__BASE64__#{arg}" }
12
+
13
+ Monobank::Corporate.configure(private_key: 'FAKE PRIVATE KEY', key_id:)
14
+ end
15
+
16
+ context '.registration' do
17
+ before do
18
+ stub_request(:post, 'https://api.monobank.ua/personal/auth/registration').
19
+ with(
20
+ body: {
21
+ "pubkey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZZd0VBWUhLb1pJemow...",
22
+ "name": "ТОВ \"Ворона\"",
23
+ "description": "Ми робимо найрозумніший PFM з усіх можливих і нам потрібен доступ до виписка користувача, щоб створювати красиву статистику",
24
+ "contactPerson": "Роман Шевченко",
25
+ "phone": "380671234567",
26
+ "email": "etс@example.com",
27
+ "logo": "iVBORw0KGgoAAAANSUhEUgAAAUAAAACECAYAAADhnvK8AAAapElEQVR42..."
28
+ }.to_json,
29
+ headers: {
30
+ 'X-Sign'=>'__BASE64____SIGNED__1706652000/personal/auth/registration',
31
+ 'X-Time'=>'1706652000'
32
+ }).
33
+ to_return(status: 200, body: { status: 'New' }.to_json, headers: {'Content-Type' => 'application/json'})
34
+ end
35
+
36
+ it 'returns correct data' do
37
+ result = Monobank::Corporate.registration(
38
+ public_key: 'LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZZd0VBWUhLb1pJemow...',
39
+ name: 'ТОВ "Ворона"',
40
+ description: 'Ми робимо найрозумніший PFM з усіх можливих і нам потрібен доступ до виписка користувача, щоб створювати красиву статистику',
41
+ contact_person: 'Роман Шевченко',
42
+ phone: '380671234567',
43
+ email: 'etс@example.com',
44
+ logo: 'iVBORw0KGgoAAAANSUhEUgAAAUAAAACECAYAAADhnvK8AAAapElEQVR42...'
45
+ )
46
+
47
+ expect(result.status).to eq 'New'
48
+ end
49
+ end
50
+
51
+ context '.registration_status' do
52
+ before do
53
+ stub_request(:post, 'https://api.monobank.ua/personal/auth/registration/status').
54
+ with(
55
+ body: {
56
+ "pubkey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZZd0VBWUhLb1pJemow..."
57
+ }.to_json,
58
+ headers: {
59
+ 'X-Sign' => '__BASE64____SIGNED__1706652000/personal/auth/registration/status',
60
+ 'X-Time' => '1706652000'
61
+ }).
62
+ to_return(
63
+ status: 200,
64
+ body: { status: 'Approved', keyId: '28a75537175a018645e6f8b14be7681791e701e0' }.to_json,
65
+ headers: {'Content-Type' => 'application/json'}
66
+ )
67
+ end
68
+
69
+ it 'returns correct data' do
70
+ result = Monobank::Corporate.registration_status(public_key: 'LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZZd0VBWUhLb1pJemow...')
71
+
72
+ expect(result.status).to eq 'Approved'
73
+ expect(result.key_id).to eq '28a75537175a018645e6f8b14be7681791e701e0'
74
+ end
75
+ end
76
+
77
+ context 'with key_id' do
78
+ let(:key_id) { '28a75537175a018645e6f8b14be7681791e701e0' }
79
+
80
+ context '.set_webhook' do
81
+ before do
82
+ stub_request(:post, 'https://api.monobank.ua/personal/corp/webhook').
83
+ with(
84
+ body: {'webHookUrl': 'https://example.com/some_random_data_for_security'}.to_json,
85
+ headers: {
86
+ 'X-Key-Id' => '28a75537175a018645e6f8b14be7681791e701e0',
87
+ 'X-Sign' => '__BASE64____SIGNED__1706652000/personal/corp/webhook',
88
+ 'X-Time' => '1706652000'
89
+ }).
90
+ to_return(status: 200, body: {'status' => 'ok'}.to_json, headers: {'Content-Type' => 'application/json'})
91
+ end
92
+
93
+ it 'returns correct data' do
94
+ result = Monobank::Corporate.set_webhook(url: 'https://example.com/some_random_data_for_security')
95
+
96
+ expect(result.status).to eq 'ok'
97
+ end
98
+ end
99
+
100
+ context '.settings' do
101
+ before do
102
+ stub_request(:post, 'https://api.monobank.ua/personal/corp/settings').
103
+ with(
104
+ headers: {
105
+ 'X-Key-Id' => '28a75537175a018645e6f8b14be7681791e701e0',
106
+ 'X-Sign' => '__BASE64____SIGNED__1706652000/personal/corp/settings',
107
+ 'X-Time' => '1706652000'
108
+ }).
109
+ to_return(
110
+ status: 200,
111
+ body: {
112
+ "pubkey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZZd0VBWUhLb1pJemow...",
113
+ "name": "Компанія",
114
+ "permission": "psf",
115
+ "logo": "iVBORw0KGgoAAAANSUhEUgAAAUAAAACECAYAAADhnvK8AAAapElEQVR42...",
116
+ "webhook": "https://example.com/mono/corp/webhook/maybesomegibberishuniquestringbutnotnecessarily"
117
+ }.to_json,
118
+ headers: {'Content-Type' => 'application/json'}
119
+ )
120
+ end
121
+
122
+ it 'returns correct data' do
123
+ result = Monobank::Corporate.settings
124
+
125
+ expect(result.name).to eq 'Компанія'
126
+ expect(result.webhook).to eq 'https://example.com/mono/corp/webhook/maybesomegibberishuniquestringbutnotnecessarily'
127
+ end
128
+ end
129
+
130
+ context '.auth_request' do
131
+ let(:headers) { {} }
132
+
133
+ before do
134
+ stub_request(:post, 'https://api.monobank.ua/personal/auth/request').
135
+ with(
136
+ headers: {
137
+ 'X-Key-Id' => '28a75537175a018645e6f8b14be7681791e701e0',
138
+ 'X-Sign' => '__BASE64____SIGNED__1706652000/personal/auth/request',
139
+ 'X-Time' => '1706652000',
140
+ **headers
141
+ }).
142
+ to_return(
143
+ status: 200,
144
+ body: {
145
+ "tokenRequestId": "uLkwh3NzFAfEkj7urj5C7AU_",
146
+ "acceptUrl": "https://mbnk.app/auth/uLkwh3NzFAfEkj7urj5C7AU_"
147
+ }.to_json,
148
+ headers: {'Content-Type' => 'application/json'}
149
+ )
150
+ end
151
+
152
+ it 'returns correct data' do
153
+ result = Monobank::Corporate.auth_request
154
+
155
+ expect(result.request_id).to eq 'uLkwh3NzFAfEkj7urj5C7AU_'
156
+ expect(result.accept_url).to eq 'https://mbnk.app/auth/uLkwh3NzFAfEkj7urj5C7AU_'
157
+ end
158
+
159
+ context 'when a callback is passed' do
160
+ let(:headers) { {'X-Callback' => 'https://example.com' }}
161
+
162
+ it 'returns passes it as headers' do
163
+ result = Monobank::Corporate.auth_request(callback: 'https://example.com')
164
+
165
+ expect(result.request_id).to eq 'uLkwh3NzFAfEkj7urj5C7AU_'
166
+ expect(result.accept_url).to eq 'https://mbnk.app/auth/uLkwh3NzFAfEkj7urj5C7AU_'
167
+ end
168
+ end
169
+ end
170
+
171
+ context 'with request_id' do
172
+ let(:request_id) { 'uLkwh3NzFAfEkj7urj5C7AU_' }
173
+
174
+ context '.auth_check' do
175
+ before do
176
+ stub_request(:get, 'https://api.monobank.ua/personal/auth/request').
177
+ with(
178
+ headers: {
179
+ 'X-Key-Id' => '28a75537175a018645e6f8b14be7681791e701e0',
180
+ 'X-Request-Id' => 'uLkwh3NzFAfEkj7urj5C7AU_',
181
+ 'X-Sign' => '__BASE64____SIGNED__1706652000uLkwh3NzFAfEkj7urj5C7AU_/personal/auth/request',
182
+ 'X-Time' => '1706652000'
183
+ }).
184
+ to_return(
185
+ status: 200,
186
+ body: { status: 'ok' }.to_json,
187
+ headers: {'Content-Type' => 'application/json'}
188
+ )
189
+ end
190
+
191
+ it 'returns correct data' do
192
+ result = Monobank::Corporate.auth_check(request_id:)
193
+
194
+ expect(result.status).to eq 'ok'
195
+ end
196
+ end
197
+
198
+ context '.client_info' do
199
+ before do
200
+ stub_request(:get, 'https://api.monobank.ua/personal/client-info').
201
+ with(
202
+ headers: {
203
+ 'X-Key-Id' => '28a75537175a018645e6f8b14be7681791e701e0',
204
+ 'X-Request-Id' => 'uLkwh3NzFAfEkj7urj5C7AU_',
205
+ 'X-Sign' => '__BASE64____SIGNED__1706652000uLkwh3NzFAfEkj7urj5C7AU_/personal/client-info',
206
+ 'X-Time' => '1706652000'
207
+ }).
208
+ to_return(
209
+ status: 200,
210
+ body: {
211
+ "clientId": "3MSaMMtczs",
212
+ "name": "Мазепа Іван",
213
+ "webHookUrl": "https://mysomesite.copm/some_random_data_for_security",
214
+ "permissions": "psf",
215
+ "accounts": [
216
+ {
217
+ "id": "kKGVoZuHWzqVoZuH",
218
+ "sendId": "uHWzqVoZuH",
219
+ "balance": 10000000,
220
+ "creditLimit": 10000000,
221
+ "type": "black",
222
+ "currencyCode": 980,
223
+ "cashbackType": "UAH",
224
+ "maskedPan": [
225
+ "537541******1234"
226
+ ],
227
+ "iban": "UA733220010000026201234567890"
228
+ }
229
+ ]
230
+ }.to_json,
231
+ headers: {'Content-Type' => 'application/json'}
232
+ )
233
+ end
234
+
235
+ it 'returns correct data' do
236
+ result = Monobank::Corporate.client_info(request_id:)
237
+
238
+ expect(result.name).to eq 'Мазепа Іван'
239
+ expect(result.accounts.length).to eq 1
240
+ end
241
+ end
242
+
243
+ context '.statement' do
244
+ before do
245
+ stub_request(:get, 'https://api.monobank.ua/personal/statement/0/1546304461').
246
+ with(
247
+ headers: {
248
+ 'X-Key-Id' => '28a75537175a018645e6f8b14be7681791e701e0',
249
+ 'X-Request-Id' => 'uLkwh3NzFAfEkj7urj5C7AU_',
250
+ 'X-Sign' => '__BASE64____SIGNED__1706652000uLkwh3NzFAfEkj7urj5C7AU_/personal/statement/0/1546304461',
251
+ 'X-Time' => '1706652000'
252
+ }).
253
+ to_return(
254
+ status: 200,
255
+ body: [
256
+ {
257
+ "id": "ZuHWzqkKGVo=",
258
+ "time": 1554466347,
259
+ "description": "Покупка щастя",
260
+ "mcc": 7997,
261
+ "originalMcc": 7997,
262
+ "hold": false,
263
+ "amount": -95000,
264
+ "operationAmount": -95000,
265
+ "currencyCode": 980,
266
+ "commissionRate": 0,
267
+ "cashbackAmount": 19000,
268
+ "balance": 10050000,
269
+ "comment": "За каву",
270
+ "receiptId": "XXXX-XXXX-XXXX-XXXX",
271
+ "counterEdrpou": "3096889974",
272
+ "counterIban": "UA898999980000355639201001404",
273
+ "counterName": "ТОВАРИСТВО З ОБМЕЖЕНОЮ ВІДПОВІДАЛЬНІСТЮ «ВОРОНА»"
274
+ }
275
+ ].to_json,
276
+ headers: {'Content-Type' => 'application/json'}
277
+ )
278
+ end
279
+
280
+ it 'returns correct data' do
281
+ result = Monobank::Corporate.statement(request_id:, account_id: 0, from: 1546304461)
282
+
283
+ expect(result.first.id).to eq 'ZuHWzqkKGVo='
284
+ expect(result.first.amount).to eq -95000
285
+ expect(result.first.currency_code).to eq 980
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,138 @@
1
+ describe Monobank do
2
+ let(:token) { 'FAKE_TOKEN' }
3
+
4
+ context '.bank_currency' do
5
+ before do
6
+ stub_request(:get, "https://api.monobank.ua/bank/currency").
7
+ to_return(
8
+ status: 200,
9
+ body: [
10
+ {
11
+ 'currencyCodeA' => 840,
12
+ 'currencyCodeB' => 980,
13
+ 'date' => 1552392228,
14
+ 'rateSell' => 27,
15
+ 'rateBuy' => 27.2,
16
+ 'rateCross' => 27.1
17
+ }
18
+ ].to_json,
19
+ headers: {'Content-Type' => 'application/json'}
20
+ )
21
+ end
22
+
23
+ it 'returns correct data' do
24
+ result = Monobank.bank_currency
25
+ expect(result.first.currency_code_a).to eq 840
26
+ end
27
+ end
28
+
29
+ context '.client_info' do
30
+ before do
31
+ stub_request(:get, "https://api.monobank.ua/personal/client-info").
32
+ with(headers: {'X-Token' => 'FAKE_TOKEN'}).
33
+ to_return(
34
+ status: 200,
35
+ body: {
36
+ "clientId": "3MSaMMtczs",
37
+ "name": "Мазепа Іван",
38
+ "webHookUrl": "https://example.com/some_random_data_for_security",
39
+ "permissions": "psfj",
40
+ "accounts": [
41
+ {
42
+ "id": "kKGVoZuHWzqVoZuH",
43
+ "sendId": "uHWzqVoZuH",
44
+ "balance": 10000000,
45
+ "creditLimit": 10000000,
46
+ "type": "black",
47
+ "currencyCode": 980,
48
+ "cashbackType": "UAH",
49
+ "maskedPan": [
50
+ "537541******1234"
51
+ ],
52
+ "iban": "UA733220010000026201234567890"
53
+ }
54
+ ],
55
+ "jars": [
56
+ {
57
+ "id": "kKGVoZuHWzqVoZuH",
58
+ "sendId": "uHWzqVoZuH",
59
+ "title": "На тепловізор",
60
+ "description": "На тепловізор",
61
+ "currencyCode": 980,
62
+ "balance": 1000000,
63
+ "goal": 10000000
64
+ }
65
+ ]
66
+ }.to_json,
67
+ headers: {'Content-Type' => 'application/json'}
68
+ )
69
+ end
70
+
71
+ it 'returns correct data' do
72
+ result = Monobank.client_info(token:)
73
+ expect(result.name).to eq 'Мазепа Іван'
74
+ expect(result.accounts.length).to eq 1
75
+ end
76
+ end
77
+
78
+ context '.statement' do
79
+ before do
80
+ stub_request(:get, "https://api.monobank.ua/personal/statement/0/1546304461").
81
+ with(headers: {'X-Token' => 'FAKE_TOKEN'}).
82
+ to_return(
83
+ status: 200,
84
+ body: [
85
+ {
86
+ "id": "ZuHWzqkKGVo=",
87
+ "time": 1554466347,
88
+ "description": "Покупка щастя",
89
+ "mcc": 7997,
90
+ "originalMcc": 7997,
91
+ "hold": false,
92
+ "amount": -95000,
93
+ "operationAmount": -95000,
94
+ "currencyCode": 980,
95
+ "commissionRate": 0,
96
+ "cashbackAmount": 19000,
97
+ "balance": 10050000,
98
+ "comment": "За каву",
99
+ "receiptId": "XXXX-XXXX-XXXX-XXXX",
100
+ "invoiceId": "2103.в.27",
101
+ "counterEdrpou": "3096889974",
102
+ "counterIban": "UA898999980000355639201001404",
103
+ "counterName": "ТОВАРИСТВО З ОБМЕЖЕНОЮ ВІДПОВІДАЛЬНІСТЮ «ВОРОНА»"
104
+ }
105
+ ].to_json,
106
+ headers: {'Content-Type' => 'application/json'}
107
+ )
108
+ end
109
+
110
+ it 'returns correct data' do
111
+ result = Monobank.statement(token:, account_id: 0, from: 1546304461)
112
+ expect(result.first.id).to eq 'ZuHWzqkKGVo='
113
+ expect(result.first.amount).to eq -95000
114
+ expect(result.first.currency_code).to eq 980
115
+ end
116
+ end
117
+
118
+ context '.set_webhook' do
119
+ before do
120
+ stub_request(:post, "https://api.monobank.ua/personal/webhook").
121
+ with(
122
+ body: {'webHookUrl': 'https://example.com/some_random_data_for_security'}.to_json,
123
+ headers: {
124
+ 'Accept'=>'*/*',
125
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
126
+ 'User-Agent'=>'Ruby',
127
+ 'X-Token'=>'FAKE_TOKEN'
128
+ }).
129
+ to_return(status: 200, body: {'status' => 'ok'}.to_json, headers: {'Content-Type' => 'application/json'})
130
+ end
131
+
132
+ it 'returns correct data' do
133
+ result = Monobank.set_webhook(token:, url: 'https://example.com/some_random_data_for_security')
134
+
135
+ expect(result.status).to eq 'ok'
136
+ end
137
+ end
138
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  ENV['RAILS_ENV'] ||= 'test'
2
2
 
3
+ require 'webmock/rspec'
4
+
3
5
  require 'monobank'
4
6
 
5
7
  ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../')
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monobank
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - vergilet
8
8
  - anatoliikryvishyn
9
+ - dreyks
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2024-01-31 00:00:00.000000000 Z
13
+ date: 2024-02-23 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: httparty
@@ -71,6 +72,20 @@ dependencies:
71
72
  - - ">="
72
73
  - !ruby/object:Gem::Version
73
74
  version: 3.8.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: webmock
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
74
89
  description: Unofficial Ruby Gem for Monobank API.
75
90
  email:
76
91
  - osyaroslav@gmail.com
@@ -80,24 +95,41 @@ extra_rdoc_files: []
80
95
  files:
81
96
  - Rakefile
82
97
  - lib/monobank.rb
98
+ - lib/monobank/auth/corporate.rb
99
+ - lib/monobank/auth/private.rb
83
100
  - lib/monobank/bank/currency.rb
84
101
  - lib/monobank/client.rb
85
102
  - lib/monobank/connection.rb
103
+ - lib/monobank/corporate.rb
104
+ - lib/monobank/corporate/client.rb
86
105
  - lib/monobank/error.rb
87
106
  - lib/monobank/methods/base.rb
88
107
  - lib/monobank/methods/get.rb
89
108
  - lib/monobank/methods/post.rb
109
+ - lib/monobank/personal/auth_check.rb
110
+ - lib/monobank/personal/auth_request.rb
90
111
  - lib/monobank/personal/client_info.rb
112
+ - lib/monobank/personal/corporate_webhook.rb
113
+ - lib/monobank/personal/registration.rb
114
+ - lib/monobank/personal/registration_status.rb
115
+ - lib/monobank/personal/settings.rb
91
116
  - lib/monobank/personal/statement.rb
92
117
  - lib/monobank/personal/webhook.rb
93
118
  - lib/monobank/resources/bank/currency.rb
94
119
  - lib/monobank/resources/base.rb
95
120
  - lib/monobank/resources/error.rb
96
121
  - lib/monobank/resources/personal/accounts.rb
122
+ - lib/monobank/resources/personal/auth_check.rb
123
+ - lib/monobank/resources/personal/auth_request.rb
97
124
  - lib/monobank/resources/personal/client_info.rb
125
+ - lib/monobank/resources/personal/registration.rb
126
+ - lib/monobank/resources/personal/registration_status.rb
127
+ - lib/monobank/resources/personal/settings.rb
98
128
  - lib/monobank/resources/personal/statement.rb
99
129
  - lib/monobank/resources/personal/webhook.rb
100
130
  - lib/monobank/version.rb
131
+ - spec/monobank_corporate_spec.rb
132
+ - spec/monobank_spec.rb
101
133
  - spec/spec_helper.rb
102
134
  homepage: https://github.com/vergilet/monobank
103
135
  licenses:
@@ -126,4 +158,6 @@ signing_key:
126
158
  specification_version: 4
127
159
  summary: Unofficial Ruby Gem for Monobank API.
128
160
  test_files:
161
+ - spec/monobank_corporate_spec.rb
162
+ - spec/monobank_spec.rb
129
163
  - spec/spec_helper.rb