yandex-money-sdk 0.9.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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +263 -0
  8. data/Rakefile +7 -0
  9. data/lib/yandex_money/api.rb +261 -0
  10. data/lib/yandex_money/api/version.rb +5 -0
  11. data/spec/account_info_spec.rb +54 -0
  12. data/spec/auth_spec.rb +58 -0
  13. data/spec/cards_spec.rb +53 -0
  14. data/spec/fixtures/vcr_cassettes/accept_incoming_transfer_with_protection_code.yml +42 -0
  15. data/spec/fixtures/vcr_cassettes/accept_incoming_transfer_with_protection_code_with_wrong_code.yml +42 -0
  16. data/spec/fixtures/vcr_cassettes/get_account_info.yml +40 -0
  17. data/spec/fixtures/vcr_cassettes/get_instance_id_fail.yml +876 -0
  18. data/spec/fixtures/vcr_cassettes/get_instance_id_success.yml +874 -0
  19. data/spec/fixtures/vcr_cassettes/get_operation_details.yml +50 -0
  20. data/spec/fixtures/vcr_cassettes/get_operation_history.yml +187 -0
  21. data/spec/fixtures/vcr_cassettes/get_operation_history_with_params.yml +46 -0
  22. data/spec/fixtures/vcr_cassettes/get_token_from_authorization_code.yml +875 -0
  23. data/spec/fixtures/vcr_cassettes/get_wrong_operation_details.yml +40 -0
  24. data/spec/fixtures/vcr_cassettes/init_with_client_secret.yml +839 -0
  25. data/spec/fixtures/vcr_cassettes/init_without_client_secret.yml +835 -0
  26. data/spec/fixtures/vcr_cassettes/initialize_with_token.yml +911 -0
  27. data/spec/fixtures/vcr_cassettes/obtain_token_for_get_account_info.yml +877 -0
  28. data/spec/fixtures/vcr_cassettes/obtain_token_for_making_payments_to_an_account.yml +875 -0
  29. data/spec/fixtures/vcr_cassettes/obtain_token_for_payments_from_bank_cards_without_authorization.yml +839 -0
  30. data/spec/fixtures/vcr_cassettes/process_external_payment.yml +40 -0
  31. data/spec/fixtures/vcr_cassettes/process_payment_to_an_account_with_failure.yml +43 -0
  32. data/spec/fixtures/vcr_cassettes/reject_payment.yml +42 -0
  33. data/spec/fixtures/vcr_cassettes/reject_payment_fail.yml +42 -0
  34. data/spec/fixtures/vcr_cassettes/request_external_payment.yml +46 -0
  35. data/spec/fixtures/vcr_cassettes/request_payment_to_an_account_with_failure.yml +43 -0
  36. data/spec/fixtures/vcr_cassettes/success_process_payment_to_an_account.yml +42 -0
  37. data/spec/fixtures/vcr_cassettes/success_request_payment_to_an_account.yml +43 -0
  38. data/spec/fixtures/vcr_cassettes/token_with_client_secret.yml +874 -0
  39. data/spec/payments_spec.rb +96 -0
  40. data/spec/spec_helper.rb +17 -0
  41. data/spec/support/constants.rb +6 -0
  42. data/yandex-money-sdk.gemspec +30 -0
  43. metadata +230 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b35c5d1e20347b5dffc26751200cd84afabf4d52
