synapse_pay_rest 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/synapse_pay_rest.rb +3 -1
  4. data/lib/synapse_pay_rest/error.rb +1 -0
  5. data/lib/synapse_pay_rest/http_client.rb +2 -0
  6. data/lib/synapse_pay_rest/models/node/ach_us_node.rb +11 -19
  7. data/lib/synapse_pay_rest/models/node/base_node.rb +88 -17
  8. data/lib/synapse_pay_rest/models/node/eft_ind_node.rb +7 -6
  9. data/lib/synapse_pay_rest/models/node/eft_np_node.rb +3 -4
  10. data/lib/synapse_pay_rest/models/node/iou_node.rb +6 -15
  11. data/lib/synapse_pay_rest/models/node/node.rb +18 -17
  12. data/lib/synapse_pay_rest/models/node/reserve_us_node.rb +5 -11
  13. data/lib/synapse_pay_rest/models/node/synapse_ind_node.rb +4 -8
  14. data/lib/synapse_pay_rest/models/node/synapse_np_node.rb +2 -8
  15. data/lib/synapse_pay_rest/models/node/synapse_us_node.rb +2 -8
  16. data/lib/synapse_pay_rest/models/node/triumph_subaccount_us_node.rb +17 -0
  17. data/lib/synapse_pay_rest/models/node/unverified_node.rb +1 -1
  18. data/lib/synapse_pay_rest/models/node/wire_int_node.rb +3 -4
  19. data/lib/synapse_pay_rest/models/node/wire_us_node.rb +1 -2
  20. data/lib/synapse_pay_rest/models/transaction/transaction.rb +9 -9
  21. data/lib/synapse_pay_rest/models/user/base_document.rb +12 -16
  22. data/lib/synapse_pay_rest/models/user/document.rb +2 -2
  23. data/lib/synapse_pay_rest/models/user/physical_document.rb +58 -17
  24. data/lib/synapse_pay_rest/models/user/user.rb +27 -10
  25. data/lib/synapse_pay_rest/models/user/virtual_document.rb +7 -8
  26. data/lib/synapse_pay_rest/version.rb +1 -1
  27. data/samples.md +41 -60
  28. data/synapse_pay_rest.gemspec +8 -8
  29. metadata +4 -6
  30. data/lib/synapse_pay_rest/models/node/eft_node.rb +0 -27
  31. data/lib/synapse_pay_rest/models/node/synapse_node.rb +0 -25
  32. data/lib/synapse_pay_rest/models/node/wire_node.rb +0 -38
@@ -1,7 +1,7 @@
1
1
  module SynapsePayRest
2
2
  # Represents a Synapse node allowing any user to hold funds. You can use this
3
3
  # node as a wallet, an escrow account or something else along those lines.
4
- class SynapseUsNode < SynapseNode
4
+ class SynapseUsNode < BaseNode
5
5
  class << self
6
6
  private
7
7
 
@@ -10,13 +10,7 @@ module SynapsePayRest
10
10
  type: 'SYNAPSE-US',
11
11
  nickname: nickname
12
12
  }.merge(options)
13
- payload = super(args)
14
- # optional payload fields
15
- extra = {}
16
- extra['supp_id'] = options[:supp_id] if options[:supp_id]
17
- extra['gateway_restricted'] = options[:gateway_restricted] if options[:gateway_restricted]
18
- payload['extra'] = extra if extra.any?
19
- payload
13
+ super(args)
20
14
  end
21
15
  end
22
16
  end
@@ -0,0 +1,17 @@
1
+ module SynapsePayRest
2
+ # Represents a Synapse node allowing any user to hold funds. You can use this
3
+ # node as a wallet, an escrow account or something else along those lines.
4
+ class TriumphSubaccountUsNode < BaseNode
5
+ class << self
6
+ private
7
+
8
+ def payload_for_create(nickname:, **options)
9
+ args = {
10
+ type: 'TRIUMPH-SUBACCOUNT-US',
11
+ nickname: nickname
12
+ }.merge(options)
13
+ super(args)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -53,7 +53,7 @@ module SynapsePayRest
53
53
  if response['error_code'] == '0'
54
54
  # correct answer
55
55
  @mfa_verified = true
56
- AchUsNode.create_multiple_from_response(user, response['nodes'])
56
+ AchUsNode.multiple_from_response(user, response['nodes'])
57
57
  elsif response['error_code'] == '10' && response['mfa']['message'] == mfa_message
58
58
  # wrong answer (mfa message the same), retry if allowed
