synapse_pay_rest 2.2.3 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.sample +8 -0
- data/.gitignore +2 -2
- data/README.md +3 -19
- data/bin/console +17 -0
- data/lib/synapse_pay_rest/api/transactions.rb +2 -2
- data/lib/synapse_pay_rest/client.rb +1 -1
- data/lib/synapse_pay_rest/error.rb +20 -20
- data/lib/synapse_pay_rest/http_client.rb +10 -4
- data/lib/synapse_pay_rest/models/node/ach_us_node.rb +0 -1
- data/lib/synapse_pay_rest/models/node/base_node.rb +11 -7
- data/lib/synapse_pay_rest/models/node/node.rb +0 -2
- data/lib/synapse_pay_rest/models/node/unverified_node.rb +1 -9
- data/lib/synapse_pay_rest/models/node/wire_us_node.rb +3 -5
- data/lib/synapse_pay_rest/models/transaction/transaction.rb +29 -17
- data/lib/synapse_pay_rest/models/user/base_document.rb +0 -2
- data/lib/synapse_pay_rest/models/user/physical_document.rb +9 -9
- data/lib/synapse_pay_rest/models/user/question.rb +2 -0
- data/lib/synapse_pay_rest/models/user/user.rb +20 -17
- data/lib/synapse_pay_rest/models/user/virtual_document.rb +4 -2
- data/lib/synapse_pay_rest/version.rb +2 -2
- data/samples.md +12 -4
- data/synapse_pay_rest.gemspec +3 -0
- metadata +20 -5
- data/Gemfile.lock +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d201dae4eb740319963ab42443361cd8fad2d5a
|
4
|
+
data.tar.gz: 40d4b70997bebff7e71f30fbc25ddc076c728cc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: accdfae93f38d4d0ca80d50e63afc6a7d30f511f34569c709facd33e954baf6dea7378628dfcca88661d3b1955aefda1cf7fe73e8f49dad754b058cedd8f580b
|
7
|
+
data.tar.gz: a283391d0a7d766425d1ad52c670d5630fa535ad1d03b0eb36198b8ccc20f11d2162f05403c6e8af8d9b58c96c785d8aa1658d24eecc3b091642d9260132b833
|
data/.env.sample
ADDED
data/.gitignore
CHANGED
@@ -30,7 +30,7 @@ build/
|
|
30
30
|
|
31
31
|
# for a library or gem, you might want to ignore these files since the code is
|
32
32
|
# intended to run in multiple environments; otherwise, check them in:
|
33
|
-
|
33
|
+
Gemfile.lock
|
34
34
|
# .ruby-version
|
35
35
|
# .ruby-gemset
|
36
36
|
|
@@ -42,4 +42,4 @@ build/
|
|
42
42
|
## ENV variables and other secrets
|
43
43
|
.env
|
44
44
|
test.txt
|
45
|
-
*.yml
|
45
|
+
*.yml
|
data/README.md
CHANGED
@@ -2,19 +2,8 @@
|
|
2
2
|
|
3
3
|
Native API library for SynapsePay REST v3.x
|
4
4
|
|
5
|
-
Originally developed as a simple wrapper to handle the headers and endpoint URLs for each API request, as of v2.0.0 it now handles creation of User, Node, Transaction and related objects to remove the necessity of dealing with raw payload and response JSON.
|
6
|
-
|
7
5
|
Not all API endpoints are supported.
|
8
6
|
|
9
|
-
**Pre-2.0.0 users**
|
10
|
-
|
11
|
-
There are significant changes but backwards compatibility has been mostly maintained by building on top of the base API wrapper. You can still use the previous classes but note the following changes:
|
12
|
-
|
13
|
-
- `ArgumentError` will be raised for missing payloads or other required arguments, where `RuntimeError` was raised previously.
|
14
|
-
- `development_mode` now defaults to true (gem previously defaulted to production).
|
15
|
-
- KYC 1.0 methods for uploading documents have been deprecated. Please contact SynapsePay if you need to update to KYC 2.0.
|
16
|
-
- API errors will now raise `SynapsePayRest::Error`s instead returning a JSON hash (and sometimes obfuscating the API error message).
|
17
|
-
|
18
7
|
## Installation
|
19
8
|
|
20
9
|
Add this line to your application's Gemfile:
|
@@ -43,16 +32,11 @@ $ gem install synapse_pay_rest
|
|
43
32
|
|
44
33
|
## Contributing
|
45
34
|
|
46
|
-
For minor issues, just open a pull request. For larger changes or features, please email steven@synapsepay.com.Please document and test any public constants/methods. Open an issue or email steven@synapsepay.com if you have any questions.
|
35
|
+
For minor issues, just open a pull request. For larger changes or features, please email steven@synapsepay.com. Please document and test any public constants/methods. Open an issue or email steven@synapsepay.com if you have any questions.
|
47
36
|
|
48
37
|
## Running the Test Suite
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
```
|
53
|
-
CLIENT_ID=your_sandbox_client_id
|
54
|
-
CLIENT_SECRET=your_sandbox_client_secret
|
55
|
-
```
|
39
|
+
If you haven't already, run `cp .env.sample .env` and set the `TEST_CLIENT_ID` and `TEST_CLIENT_SECRET` environment variables.
|
56
40
|
|
57
41
|
To run all tests, execute:
|
58
42
|
|
@@ -60,7 +44,7 @@ To run all tests, execute:
|
|
60
44
|
rake
|
61
45
|
```
|
62
46
|
|
63
|
-
To run a specific file or test
|
47
|
+
To run a specific file or test run:
|
64
48
|
|
65
49
|
```bash
|
66
50
|
m path/to/file:line_number
|
data/bin/console
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'synapse_pay_rest'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require 'pry'
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'dotenv'
|
14
|
+
Dotenv.load
|
15
|
+
|
16
|
+
require 'irb'
|
17
|
+
IRB.start
|
@@ -57,9 +57,9 @@ module SynapsePayRest
|
|
57
57
|
# HTTP response from API
|
58
58
|
#
|
59
59
|
# @return [Hash] API response
|
60
|
-
def create(user_id:, node_id:, payload:)
|
60
|
+
def create(user_id:, node_id:, payload:, idempotency_key: nil)
|
61
61
|
path = create_transaction_path(user_id: user_id, node_id: node_id)
|
62
|
-
client.post(path, payload)
|
62
|
+
client.post(path, payload, idempotency_key: idempotency_key)
|
63
63
|
end
|
64
64
|
|
65
65
|
# Sends a PATCH request to /trans endpoint to update a transaction.
|
@@ -28,7 +28,7 @@ module SynapsePayRest
|
|
28
28
|
def initialize(client_id:, client_secret:, ip_address:, fingerprint: nil,
|
29
29
|
development_mode: true, **options)
|
30
30
|
base_url = if development_mode
|
31
|
-
'https://
|
31
|
+
'https://uat-api.synapsefi.com/v3.1'
|
32
32
|
else
|
33
33
|
'https://synapsepay.com/api/3'
|
34
34
|
end
|
@@ -54,20 +54,20 @@ module SynapsePayRest
|
|
54
54
|
# @todo need to add an error message for various 202 cases (fingerprint, mfa, etc)
|
55
55
|
# @todo doesn't do well when there's an html response from nginx for bad gateway/timeout
|
56
56
|
ERRORS = {
|
57
|
-
400 => SynapsePayRest::Error::BadRequest,
|
58
|
-
401 => SynapsePayRest::Error::Unauthorized,
|
59
|
-
402 => SynapsePayRest::Error::RequestDeclined,
|
60
|
-
403 => SynapsePayRest::Error::Forbidden,
|
61
|
-
404 => SynapsePayRest::Error::NotFound,
|
62
|
-
406 => SynapsePayRest::Error::NotAcceptable,
|
63
|
-
409 => SynapsePayRest::Error::Conflict,
|
64
|
-
415 => SynapsePayRest::Error::UnsupportedMediaType,
|
65
|
-
422 => SynapsePayRest::Error::UnprocessableEntity,
|
66
|
-
429 => SynapsePayRest::Error::TooManyRequests,
|
67
|
-
500 => SynapsePayRest::Error::InternalServerError,
|
68
|
-
502 => SynapsePayRest::Error::BadGateway,
|
69
|
-
503 => SynapsePayRest::Error::ServiceUnavailable,
|
70
|
-
504 => SynapsePayRest::Error::GatewayTimeout
|
57
|
+
'400' => SynapsePayRest::Error::BadRequest,
|
58
|
+
'401' => SynapsePayRest::Error::Unauthorized,
|
59
|
+
'402' => SynapsePayRest::Error::RequestDeclined,
|
60
|
+
'403' => SynapsePayRest::Error::Forbidden,
|
61
|
+
'404' => SynapsePayRest::Error::NotFound,
|
62
|
+
'406' => SynapsePayRest::Error::NotAcceptable,
|
63
|
+
'409' => SynapsePayRest::Error::Conflict,
|
64
|
+
'415' => SynapsePayRest::Error::UnsupportedMediaType,
|
65
|
+
'422' => SynapsePayRest::Error::UnprocessableEntity,
|
66
|
+
'429' => SynapsePayRest::Error::TooManyRequests,
|
67
|
+
'500' => SynapsePayRest::Error::InternalServerError,
|
68
|
+
'502' => SynapsePayRest::Error::BadGateway,
|
69
|
+
'503' => SynapsePayRest::Error::ServiceUnavailable,
|
70
|
+
'504' => SynapsePayRest::Error::GatewayTimeout
|
71
71
|
}.freeze
|
72
72
|
|
73
73
|
# The SynapsePay API Error Code
|
@@ -86,10 +86,10 @@ module SynapsePayRest
|
|
86
86
|
# @param body [String]
|
87
87
|
# @param code [Integer]
|
88
88
|
# @return [SynapsePayRest::Error]
|
89
|
-
def
|
89
|
+
def from_response(body)
|
90
90
|
# require 'pry'; binding.pry
|
91
|
-
|
92
|
-
|
91
|
+
message, error_code, http_code = parse_error(body)
|
92
|
+
klass = ERRORS[http_code] || SynapsePayRest::Error
|
93
93
|
klass.new(message: message, code: error_code, response: body)
|
94
94
|
end
|
95
95
|
|
@@ -97,9 +97,9 @@ module SynapsePayRest
|
|
97
97
|
|
98
98
|
def parse_error(body)
|
99
99
|
if body.nil? || body.empty?
|
100
|
-
['', nil]
|
100
|
+
['', nil, nil]
|
101
101
|
elsif body.is_a?(Hash) && body['error'].is_a?(Hash)
|
102
|
-
[body['error']['en'], body['error_code']]
|
102
|
+
[body['error']['en'], body['error_code'], body['http_code']]
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -112,7 +112,7 @@ module SynapsePayRest
|
|
112
112
|
# @return [SynapsePayRest::Error]
|
113
113
|
def initialize(message: '', code: nil, response: {})
|
114
114
|
super(message)
|
115
|
-
@code
|
115
|
+
@code = code
|
116
116
|
@response = response
|
117
117
|
end
|
118
118
|
end
|
@@ -21,7 +21,7 @@ module SynapsePayRest
|
|
21
21
|
client_secret:, **options)
|
22
22
|
log_to = options[:log_to] || 'stdout'
|
23
23
|
RestClient.log = log_to if options[:logging]
|
24
|
-
@logging
|
24
|
+
@logging = options[:logging]
|
25
25
|
|
26
26
|
@config = {
|
27
27
|
client_id: client_id,
|
@@ -73,11 +73,17 @@ module SynapsePayRest
|
|
73
73
|
#
|
74
74
|
# @param path [String]
|
75
75
|
# @param payload [Hash]
|
76
|
-
#
|
76
|
+
# @param idempotency_key [String] (optional) avoid accidentally performing the same operation twice
|
77
|
+
#
|
77
78
|
# @raise [SynapsePayRest::Error] subclass depends on HTTP response
|
78
79
|
#
|
79
80
|
# @return [Hash] API response
|
80
|
-
def post(path, payload)
|
81
|
+
def post(path, payload, **options)
|
82
|
+
headers = get_headers
|
83
|
+
if options[:idempotency_key]
|
84
|
+
headers = headers.merge({'X-SP-IDEMPOTENCY-KEY' => options[:idempotency_key]})
|
85
|
+
end
|
86
|
+
|
81
87
|
response = with_error_handling { RestClient.post(full_url(path), payload.to_json, headers) }
|
82
88
|
p 'RESPONSE:', JSON.parse(response) if @logging
|
83
89
|
JSON.parse(response)
|
@@ -133,7 +139,7 @@ module SynapsePayRest
|
|
133
139
|
yield
|
134
140
|
rescue RestClient::Exception => e
|
135
141
|
body = JSON.parse(e.response.body)
|
136
|
-
raise Error.
|
142
|
+
raise Error.from_response(body)
|
137
143
|
end
|
138
144
|
end
|
139
145
|
end
|
@@ -24,7 +24,6 @@ module SynapsePayRest
|
|
24
24
|
raise ArgumentError, 'password must be a String' unless password.is_a?(String)
|
25
25
|
|
26
26
|
payload = payload_for_create_via_bank_login(bank_name: bank_name, username: username, password: password)
|
27
|
-
user.authenticate
|
28
27
|
response = user.client.nodes.add(user_id: user.id, payload: payload)
|
29
28
|
# MFA questions
|
30
29
|
if response['mfa']
|
@@ -38,7 +38,6 @@ module SynapsePayRest
|
|
38
38
|
raise ArgumentError, 'nickname must be a String' unless nickname.is_a?(String)
|
39
39
|
|
40
40
|
payload = payload_for_create(nickname: nickname, **options)
|
41
|
-
user.authenticate
|
42
41
|
response = user.client.nodes.add(user_id: user.id, payload: payload)
|
43
42
|
from_response(user, response['nodes'].first)
|
44
43
|
end
|
@@ -64,7 +63,6 @@ module SynapsePayRest
|
|
64
63
|
raise ArgumentError, "type must be nil or in #{NODE_TYPES_TO_CLASSES.keys}"
|
65
64
|
end
|
66
65
|
|
67
|
-
user.authenticate
|
68
66
|
response = user.client.nodes.get(
|
69
67
|
user_id: user.id,
|
70
68
|
page: page,
|
@@ -221,7 +219,8 @@ module SynapsePayRest
|
|
221
219
|
# @param fee_note [String] (optional)
|
222
220
|
# @param fee_to_id [String] (optional) node id to which to send the fee
|
223
221
|
# @param supp_id [String] (optional)
|
224
|
-
#
|
222
|
+
# @param idempotency_key [String] (optional) avoid accidentally performing the same operation twice
|
223
|
+
#
|
225
224
|
# @raise [SynapsePayRest::Error] if HTTP error or invalid argument format
|
226
225
|
#
|
227
226
|
# @return [SynapsePayRest::Transaction]
|
@@ -262,14 +261,19 @@ module SynapsePayRest
|
|
262
261
|
#
|
263
262
|
# @return [:success]
|
264
263
|
def deactivate
|
265
|
-
user.
|
266
|
-
|
267
|
-
|
264
|
+
response = user.client.nodes.delete(user_id: user.id, node_id: id)
|
265
|
+
if response['_id']
|
266
|
+
# api v3.1.1
|
267
|
+
self.class.from_response(user, response)
|
268
|
+
else
|
269
|
+
# api v3.1
|
270
|
+
nil
|
271
|
+
end
|
268
272
|
end
|
269
273
|
|
270
274
|
# Checks if two BaseNode instances have same id (different instances of same record).
|
271
275
|
def ==(other)
|
272
|
-
other.instance_of?(self.class) && !id.nil? &&
|
276
|
+
other.instance_of?(self.class) && !id.nil? && id == other.id
|
273
277
|
end
|
274
278
|
end
|
275
279
|
end
|
@@ -33,7 +33,6 @@ module SynapsePayRest
|
|
33
33
|
raise ArgumentError, 'user must be a User object' unless user.is_a?(User)
|
34
34
|
raise ArgumentError, 'id must be a String' unless id.is_a?(String)
|
35
35
|
|
36
|
-
user.authenticate
|
37
36
|
response = user.client.nodes.get(user_id: user.id, node_id: id)
|
38
37
|
from_response(user, response)
|
39
38
|
end
|
@@ -61,7 +60,6 @@ module SynapsePayRest
|
|
61
60
|
raise ArgumentError, "type must be nil or in #{NODE_TYPES_TO_CLASSES.keys}"
|
62
61
|
end
|
63
62
|
|
64
|
-
user.authenticate
|
65
63
|
response = user.client.nodes.get(
|
66
64
|
user_id: user.id,
|
67
65
|
page: page,
|
@@ -54,16 +54,8 @@ module SynapsePayRest
|
|
54
54
|
# correct answer
|
55
55
|
@mfa_verified = true
|
56
56
|
AchUsNode.multiple_from_response(user, response['nodes'])
|
57
|
-
elsif response['error_code'] == '10' && response['mfa']['message'] == mfa_message
|
58
|
-
# wrong answer (mfa message the same), retry if allowed
|
59
|
-
args = {
|
60
|
-
message: 'incorrect bank login mfa answer',
|
61
|
-
code: response['http_code'],
|
62
|
-
response: response
|
63
|
-
}
|
64
|
-
raise SynapsePayRest::Error, args
|
65
57
|
elsif response['error_code'] == '10'
|
66
|
-
# new additional MFA question
|
58
|
+
# wrong answer or new additional MFA question
|
67
59
|
@mfa_access_token = response['mfa']['access_token']
|
68
60
|
@mfa_message = response['mfa']['message']
|
69
61
|
self
|
@@ -4,16 +4,14 @@ module SynapsePayRest
|
|
4
4
|
class << self
|
5
5
|
private
|
6
6
|
|
7
|
-
def payload_for_create(nickname:,
|
8
|
-
name_on_account:,
|
7
|
+
def payload_for_create(nickname:, account_number:, routing_number:,
|
8
|
+
name_on_account:, **options)
|
9
9
|
args = {
|
10
10
|
type: 'WIRE-US',
|
11
11
|
nickname: nickname,
|
12
|
-
bank_name: bank_name,
|
13
12
|
account_number: account_number,
|
14
13
|
routing_number: routing_number,
|
15
|
-
name_on_account: name_on_account
|
16
|
-
address: address
|
14
|
+
name_on_account: name_on_account
|
17
15
|
}.merge(options)
|
18
16
|
super(args)
|
19
17
|
end
|
@@ -4,8 +4,7 @@ module SynapsePayRest
|
|
4
4
|
# is intended to make it easier to use the API without knowing payload formats
|
5
5
|
# or knowledge of REST.
|
6
6
|
#
|
7
|
-
# @todo use mixins to remove duplication between Node and BaseNode.
|
8
|
-
# better to refactor this into a mixin altogether since this shouldn't be instantiated.
|
7
|
+
# @todo use mixins to remove duplication between Node and BaseNode.
|
9
8
|
# @todo reduce duplicated logic between User/BaseNode/Transaction
|
10
9
|
class Transaction
|
11
10
|
# @!attribute [rw] node
|
@@ -28,11 +27,13 @@ module SynapsePayRest
|
|
28
27
|
# @param ip [String]
|
29
28
|
# @param note [String] (optional)
|
30
29
|
# @param process_in [Integer] (optional) days until processed (default/minimum 1)
|
31
|
-
# @param
|
32
|
-
# @param
|
33
|
-
# @param
|
30
|
+
# @param fees [Array] (optional) fee amounts to add to the transaction. Example: [{fee: 1.0, note: 'Test Fee', to: {id: 'fee_node_id'}}]
|
31
|
+
# @param fee_amount [Float] (deprecated) fee amount to add to the transaction
|
32
|
+
# @param fee_to_id [String] (deprecated) node id to which to send the fee (must be SYNAPSE-US)
|
33
|
+
# @param fee_note [String] (deprecated)
|
34
34
|
# @param supp_id [String] (optional)
|
35
|
-
#
|
35
|
+
# @param idempotency_key [String] (optional)
|
36
|
+
#
|
36
37
|
# @raise [SynapsePayRest::Error] if HTTP error or invalid argument format
|
37
38
|
#
|
38
39
|
# @return [SynapsePayRest::Transaction]
|
@@ -46,16 +47,18 @@ module SynapsePayRest
|
|
46
47
|
raise ArgumentError, 'node must be a type of BaseNode object' unless node.is_a?(BaseNode)
|
47
48
|
raise ArgumentError, 'amount must be a Numeric (Integer or Float)' unless amount.is_a?(Numeric)
|
48
49
|
[to_type, to_id, currency, ip].each do |arg|
|
49
|
-
|
50
|
+
if options[arg] && !options[arg].is_a?(String)
|
51
|
+
raise ArgumentError, "#{arg} must be a String"
|
52
|
+
end
|
50
53
|
end
|
51
54
|
|
52
55
|
payload = payload_for_create(node: node, to_type: to_type, to_id: to_id,
|
53
56
|
amount: amount, currency: currency, ip: ip, **options)
|
54
|
-
node.user.authenticate
|
55
57
|
response = node.user.client.trans.create(
|
56
58
|
user_id: node.user.id,
|
57
59
|
node_id: node.id,
|
58
|
-
payload: payload
|
60
|
+
payload: payload,
|
61
|
+
idempotency_key: options[:idempotency_key],
|
59
62
|
)
|
60
63
|
from_response(node, response)
|
61
64
|
end
|
@@ -73,7 +76,6 @@ module SynapsePayRest
|
|
73
76
|
raise ArgumentError, 'node must be a type of BaseNode object' unless node.is_a?(BaseNode)
|
74
77
|
raise ArgumentError, 'id must be a String' unless id.is_a?(String)
|
75
78
|
|
76
|
-
node.user.authenticate
|
77
79
|
response = node.user.client.trans.get(
|
78
80
|
user_id: node.user.id,
|
79
81
|
node_id: node.id,
|
@@ -100,7 +102,6 @@ module SynapsePayRest
|
|
100
102
|
end
|
101
103
|
end
|
102
104
|
|
103
|
-
node.user.authenticate
|
104
105
|
response = node.user.client.trans.get(
|
105
106
|
user_id: node.user.id,
|
106
107
|
node_id: node.id,
|
@@ -137,11 +138,13 @@ module SynapsePayRest
|
|
137
138
|
from: response['from'],
|
138
139
|
to: response['to'],
|
139
140
|
to_type: response['to']['type'],
|
140
|
-
to_id: response['to']['id']
|
141
|
-
fee_amount: response['fees'].last['fee'],
|
142
|
-
fee_note: response['fees'].last['note'],
|
143
|
-
fee_to_id: response['fees'].last['to']['id'],
|
141
|
+
to_id: response['to']['id']
|
144
142
|
}
|
143
|
+
if response['fees'].any?
|
144
|
+
args[:fee_amount] = response['fees'].first['fee']
|
145
|
+
args[:fee_note] = response['fees'].first['note']
|
146
|
+
args[:fee_to_id] = response['fees'].first['to']['id']
|
147
|
+
end
|
145
148
|
self.new(args)
|
146
149
|
end
|
147
150
|
|
@@ -170,6 +173,7 @@ module SynapsePayRest
|
|
170
173
|
other['attachments'] = options[:attachments] if options[:attachments]
|
171
174
|
payload['extra']['other'] = other if other.any?
|
172
175
|
fees = []
|
176
|
+
# deprecated fee flow
|
173
177
|
fee = {}
|
174
178
|
fee['fee'] = options[:fee_amount] if options[:fee_amount]
|
175
179
|
fee['note'] = options[:fee_note] if options[:fee_note]
|
@@ -177,6 +181,8 @@ module SynapsePayRest
|
|
177
181
|
fee_to['id'] = options[:fee_to_id] if options[:fee_to_id]
|
178
182
|
fee['to'] = fee_to if fee_to.any?
|
179
183
|
fees << fee if fee.any?
|
184
|
+
# new fee flow
|
185
|
+
fees = options[:fees] if options[:fees]
|
180
186
|
payload['fees'] = fees if fees.any?
|
181
187
|
payload
|
182
188
|
end
|
@@ -208,7 +214,13 @@ module SynapsePayRest
|
|
208
214
|
trans_id: id,
|
209
215
|
payload: payload
|
210
216
|
)
|
211
|
-
|
217
|
+
if response['trans']
|
218
|
+
# api v3.1
|
219
|
+
self.class.from_response(node, response['trans'])
|
220
|
+
else
|
221
|
+
# api v3.1.1
|
222
|
+
self.class.from_response(node, response)
|
223
|
+
end
|
212
224
|
end
|
213
225
|
|
214
226
|
# Cancels this transaction if it has not already settled.
|
@@ -227,7 +239,7 @@ module SynapsePayRest
|
|
227
239
|
|
228
240
|
# Checks if two Transaction instances have same id (different instances of same record).
|
229
241
|
def ==(other)
|
230
|
-
other.instance_of?(self.class) && !id.nil? &&
|
242
|
+
other.instance_of?(self.class) && !id.nil? && id == other.id
|
231
243
|
end
|
232
244
|
end
|
233
245
|
end
|
@@ -164,7 +164,6 @@ module SynapsePayRest
|
|
164
164
|
#
|
165
165
|
# @return [SynapsePayRest::BaseDocument] new instance with updated info (id will be different if email or phone changed)
|
166
166
|
def submit
|
167
|
-
user.authenticate
|
168
167
|
response = user.client.users.update(user_id: user.id, payload: payload_for_submit)
|
169
168
|
@user = User.from_response(user.client, response)
|
170
169
|
|
@@ -210,7 +209,6 @@ module SynapsePayRest
|
|
210
209
|
if changes.empty?
|
211
210
|
raise ArgumentError, 'must provide some key-value pairs to update'
|
212
211
|
end
|
213
|
-
user.authenticate
|
214
212
|
payload = payload_for_update(changes)
|
215
213
|
response = user.client.users.update(user_id: user.id, payload: payload)
|
216
214
|
@user = User.from_response(user.client, response)
|
@@ -11,19 +11,19 @@ module SynapsePayRest
|
|
11
11
|
# Creates a document instance but does not submit it to the API. Use
|
12
12
|
# BaseDocument#create/#update/#add_physical_documents or related methods
|
13
13
|
# to submit the document to the API.
|
14
|
-
#
|
15
|
-
# @note This should only be called on subclasses of Document, not on
|
14
|
+
#
|
15
|
+
# @note This should only be called on subclasses of Document, not on
|
16
16
|
# Document itself.
|
17
|
-
#
|
17
|
+
#
|
18
18
|
# @param type [String]
|
19
19
|
# @param value [String] (optional) padded base64-encoded image ("data:#{mime_type};base64,#{base64}")
|
20
20
|
# @param file_path [String] (optional) path to image file
|
21
21
|
# @param url [String] (optional) image file url
|
22
22
|
# @param byte_stream [String] (optional) byte representation of image
|
23
23
|
# @param mime_type [String] (optional) mime type of byte_stream (e.g. 'image/png')
|
24
|
-
#
|
24
|
+
#
|
25
25
|
# @return [SynapsePayRest::Document]
|
26
|
-
#
|
26
|
+
#
|
27
27
|
# @see https://docs.synapsepay.com/docs/user-resources#section-physical-document-types physical document types
|
28
28
|
# @see https://docs.synapsepay.com/docs/user-resources#section-social-document-types social document types
|
29
29
|
# @see https://docs.synapsepay.com/docs/user-resources#section-virtual-document-types virtual document types
|
@@ -37,7 +37,7 @@ module SynapsePayRest
|
|
37
37
|
elsif options[:value]
|
38
38
|
value = options[:value]
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
super(type: type, value: value)
|
42
42
|
end
|
43
43
|
|
@@ -46,7 +46,8 @@ module SynapsePayRest
|
|
46
46
|
raise ArgumentError, 'url must be a String' unless url.is_a?(String)
|
47
47
|
byte_stream = open(url).read
|
48
48
|
begin
|
49
|
-
|
49
|
+
# remove any query params to get the mime type
|
50
|
+
mime_type = MIME::Types.type_for(url.gsub(/\?.*$/, '')).first.content_type
|
50
51
|
rescue
|
51
52
|
mime_type = nil
|
52
53
|
end
|
@@ -62,8 +63,7 @@ module SynapsePayRest
|
|
62
63
|
# Converts the supplied image byte stream to padded base64
|
63
64
|
def byte_stream_to_base64(byte_stream, mime_type)
|
64
65
|
base64 = Base64.encode64(byte_stream)
|
65
|
-
|
66
|
-
padding + base64
|
66
|
+
"data:#{mime_type};base64,#{base64}"
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -4,8 +4,7 @@ module SynapsePayRest
|
|
4
4
|
# is intended to make it easier to use the API without knowing payload formats
|
5
5
|
# or knowledge of REST.
|
6
6
|
#
|
7
|
-
# @todo use mixins to remove duplication between Node and BaseNode.
|
8
|
-
# better to refactor this into a mixin altogether since this shouldn't be instantiated.
|
7
|
+
# @todo use mixins to remove duplication between Node and BaseNode.
|
9
8
|
# @todo reduce duplicated logic between User/BaseNode/Transaction
|
10
9
|
class User
|
11
10
|
# @!attribute [rw] base_documents
|
@@ -89,6 +88,8 @@ module SynapsePayRest
|
|
89
88
|
# @raise [SynapsePayRest::Error] if HTTP error or invalid argument format
|
90
89
|
#
|
91
90
|
# @return [Array<SynapsePayRest::User>]
|
91
|
+
#
|
92
|
+
# @note users created this way are not automatically OAuthed
|
92
93
|
def all(client:, page: nil, per_page: nil, query: nil)
|
93
94
|
raise ArgumentError, 'client must be a SynapsePayRest::Client' unless client.is_a?(Client)
|
94
95
|
[page, per_page].each do |arg|
|
@@ -116,6 +117,8 @@ module SynapsePayRest
|
|
116
117
|
# @raise [SynapsePayRest::Error] if HTTP error or invalid argument format
|
117
118
|
#
|
118
119
|
# @return [Array<SynapsePayRest::User>]
|
120
|
+
#
|
121
|
+
# @note users created this way are not automatically OAuthed
|
119
122
|
def search(client:, query:, page: nil, per_page: nil)
|
120
123
|
all(client: client, query: query, page: page, per_page: per_page)
|
121
124
|
end
|
@@ -141,7 +144,7 @@ module SynapsePayRest
|
|
141
144
|
|
142
145
|
# Constructs a user instance from a user response.
|
143
146
|
# @note Do not call directly.
|
144
|
-
def from_response(client, response)
|
147
|
+
def from_response(client, response, oauth: true)
|
145
148
|
user = self.new(
|
146
149
|
client: client,
|
147
150
|
id: response['_id'],
|
@@ -160,13 +163,14 @@ module SynapsePayRest
|
|
160
163
|
base_documents = BaseDocument.from_response(user, response)
|
161
164
|
user.base_documents = base_documents
|
162
165
|
end
|
163
|
-
user
|
166
|
+
oauth ? user.authenticate : user
|
164
167
|
end
|
165
168
|
|
166
169
|
# Calls from_response on each member of a response collection.
|
170
|
+
# @note users created this way are not automatically OAuthed
|
167
171
|
def multiple_from_response(client, response)
|
168
172
|
return [] if response.empty?
|
169
|
-
response.map { |user_data| from_response(client, user_data)}
|
173
|
+
response.map { |user_data| from_response(client.dup, user_data, oauth: false)}
|
170
174
|
end
|
171
175
|
end
|
172
176
|
|
@@ -177,6 +181,16 @@ module SynapsePayRest
|
|
177
181
|
@base_documents ||= []
|
178
182
|
end
|
179
183
|
|
184
|
+
# Updates the oauth token.
|
185
|
+
#
|
186
|
+
# @raise [SynapsePayRest::Error]
|
187
|
+
#
|
188
|
+
# @return [SynapsePayRest::User] (self)
|
189
|
+
def authenticate
|
190
|
+
client.users.refresh(user_id: id, payload: payload_for_refresh)
|
191
|
+
self
|
192
|
+
end
|
193
|
+
|
180
194
|
# Updates the given key value pairs.
|
181
195
|
#
|
182
196
|
# @param login [Hash]
|
@@ -201,7 +215,6 @@ module SynapsePayRest
|
|
201
215
|
raise ArgumentError, 'must provide a key-value pair to update. keys: login,
|
202
216
|
read_only, phone_number, legal_name, remove_phone_number, remove_login'
|
203
217
|
end
|
204
|
-
authenticate
|
205
218
|
response = client.users.update(user_id: id, payload: payload_for_update(options))
|
206
219
|
# return an updated user instance
|
207
220
|
self.class.from_response(client, response)
|
@@ -301,16 +314,6 @@ module SynapsePayRest
|
|
301
314
|
update(remove_phone_number: phone_number)
|
302
315
|
end
|
303
316
|
|
304
|
-
# Updates the user's oauth token.
|
305
|
-
#
|
306
|
-
# @raise [SynapsePayRest::Error]
|
307
|
-
#
|
308
|
-
# @return [SynapsePayRest::User] (self)
|
309
|
-
def authenticate
|
310
|
-
client.users.refresh(user_id: id, payload: payload_for_refresh)
|
311
|
-
self
|
312
|
-
end
|
313
|
-
|
314
317
|
# Step 1 of fingerprint registration. Requests a new fingerprint be
|
315
318
|
# registered to the user.
|
316
319
|
#
|
@@ -582,7 +585,7 @@ module SynapsePayRest
|
|
582
585
|
|
583
586
|
# Checks if two User instances have same id (different instances of same record).
|
584
587
|
def ==(other)
|
585
|
-
other.instance_of?(self.class) && !id.nil? &&
|
588
|
+
other.instance_of?(self.class) && !id.nil? && id == other.id
|
586
589
|
end
|
587
590
|
|
588
591
|
private
|
@@ -27,10 +27,9 @@ module SynapsePayRest
|
|
27
27
|
#
|
28
28
|
# @return [SynapsePayRest::VirtualDocument] (self)
|
29
29
|
#
|
30
|
-
# @
|
30
|
+
# @deprecated
|
31
31
|
def submit_kba
|
32
32
|
user = base_document.user
|
33
|
-
user.authenticate()
|
34
33
|
response = user.client.users.update(user_id: user.id, payload: payload_for_kba)
|
35
34
|
user = User.from_response(user.client, response)
|
36
35
|
base_doc = user.base_documents.find { |doc| doc.id == base_document.id }
|
@@ -38,6 +37,8 @@ module SynapsePayRest
|
|
38
37
|
end
|
39
38
|
|
40
39
|
# Maps question set from response to Question objects.
|
40
|
+
#
|
41
|
+
# @deprecated
|
41
42
|
def add_question_set(question_set_data)
|
42
43
|
questions = question_set_data['questions'].map do |question_info|
|
43
44
|
# re-map question/answer hash structure
|
@@ -58,6 +59,7 @@ module SynapsePayRest
|
|
58
59
|
|
59
60
|
private
|
60
61
|
|
62
|
+
# @deprecated
|
61
63
|
def payload_for_kba
|
62
64
|
{
|
63
65
|
'documents' => [{
|
data/samples.md
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
+
# Setup
|
2
|
+
|
3
|
+
First, run `cp .env.sample .env` if you haven't already and make sure `CLIENT_ID`, `CLIENT_SECRET`, and `FINGERPRINT` are set.
|
4
|
+
|
5
|
+
Start a console that will load this gem and your settings from `.env` automatically.
|
6
|
+
|
7
|
+
```
|
8
|
+
$ ./bin/console
|
9
|
+
```
|
10
|
+
|
1
11
|
## Initialization
|
2
12
|
|
3
13
|
```ruby
|
4
|
-
require 'synapse_pay_rest'
|
5
|
-
|
6
14
|
args = {
|
7
15
|
# synapse client_id
|
8
16
|
client_id: ENV.fetch('CLIENT_ID'),
|
@@ -272,7 +280,7 @@ base_doc = virtual_doc.base_document
|
|
272
280
|
|
273
281
|
## Node Methods
|
274
282
|
|
275
|
-
#### All Nodes for a User
|
283
|
+
#### All Nodes for a User
|
276
284
|
|
277
285
|
##### a) User#nodes
|
278
286
|
|
@@ -310,7 +318,7 @@ Returns a collection of `AchUsNode`s associated with the account unless bank req
|
|
310
318
|
|
311
319
|
```ruby
|
312
320
|
login_info = {
|
313
|
-
bank_name: '
|
321
|
+
bank_name: 'fake',
|
314
322
|
username: 'synapse_good',
|
315
323
|
password: 'test1234'
|
316
324
|
}
|
data/synapse_pay_rest.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
|
20
|
+
s.required_ruby_version = '>= 2.1.0'
|
21
|
+
|
20
22
|
s.add_dependency 'rest-client', '~> 2.0'
|
21
23
|
|
22
24
|
s.add_development_dependency 'bundler', '~> 1.10'
|
@@ -26,4 +28,5 @@ Gem::Specification.new do |s|
|
|
26
28
|
s.add_development_dependency 'dotenv', '~> 2.1.1'
|
27
29
|
s.add_development_dependency 'faker', '~> 1.6.6'
|
28
30
|
s.add_development_dependency 'simplecov', '~> 0.12.0'
|
31
|
+
s.add_development_dependency 'm', '~> 1.5.0'
|
29
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: synapse_pay_rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Broderick
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-02-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -123,18 +123,33 @@ dependencies:
|
|
123
123
|
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: 0.12.0
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: m
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.5.0
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 1.5.0
|
126
140
|
description:
|
127
141
|
email: help@synapsepay.com
|
128
142
|
executables: []
|
129
143
|
extensions: []
|
130
144
|
extra_rdoc_files: []
|
131
145
|
files:
|
146
|
+
- ".env.sample"
|
132
147
|
- ".gitignore"
|
133
148
|
- Gemfile
|
134
|
-
- Gemfile.lock
|
135
149
|
- LICENSE
|
136
150
|
- README.md
|
137
151
|
- Rakefile
|
152
|
+
- bin/console
|
138
153
|
- lib/synapse_pay_rest.rb
|
139
154
|
- lib/synapse_pay_rest/api/nodes.rb
|
140
155
|
- lib/synapse_pay_rest/api/transactions.rb
|
@@ -179,7 +194,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
194
|
requirements:
|
180
195
|
- - ">="
|
181
196
|
- !ruby/object:Gem::Version
|
182
|
-
version:
|
197
|
+
version: 2.1.0
|
183
198
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
199
|
requirements:
|
185
200
|
- - ">="
|
@@ -187,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
202
|
version: '0'
|
188
203
|
requirements: []
|
189
204
|
rubyforge_project:
|
190
|
-
rubygems_version: 2.
|
205
|
+
rubygems_version: 2.6.10
|
191
206
|
signing_key:
|
192
207
|
specification_version: 4
|
193
208
|
summary: SynapsePay v3 Rest Native API Library
|
data/Gemfile.lock
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
synapse_pay_rest (2.0.0)
|
5
|
-
rest-client (~> 2.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
ansi (1.5.0)
|
11
|
-
builder (3.2.2)
|
12
|
-
docile (1.1.5)
|
13
|
-
domain_name (0.5.20160826)
|
14
|
-
unf (>= 0.0.5, < 1.0.0)
|
15
|
-
dotenv (2.1.1)
|
16
|
-
faker (1.6.6)
|
17
|
-
i18n (~> 0.5)
|
18
|
-
http-cookie (1.0.3)
|
19
|
-
domain_name (~> 0.5)
|
20
|
-
i18n (0.7.0)
|
21
|
-
json (1.8.3)
|
22
|
-
mime-types (3.1)
|
23
|
-
mime-types-data (~> 3.2015)
|
24
|
-
mime-types-data (3.2016.0521)
|
25
|
-
minitest (5.8.2)
|
26
|
-
minitest-reporters (1.1.5)
|
27
|
-
ansi
|
28
|
-
builder
|
29
|
-
minitest (>= 5.0)
|
30
|
-
ruby-progressbar
|
31
|
-
netrc (0.11.0)
|
32
|
-
rake (10.4.2)
|
33
|
-
rest-client (2.0.0)
|
34
|
-
http-cookie (>= 1.0.2, < 2.0)
|
35
|
-
mime-types (>= 1.16, < 4.0)
|
36
|
-
netrc (~> 0.8)
|
37
|
-
ruby-progressbar (1.7.5)
|
38
|
-
simplecov (0.12.0)
|
39
|
-
docile (~> 1.1.0)
|
40
|
-
json (>= 1.8, < 3)
|
41
|
-
simplecov-html (~> 0.10.0)
|
42
|
-
simplecov-html (0.10.0)
|
43
|
-
unf (0.1.4)
|
44
|
-
unf_ext
|
45
|
-
unf_ext (0.0.7.2)
|
46
|
-
|
47
|
-
PLATFORMS
|
48
|
-
ruby
|
49
|
-
|
50
|
-
DEPENDENCIES
|
51
|
-
bundler (~> 1.10)
|
52
|
-
dotenv (~> 2.1.1)
|
53
|
-
faker (~> 1.6.6)
|
54
|
-
minitest (~> 5.8.2)
|
55
|
-
minitest-reporters (~> 1.1.5)
|
56
|
-
rake (~> 10.0)
|
57
|
-
simplecov (~> 0.12.0)
|
58
|
-
synapse_pay_rest!
|
59
|
-
|
60
|
-
BUNDLED WITH
|
61
|
-
1.13.0
|