4
+ data.tar.gz: a22533f4d4f4bbe22df08cebd05a0593adb5fb33
5
+ SHA512:
6
+ metadata.gz: bb48c617b552c1cf0587aed53a4868f1fbdcce764980cdd38c3ad5685265e14f008d9e28c26af76dfa477f37214f4753104ab9cb70f731c7b781c3a372f8b75d
7
+ data.tar.gz: c08ce8f42f52a22d31ec327fc2ecf85c1f74b49b33ef434d2bc5324446067864e68ba6bb7a72589ea5796062d110ddca1d171422538e74e148f94d4ecfd42ecf
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .DS_Store
24
+ *.swp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ script: "rake"
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+ matrix:
8
+ include:
9
+ - rvm: jruby-19mode
10
+ - rvm: rbx-2
11
+ fast_finish: true
12
+ branches:
13
+ only: master
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :development do
4
+ gem "pry", require: false
5
+ end
6
+
7
+ gemspec
8
+
9
+ group :metrics do
10
+ gem "coveralls", require: false
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Alexander Maslov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # Yandex Money Ruby SDK Ruby
2
+
3
+ [![Build Status](https://travis-ci.org/yandex-money/yandex-money-sdk-ruby.svg)](https://travis-ci.org/yandex-money/yandex-money-sdk-ruby)
4
+ [![Coverage Status](https://img.shields.io/coveralls/yandex-money/yandex-money-sdk-ruby.svg)](https://coveralls.io/r/yandex-money/yandex-money-sdk-ruby)
5
+ [![Code Climate](https://codeclimate.com/github/yandex-money/yandex-money-sdk-ruby/badges/gpa.svg)](https://codeclimate.com/github/yandex-money/yandex-money-sdk-ruby)
6
+
7
+ Ruby gem for Yandex Money API usage.
8
+
9
+ ## Example application
10
+
11
+ You could find small example application in [yandex-money/yandex-money-sdk-ruby-sample](https://github.com/yandex-money/yandex-money-sdk-ruby-sample) repository.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'yandex-money-sdk'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ ```
24
+ bundle
25
+ ```
26
+
27
+ Or install it manually with:
28
+
29
+ ```
30
+ gem install yandex-money-sdk
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ### Initialize API
36
+
37
+ #### Require gem
38
+
39
+ ```ruby
40
+ require 'yandex_money/api'
41
+ ```
42
+
43
+ #### Initialize API
44
+
45
+ ```ruby
46
+ # If TOKEN was obtained previosly
47
+ api = YandexMoney::Api.new(token: TOKEN)
48
+ ```
49
+
50
+ ```ruby
51
+ # If TOKEN is need to be obtained
52
+ api = YandexMoney::Api.new(
53
+ client_id: CLIENT_ID,
54
+ redirect_uri: REDIRECT_URI,
55
+ scope: "account-info operation-history"
56
+ )
57
+ # If TOKEN is need to be obtained and client_secret key is set
58
+ api = YandexMoney::Api.new(
59
+ client_id: CLIENT_ID,
60
+ redirect_uri: REDIRECT_URI,
61
+ scope: "account-info operation-history",
62
+ client_secret: "ACBECEBCB21411...123BCE"
63
+ )
64
+ ```
65
+
66
+ ### Use user browser to send auth request to Yandex.Money server
67
+
68
+ After initializing `YandexMoney::Api` without token, you will find token request url in `api.client_url`. User need to visit that address with browser.
69
+
70
+ After visiting `api.client_url` the user will be redirected to `REDIRECT_URL` with `code` parameter. It is authorization code, needed for token obtaining.
71
+
72
+ To get token use `YandexMoney::Api#obtain_token`:
73
+
74
+ ```ruby
75
+ api.code = "ACEB6F56EC46B66F280AFB9C805C61A66A8B5" # obtained code
76
+ token = api.obtain_token # token contains valid client token
77
+ ```
78
+
79
+ ## Methods
80
+
81
+ ### Information about a user's account
82
+
83
+ #### account-info method
84
+
85
+ Getting information about the status of user's account. Required permissions: `account-info`.
86
+
87
+ ```ruby
88
+ api.account_info
89
+ #<OpenStruct account="41001565326286", balance=48.98, currency="643", avatar={"ts"=>"2012-05-02T17:22:59.000+04:00", "url"=>"https://avatars.yandex.net/get-yamoney-profile/yamoney-profile-56809635-2/normal?1335964979000"}, account_type="personal", identified=false, account_status="named">
90
+ ```
91
+
92
+ #### operation-history method
93
+
94
+ This method allows viewing the full or partial history of operations in page mode. History records are displayed in reverse chronological order (from most recent to oldest).
95
+
96
+ Required permissions: `operation-history`.
97
+
98
+ ```ruby
99
+ api.operation_history
100
+ #<OpenStruct next_record="30", operations=[{"operation_id"=>"462449992116028008", "title"=>"Возврат средств от:", "amount"=>1.0, "direction"=>"in", "datetime"=>"2014-08-27T10:19:52Z", "status"=>"success", "type"=>"deposition"}, ..., {"pattern_id"=>"p2p", "operation_id"=>"460970888534110007", "title"=>"Перевод на счет 410011700000000", "amount"=>3.02, "direction"=>"out", "datetime"=>"2014-08-10T07:28:15Z", "status"=>"success", "type"=>"outgoing-transfer"}]>
101
+ # you could pass params:
102
+ api.operation_history(records: 1)
103
+ #<OpenStruct next_record="1", operations=[{"pattern_id"=>"p2p", "operation_id"=>"463947376678019004", "title"=>"Перевод от 410011285000000", "amount"=>0.99, "direction"=>"in", "datetime"=>"2014-09-13T18:16:16Z", "status"=>"refused", "type"=>"incoming-transfer-protected"}]>
104
+ ```
105
+
106
+ #### operation-details method
107
+
108
+ Provides detailed information about a particular operation from the history.
109
+
110
+ Required permissions: `operation-details`.
111
+
112
+ ```ruby
113
+ api.operation_details(OPERATION_ID)
114
+ #<OpenStruct operation_id="462449992116028008", title="Возврат средств от:", amount=1.0, direction="in", datetime="2014-08-27T10:19:52Z", status="success", type="deposition", details="Отмена оплаты по банковской карте Яндекс.Денег\n , 5411, , \nНомер транзакции: 423910208430140827101810\nСумма в валюте платежа: 1.00 RUB">
115
+ ```
116
+
117
+ If operation doesn't exist, exception will be raised:
118
+
119
+ ```ruby
120
+ api.operation_details "unknown"
121
+ # RuntimeError:
122
+ # Illegal param operation id
123
+ ```
124
+
125
+ If scope is insufficient, expcetion will be raised:
126
+
127
+ ```ruby
128
+ api = YandexMoney::Api.new(token: TOKEN)
129
+ api.operation_details(OPERATION_ID)
130
+ # RuntimeError:
131
+ # Insufficient Scope
132
+ ```
133
+
134
+ ### Payments from the Yandex.Money wallet
135
+
136
+ #### request-payment method
137
+
138
+ Creates a payment, checks parameters and verifies that the merchant can accept the payment, or that funds can be transferred to a Yandex.Money user account.
139
+
140
+ Permissions required for making a payment to a merchant: `payment.to-pattern` (Payment Pattern) or `payment-shop`.
141
+ Permissions required for transferring funds to the accounts of other users: `payment.to-account ("payee ID," "ID type")` or `payment-p2p`.
142
+
143
+ Basic request-payment method call:
144
+
145
+ ```ruby
146
+ api = YandexMoney::Api.new(token: TOKEN)
147
+ server_response = api.request_payment(
148
+ pattern_id: "p2p",
149
+ to: "410011285611534",
150
+ amount: "1.0",
151
+ comment: "test payment comment from yandex-money-ruby",
152
+ message: "test payment message from yandex-money-ruby",
153
+ label: "testPayment",
154
+ )
155
+ #<OpenStruct status="success", contract="The generated test outgoing money transfer to 410011285611534, amount 1.0", recipient_account_type="personal", recipient_account_status="anonymous", request_id="test-p2p", test_payment="true", contract_amount=1.0, money_source={"wallet"=>{"allowed"=>true}}, recipient_identified=false>
156
+ ```
157
+
158
+ #### process-payment method
159
+
160
+ Confirms a payment that was created using the `request_payment` method. Specifies the method for making the payment.
161
+
162
+ Basic process-payment method call:
163
+
164
+ ```ruby
165
+ api = YandexMoney::Api.new(token: TOKEN)
166
+ api.process_payment(
167
+ request_id: "test-p2p",
168
+ )
169
+ #<OpenStruct status="success", payer="41001565326286", payee="test", credit_amount=20.3, payee_uid=56809635, test_payment="true", payment_id="test">
170
+ ```
171
+
172
+ #### incoming-transfer-accept method
173
+
174
+ Accepting incoming transfers with a secret code and deferred transfers.
175
+
176
+ There is a limit on the number of attempts to accept an incoming transfer with a secret code. When the allowed number of attempts have been used up, the transfer is automatically rejected (the transfer is returned to the sender).
177
+
178
+ Required token permissions: `incoming-transfers`.
179
+
180
+ ```ruby
181
+ api = YandexMoney::Api.new(token: TOKEN)
182
+ api.incoming_transfer_accept "463937708331015004", "0208"
183
+ # true
184
+ api.incoming_transfer_accept "463937708331015004", "WRONG"
185
+ # RuntimeError:
186
+ # Illegal param protection code, attemps available: 2
187
+ ```
188
+
189
+ #### incoming-transfer-reject method
190
+
191
+ Canceling incoming transfers with a secret code and deferred transfers. If the transfer is canceled, it is returned to the sender.
192
+
193
+ Required token permissions: `incoming-transfers`.
194
+
195
+ ```ruby
196
+ api = YandexMoney::Api.new(token: TOKEN)
197
+ api.incoming_transfer_reject "463947376678019004"
198
+ # true
199
+ api.incoming_transfer_reject ""
200
+ # RuntimeError:
201
+ # Illegal param operation id
202
+ ```
203
+
204
+ ### Payments from bank cards without authorization
205
+
206
+ #### instance-id method
207
+
208
+ Registering an instance of the application.
209
+
210
+ ```ruby
211
+ api = YandexMoney::Api.new(client_id: CLIENT_ID)
212
+ api.get_instance_id # returns string, contains instance id
213
+ ```
214
+
215
+ If `client_id` is wrong - exception will be raised.
216
+
217
+ #### request-external-payment method
218
+
219
+ Creating a payment and checking its parameters.
220
+
221
+ ```ruby
222
+ api = YandexMoney::Api.new(
223
+ client_id: CLIENT_ID,
224
+ instance_id: INSTANCE_ID
225
+ )
226
+ api.request_external_payment({
227
+ pattern_id: "p2p",
228
+ to: "410011285611534",
229
+ amount_due: "1.00",
230
+ message: "test"
231
+ })
232
+ #<OpenStruct status="success", title="Перевод на счет 4100000000000000", contract_amount=50.0, request_id="313230...93134623165", money_source={"payment-card"=>{}}>
233
+ ```
234
+
235
+ #### process-external-payment method
236
+
237
+ Making a payment. The application calls the method up until the final payment status is known (`status`=`success`/`refused`).
238
+ The recommended retry mode is determined by the `next_retry` response field (by default, 5 seconds).
239
+
240
+ ```ruby
241
+ api = YandexMoney::Api.new(instance_id: INSTANCE_ID)
242
+ api.process_external_payment({
243
+ request_id: REQUEST_ID,
244
+ ext_auth_success_uri: "http://example.com/success",
245
+ ext_auth_fail_uri: "http://example.com/fail"
246
+ })
247
+ #<OpenStruct status="ext_auth_required", acs_params={"cps_context_id"=>"31323039373...93134623165", "paymentType"=>"FC"}, acs_uri="https://m.sp-money.yandex.ru/internal/public-api/to-payment-type">
248
+ ```
249
+
250
+ ## Caveats
251
+
252
+ This library is very unstable. Pull requests welcome!
253
+
254
+ ## Contributing
255
+
256
+ 1. Fork it ( https://github.com/yandex-money/yandex-money-sdk-ruby/fork )
257
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
258
+ 3. Write tests with rspec + VCR
259
+ 4. Write code
260
+ 5. Test code
261
+ 6. Commit your changes (`git commit -am 'Add some feature'`)
262
+ 7. Push to the branch (`git push origin my-new-feature`)
263
+ 8. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,261 @@
1
+ require "yandex_money/api/version"
2
+ require "httparty"
3
+ require "uri"
4
+ require "ostruct"
5
+
6
+ module YandexMoney
7
+ class Api
8
+ include HTTParty
9
+
10
+ base_uri "https://sp-money.yandex.ru"
11
+ default_timeout 30
12
+
13
+ attr_accessor :client_url, :code, :token, :instance_id
14
+
15
+ # Returns url to get token
16
+ def initialize(options)
17
+ # TOKEN provided
18
+ if options.length == 1 && options[:token] != nil
19
+ @token = options[:token]
20
+ else
21
+ @client_id = options[:client_id]
22
+ @redirect_uri = options[:redirect_uri]
23
+ @instance_id = options[:instance_id]
24
+ @client_secret = options[:client_secret]
25
+ if options[:scope] != nil
26
+ if @client_secret
27
+ @client_url = send_authorize_request(
28
+ "client_id" => @client_id,
29
+ "response_type" => "code",
30
+ "redirect_uri" => @redirect_uri,
31
+ "scope" => options[:scope],
32
+ "client_secret" => @client_secret
33
+ )
34
+ else
35
+ @client_url = send_authorize_request(
36
+ "client_id" => @client_id,
37
+ "response_type" => "code",
38
+ "redirect_uri" => @redirect_uri,
39
+ "scope" => options[:scope]
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ # obtains and saves token from code
47
+ def obtain_token
48
+ raise "Authorization code not provided" if code == nil
49
+ uri = "/oauth/token"
50
+ if @client_secret
51
+ @token = self.class.post(uri, body: {
52
+ code: @code,
53
+ client_id: @client_id,
54
+ grant_type: "authorization_code",
55
+ redirect_uri: @redirect_url,
56
+ client_secret: @client_secret
57
+ }).parsed_response["access_token"]
58
+ else
59
+ @token = self.class.post(uri, body: {
60
+ code: @code,
61
+ client_id: @client_id,
62
+ grant_type: "authorization_code",
63
+ redirect_uri: @redirect_url
64
+ }).parsed_response["access_token"]
65
+ end
66
+ end
67
+
68
+ # obtains account info
69
+ def account_info
70
+ check_token
71
+ uri = "/api/account-info"
72
+ OpenStruct.new self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
73
+ "Authorization" => "Bearer #{@token}",
74
+ "Content-Type" => "application/x-www-form-urlencoded"
75
+ }).parsed_response
76
+ end
77
+
78
+ # obtains operation history
79
+ def operation_history(options=nil)
80
+ check_token
81
+ uri = "/api/operation-history"
82
+ OpenStruct.new self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
83
+ "Authorization" => "Bearer #{@token}",
84
+ "Content-Type" => "application/x-www-form-urlencoded"
85
+ }, body: options).parsed_response
86
+ end
87
+
88
+ # obtains operation details
89
+ def operation_details(operation_id)
90
+ check_token
91
+ raise "Provide operation_id" if operation_id == nil
92
+ uri = "/api/operation-details"
93
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
94
+ "Authorization" => "Bearer #{@token}",
95
+ "Content-Type" => "application/x-www-form-urlencoded"
96
+ }, body: {
97
+ operation_id: operation_id
98
+ })
99
+
100
+ raise "Insufficient Scope" if request.response.code == "403"
101
+
102
+ details = OpenStruct.new request.parsed_response
103
+ if details.error
104
+ raise details.error.gsub(/_/, " ").capitalize
105
+ else
106
+ details
107
+ end
108
+ end
109
+
110
+ # basic request payment method
111
+ def request_payment(options)
112
+ check_token
113
+ uri = "/api/request-payment"
114
+ response = OpenStruct.new with_http_retries {
115
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
116
+ "Authorization" => "Bearer #{@token}",
117
+ "Content-Type" => "application/x-www-form-urlencoded"
118
+ }, body: options)
119
+
120
+ raise "Insufficient Scope" if request.response.code == "403"
121
+ request.parsed_response
122
+ }
123
+ if response.error
124
+ raise response.error.gsub(/_/, " ").capitalize
125
+ else
126
+ response
127
+ end
128
+ end
129
+
130
+ # basic process payment method
131
+ def process_payment(options)
132
+ check_token
133
+ uri = "/api/process-payment"
134
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
135
+ "Authorization" => "Bearer #{@token}",
136
+ "Content-Type" => "application/x-www-form-urlencoded"
137
+ }, body: options)
138
+
139
+ raise "Insufficient Scope" if request.response.code == "403"
140
+
141
+ response = OpenStruct.new request.parsed_response
142
+
143
+ if response.error
144
+ raise response.error.gsub(/_/, " ").capitalize
145
+ else
146
+ response
147
+ end
148
+ end
149
+
150
+ def get_instance_id
151
+ uri = "/api/instance-id"
152
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
153
+ "Content-Type" => "application/x-www-form-urlencoded"
154
+ }, body: {
155
+ client_id: @client_id
156
+ })
157
+
158
+ if request["status"] == "refused"
159
+ raise request["error"].gsub(/_/, " ").capitalize
160
+ else
161
+ request["instance_id"]
162
+ end
163
+ end
164
+
165
+ def incoming_transfer_accept(operation_id, protection_code = nil)
166
+ uri = "/api/incoming-transfer-accept"
167
+ if protection_code
168
+ request_body = {
169
+ operation_id: operation_id,
170
+ protection_code: protection_code
171
+ }
172
+ else
173
+ request_body = { operation_id: operation_id }
174
+ end
175
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
176
+ "Authorization" => "Bearer #{@token}",
177
+ "Content-Type" => "application/x-www-form-urlencoded"
178
+ }, body: request_body)
179
+
180
+ raise "Insufficient Scope" if request.response.code == "403"
181
+ if request["status"] == "refused"
182
+ if request["protection_code_attempts_available"]
183
+ attemps = ", attemps available: #{request["protection_code_attempts_available"]}"
184
+ else
185
+ attemps = ""
186
+ end
187
+ raise "#{request["error"].gsub(/_/, " ").capitalize}#{attemps}"
188
+ else
189
+ true
190
+ end
191
+ end
192
+
193
+ def incoming_transfer_reject(operation_id)
194
+ uri = "/api/incoming-transfer-reject"
195
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
196
+ "Authorization" => "Bearer #{@token}",
197
+ "Content-Type" => "application/x-www-form-urlencoded"
198
+ }, body: {
199
+ operation_id: operation_id
200
+ })
201
+
202
+ raise "Insufficient Scope" if request.response.code == "403"
203
+ if request["status"] == "refused"
204
+ raise "#{request["error"].gsub(/_/, " ").capitalize}"
205
+ else
206
+ true
207
+ end
208
+ end
209
+
210
+ def request_external_payment(payment_options)
211
+ payment_options[:instance_id] ||= @instance_id
212
+ uri = "/api/request-external-payment"
213
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
214
+ "Content-Type" => "application/x-www-form-urlencoded"
215
+ }, body: payment_options)
216
+ raise "Insufficient Scope" if request.response.code == "403"
217
+ if request["status"] == "refused"
218
+ raise "#{request["error"].gsub(/_/, " ").capitalize}"
219
+ else
220
+ OpenStruct.new request.parsed_response
221
+ end
222
+ end
223
+
224
+ def process_external_payment(payment_options)
225
+ payment_options[:instance_id] ||= @instance_id
226
+ uri = "/api/process-external-payment"
227
+ request = self.class.post(uri, base_uri: "https://money.yandex.ru", headers: {
228
+ "Content-Type" => "application/x-www-form-urlencoded"
229
+ }, body: payment_options)
230
+ raise "Insufficient Scope" if request.response.code == "403"
231
+ if request["status"] == "refused"
232
+ raise "#{request["error"].gsub(/_/, " ").capitalize}"
233
+ elsif request["status"] == "in_progress"
234
+ raise "in progress", request["next_retry"]
235
+ else
236
+ OpenStruct.new request.parsed_response
237
+ end
238
+ end
239
+
240
+ private
241
+
242
+ # Retry when errors
243
+ def with_http_retries(&block)
244
+ begin
245
+ yield
246
+ rescue Errno::ECONNREFUSED, SocketError, Net::ReadTimeout
247
+ sleep 1
248
+ retry
249
+ end
250
+ end
251
+
252
+ def check_token
253
+ raise "Token not provided" unless @token
254
+ end
255
+
256
+ def send_authorize_request(options)
257
+ uri = "/oauth/authorize"
258
+ self.class.post(uri, body: options).request.path.to_s
259
+ end
260
+ end
261
+ end