59
59
  args = {
@@ -1,6 +1,6 @@
1
1
  module SynapsePayRest
2
2
  # Represents a non-US account for wire payments.
3
- class WireIntNode < WireNode
3
+ class WireIntNode < BaseNode
4
4
  class << self
5
5
  private
6
6
 
@@ -11,12 +11,11 @@ module SynapsePayRest
11
11
  nickname: nickname,
12
12
  bank_name: bank_name,
13
13
  account_number: account_number,
14
+ swift: swift,
14
15
  name_on_account: name_on_account,
15
16
  address: address
16
17
  }.merge(options)
17
- payload = super(args)
18
- payload['info']['swift'] = swift
19
- payload
18
+ super(args)
20
19
  end
21
20
  end
22
21
  end
@@ -1,6 +1,6 @@
1
1
  module SynapsePayRest
2
2
  # Represents a US bank account for processing wire payments.
3
- class WireUsNode < WireNode
3
+ class WireUsNode < BaseNode
4
4
  class << self
5
5
  private
6
6
 
@@ -15,7 +15,6 @@ module SynapsePayRest
15
15
  name_on_account: name_on_account,
16
16
  address: address
17
17
  }.merge(options)
18
-
19
18
  super(args)
20
19
  end
21
20
  end
@@ -54,7 +54,7 @@ module SynapsePayRest
54
54
  amount: amount, currency: currency, ip: ip, **options)
55
55
  node.user.authenticate
56
56
  response = node.user.client.trans.create(node_id: node.id, payload: payload)
57
- create_from_response(node, response)
57
+ from_response(node, response)
58
58
  end
59
59
 
60
60
  # Queries the API for a transaction belonging to the supplied node by transaction id
@@ -72,7 +72,7 @@ module SynapsePayRest
72
72
 
73
73
  node.user.authenticate
74
74
  response = node.user.client.trans.get(node_id: node.id, trans_id: id)
75
- create_from_response(node, response)
75
+ from_response(node, response)
76
76
  end
77
77
 
78
78
  # Queries the API for all transactions belonging to the supplied node and returns
@@ -95,7 +95,7 @@ module SynapsePayRest
95
95
 
96
96
  node.user.authenticate
97
97
  response = node.user.client.trans.get(node_id: node.id, page: page, per_page: per_page)
98
- create_multiple_from_response(node, response['trans'])
98
+ multiple_from_response(node, response['trans'])
99
99
  end
100
100
 
101
101
  # Creates a Transaction from a response hash.
@@ -104,7 +104,7 @@ module SynapsePayRest
104
104
  #
105
105
  # @todo convert the nodes and users in response into User/Node objects
106
106
  # @todo rework to handle multiple fees
107
- def create_from_response(node, response)
107
+ def from_response(node, response)
108
108
  args = {
109
109
  node: node,
110
110
  id: response['_id'],
@@ -156,7 +156,7 @@ module SynapsePayRest
156
156
  payload['extra']['process_on'] = options[:process_in] if options[:process_in]
157
157
  other = {}
158
158
  other['attachments'] = options[:attachments] if options[:attachments]
159
- payload['other'] = other if other.any?
159
+ payload['extra']['other'] = other if other.any?
160
160
  fees = []
161
161
  fee = {}
162
162
  fee['fee'] = options[:fee_amount] if options[:fee_amount]
@@ -169,9 +169,9 @@ module SynapsePayRest
169
169
  payload
170
170
  end
171
171
 
172
- def create_multiple_from_response(node, response)
172
+ def multiple_from_response(node, response)
173
173
  return [] if response.empty?
174
- response.map { |trans_data| create_from_response(node, trans_data) }
174
+ response.map { |trans_data| from_response(node, trans_data) }
175
175
  end
176
176
  end
177
177
 
@@ -191,7 +191,7 @@ module SynapsePayRest
191
191
  def add_comment(comment)
192
192
  payload = {'comment': comment}
193
193
  response = node.user.client.trans.update(node_id: node.id, trans_id: id, payload: payload)
194
- self.class.create_from_response(node, response['trans'])
194
+ self.class.from_response(node, response['trans'])
195
195
  end
196
196
 
197
197
  # Cancels this transaction if it has not already settled.
@@ -201,7 +201,7 @@ module SynapsePayRest
201
201
  # @return [Array<SynapsePayRest::Transaction>] (self)
202
202
  def cancel
203
203
  response = node.user.client.trans.delete(node_id: node.id, trans_id: id)
204
- self.class.create_from_response(node, response)
204
+ self.class.from_response(node, response)
205
205
  end
206
206
 
207
207
  # Checks if two Transaction instances have same id (different instances of same record).
@@ -93,21 +93,21 @@ module SynapsePayRest
93
93
 
94
94
  # Parses multiple base_documents from response
95
95
  # @note Do not call directly (it's automatic).
96
- def create_from_response(user, response)
96
+ def from_response(user, response)
97
97
  base_documents_data = response['documents']
98
98
  base_documents_data.map do |base_document_data|
99
99
  physical_docs = base_document_data['physical_docs'].map do |data|
100
- doc = PhysicalDocument.create_from_response(data)
100
+ doc = PhysicalDocument.from_response(data)
101
101
  doc.base_document = self
102
102
  doc
103
103
  end
104
104
  social_docs = base_document_data['social_docs'].map do |data|
105
- doc = SocialDocument.create_from_response(data)
105
+ doc = SocialDocument.from_response(data)
106
106
  doc.base_document = self
107
107
  doc
108
108
  end
109
109
  virtual_docs = base_document_data['virtual_docs'].map do |data|
110
- doc = VirtualDocument.create_from_response(data)
110
+ doc = VirtualDocument.from_response(data)
111
111
  doc.base_document = self
112
112
  doc
113
113
  end
@@ -166,14 +166,13 @@ module SynapsePayRest
166
166
  def submit
167
167
  user.authenticate
168
168
  response = user.client.users.update(payload: payload_for_submit)
169
- @user = User.create_from_response(user.client, response)
169
+ @user = User.from_response(user.client, response)
170
170
 
171
171
  if id
172
172
  # return updated version of self
173
173
  user.base_documents.find { |doc| doc.id == id }
174
174
  else
175
175
  # first time submission, assume last doc is updated version of self
176
- require 'pry';
177
176
  user.base_documents.last
178
177
  end
179
178
  end
@@ -214,7 +213,7 @@ module SynapsePayRest
214
213
  user.authenticate
215
214
  payload = payload_for_update(changes)
216
215
  response = user.client.users.update(payload: payload)
217
- @user = User.create_from_response(user.client, response)
216
+ @user = User.from_response(user.client, response)
218
217
 
219
218
  if id
220
219
  # return updated version of self
@@ -228,13 +227,12 @@ module SynapsePayRest
228
227
  # Adds one or more physical documents to the base document and submits
229
228
  # them to the API using KYC 2.0 endpoints.
230
229
  #
231
- # @param documents [Array<SynapsePayRest::PhysicalDocument>]
230
+ # @param documents [Array<SynapsePayRest::PhysicalDocument>] (one or more documents)
232
231
  #
233
232
  # @raise [SynapsePayRest::Error]
234
233
  #
235
234
  # @return [SynapsePayRest::BaseDocument] new instance with updated info
236
- def add_physical_documents(documents)
237
- raise ArgumentError, 'must be an Array' unless documents.is_a?(Array)
235
+ def add_physical_documents(*documents)
238
236
  unless documents.first.is_a?(PhysicalDocument)
239
237
  raise ArgumentError, 'must contain a PhysicalDocument'
240
238
  end
@@ -245,13 +243,12 @@ module SynapsePayRest
245
243
  # Adds one or more social documents to the base document and submits
246
244
  # them to the API using KYC 2.0 endpoints.
247
245
  #
248
- # @param documents [Array<SynapsePayRest::SocialDocument>]
246
+ # @param documents [Array<SynapsePayRest::SocialDocument>] (one or more documents)
249
247
  #
250
248
  # @raise [SynapsePayRest::Error]
251
249
  #
252
250
  # @return [SynapsePayRest::BaseDocument] new instance with updated info
253
- def add_social_documents(documents)
254
- raise ArgumentError, 'must be an Array' unless documents.is_a?(Array)
251
+ def add_social_documents(*documents)
255
252
  unless documents.first.is_a?(SocialDocument)
256
253
  raise ArgumentError, 'must contain a SocialDocument'
257
254
  end
@@ -262,13 +259,12 @@ module SynapsePayRest
262
259
  # Adds one or more virtual documents to the base document and submits
263
260
  # them to the API using KYC 2.0 endpoints.
264
261
  #
265
- # @param documents [Array<SynapsePayRest::VirtualDocument>]
262
+ # @param documents [Array<SynapsePayRest::VirtualDocument>] (one or more documents)
266
263
  #
267
264
  # @raise [SynapsePayRest::Error]
268
265
  #
269
266
  # @return [SynapsePayRest::BaseDocument] new instance with updated info
270
- def add_virtual_documents(documents)
271
- raise ArgumentError, 'must be an Array' unless documents.is_a?(Array)
267
+ def add_virtual_documents(*documents)
272
268
  unless documents.first.is_a?(VirtualDocument)
273
269
  raise ArgumentError, 'must contain a VirtualDocument'
274
270
  end
@@ -11,7 +11,7 @@ module SynapsePayRest
11
11
  attr_accessor :base_document, :status, :id, :type, :value, :last_updated
12
12
 
13
13
  class << self
14
- # Creates a document instances but does not submit it to the API. Use
14
+ # Creates a document instance but does not submit it to the API. Use
15
15
  # BaseDocument#create/#update/#add_physical_documents or related methods
16
16
  # to submit the document to the API.
17
17
  #
@@ -34,7 +34,7 @@ module SynapsePayRest
34
34
  end
35
35
 
36
36
  # @note Do not call this method. It is used by child classes only.
37
- def create_from_response(data)
37
+ def from_response(data)
38
38
  self.new(
39
39
  type: data['document_type'],
40
40
  id: data['id'],
@@ -1,29 +1,70 @@
1
+ require 'open-uri'
2
+
1
3
  module SynapsePayRest
2
4
  # Represents physical documents that can be added to a base document.
3
5
  #
4
6
  # @see https://docs.synapsepay.com/docs/user-resources#section-physical-document-types
5
7
  # physical document types
6
8
  class PhysicalDocument < Document
7
- # Converts the document into hash format for use in request JSON.
8
- # @note You shouldn't need to call this directly.
9
- #
10
- # @return [Hash]
11
- def to_hash
12
- {'document_value' => to_base64(value), 'document_type' => type}
13
- end
14
9
 
15
- private
10
+ class << self
11
+ # Creates a document instance but does not submit it to the API. Use
12
+ # BaseDocument#create/#update/#add_physical_documents or related methods
13
+ # to submit the document to the API.
14
+ #
15
+ # @note This should only be called on subclasses of Document, not on
16
+ # Document itself.
17
+ #
18
+ # @param type [String]
19
+ # @param value [String] (optional) padded base64-encoded image ("data:#{mime_type};base64,#{base64}")
20
+ # @param file_path [String] (optional) path to image file
21
+ # @param url [String] (optional) image file url
22
+ # @param byte_stream [String] (optional) byte representation of image
23
+ # @param mime_type [String] (optional) mime type of byte_stream (e.g. 'image/png')
24
+ #
25
+ # @return [SynapsePayRest::Document]
26
+ #
27
+ # @see https://docs.synapsepay.com/docs/user-resources#section-physical-document-types physical document types
28
+ # @see https://docs.synapsepay.com/docs/user-resources#section-social-document-types social document types
29
+ # @see https://docs.synapsepay.com/docs/user-resources#section-virtual-document-types virtual document types
30
+ def create(type:, **options)
31
+ if options[:file_path]
32
+ value = self.file_to_base64(options[:file_path])
33
+ elsif options[:url]
34
+ value = self.url_to_base64(options[:url])
35
+ elsif options[:byte_stream]
36
+ value = self.byte_stream_to_base64(options[:byte_stream], options[:mime_type])
37
+ elsif options[:value]
38
+ value = options[:value]
39
+ end
40
+
41
+ super(type: type, value: value)
42
+ end
43
+
44
+ # Converts the supplied image url to padded base64
45
+ def url_to_base64(url)
46
+ raise ArgumentError, 'url must be a String' unless url.is_a?(String)
47
+ byte_stream = open(url).read
48
+ begin
49
+ mime_type = MIME::Types.type_for(url).first.content_type
50
+ rescue
51
+ mime_type = nil
52
+ end
53
+ byte_stream_to_base64(byte_stream, mime_type)
54
+ end
16
55
 
17
- # Converts the supplied file to base64 encoding so it can be uploaded to API.
18
- def to_base64(file_path)
19
- raise ArgumentError, 'file_path must be a String' unless file_path.is_a?(String)
56
+ # Converts the supplied image file to padded base64
57
+ def file_to_base64(file_path)
58
+ raise ArgumentError, 'file_path must be a String' unless file_path.is_a?(String)
59
+ url_to_base64(file_path)
60
+ end
20
61
 
21
- content_types = MIME::Types.type_for(file_path)
22
- file_type = content_types.first.content_type if content_types.any?
23
- file_contents = open(file_path) { |f| f.read }
24
- encoded = Base64.encode64(file_contents)
25
- mime_padding = "data:#{file_type};base64,"
26
- mime_padding + encoded
62
+ # Converts the supplied image byte stream to padded base64
63
+ def byte_stream_to_base64(byte_stream, mime_type)
64
+ base64 = Base64.encode64(byte_stream)
65
+ padding = "data:#{mime_type};base64,#{base64}"
66
+ padding + base64
67
+ end
27
68
  end
28
69
  end
29
70
  end
@@ -58,7 +58,7 @@ module SynapsePayRest
58
58
 
59
59
  payload = payload_for_create(logins: logins, phone_numbers: phone_numbers, legal_names: legal_names, **options)
60
60
  response = client.users.create(payload: payload)
61
- create_from_response(client, response)
61
+ from_response(client, response)
62
62
  end
63
63
 
64
64
  # Queries the API for a user by id and returns a User instances if found.
@@ -74,7 +74,7 @@ module SynapsePayRest
74
74
  raise ArgumentError, 'id must be a String' unless id.is_a?(String)
75
75
 
76
76
  response = client.users.get(user_id: id)
77
- create_from_response(client, response)
77
+ from_response(client, response)
78
78
  end
79
79
 
80
80
  # Queries the API for all users (with optional filters) and returns them
@@ -101,7 +101,7 @@ module SynapsePayRest
101
101
  end
102
102
 
103
103
  response = client.users.get(page: page, per_page: per_page, query: query)
104
- create_multiple_from_response(client, response['users'])
104
+ multiple_from_response(client, response['users'])
105
105
  end
106
106
 
107
107
  # Queries the API for all users with name/email matching the given query
@@ -141,7 +141,7 @@ module SynapsePayRest
141
141
 
142
142
  # Constructs a user instance from a user response.
143
143
  # @note Do not call directly.
144
- def create_from_response(client, response)
144
+ def from_response(client, response)
145
145
  user = self.new(
146
146
  client: client,
147
147
  id: response['_id'],
@@ -157,16 +157,16 @@ module SynapsePayRest
157
157
  )
158
158
 
159
159
  unless response['documents'].empty?
160
- base_documents = BaseDocument.create_from_response(user, response)
160
+ base_documents = BaseDocument.from_response(user, response)
161
161
  user.base_documents = base_documents
162
162
  end
163
163
  user
164
164
  end
165
165
 
166
- # Calls create_from_response on each member of a response collection.
167
- def create_multiple_from_response(client, response)
166
+ # Calls from_response on each member of a response collection.
167
+ def multiple_from_response(client, response)
168
168
  return [] if response.empty?
169
- response.map { |user_data| create_from_response(client, user_data)}
169
+ response.map { |user_data| from_response(client, user_data)}
170
170
  end
171
171
  end
172
172
 
@@ -202,10 +202,10 @@ module SynapsePayRest
202
202
  raise ArgumentError, 'must provide a key-value pair to update. keys: login,
203
203
  read_only, phone_number, legal_name, remove_phone_number, remove_login'
204
204
  end
205
-
205
+ authenticate
206
206
  response = client.users.update(payload: payload_for_update(options))
207
207
  # return an updated user instance
208
- self.class.create_from_response(client, response)
208
+ self.class.from_response(client, response)
209
209
  end
210
210
 
211
211
  # Creates a new base document for the user. To update an existing base
@@ -435,6 +435,8 @@ module SynapsePayRest
435
435
  # @raise [SynapsePayRest::Error]
436
436
  #
437
437
  # @return [SynapsePayRest::EftIndNode]
438
+ #
439
+ # @deprecated
438
440
  def create_eft_ind_node(**options)
439
441
  EftIndNode.create(user: self, **options)
440
442
  end
@@ -490,6 +492,8 @@ module SynapsePayRest
490
492
  # @raise [SynapsePayRest::Error]
491
493
  #
492
494
  # @return [SynapsePayRest::SynapseIndNode]
495
+ #
496
+ # @deprecated
493
497
  def create_synapse_ind_node(**options)
494
498
  SynapseIndNode.create(user: self, **options)
495
499
  end
@@ -520,6 +524,19 @@ module SynapsePayRest
520
524
  SynapseUsNode.create(user: self, **options)
521
525
  end
522
526
 
527
+ # Creates a TRIUMPH-SUBACCOUNT-US node.
528
+ #
529
+ # @param nickname [String] nickname for the node
530
+ # @param supp_id [String] (optional)
531
+ # @param gateway_restricted [Boolean] (optional)
532
+ #
533
+ # @raise [SynapsePayRest::Error]
534
+ #
535
+ # @return [SynapsePayRest::TriumphSubaccountUsNode]
536
+ def create_triumph_subaccount_us_node(**options)
537
+ TriumphSubaccountUsNode.create(user: self, **options)
538
+ end
539
+
523
540
  # Creates a WIRE-INT node.
524
541
  #
525
542
  # @param nickname [String] nickname for the node