zai_payment 1.3.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/badges/coverage.json +1 -1
- data/{CHANGELOG.md → changelog.md} +57 -12
- data/{CONTRIBUTING.md → contributing.md} +6 -6
- data/docs/{AUTHENTICATION.md → authentication.md} +2 -2
- data/docs/items.md +666 -0
- data/docs/{USER_QUICK_REFERENCE.md → user_quick_reference.md} +6 -6
- data/docs/{WEBHOOK_SECURITY_QUICKSTART.md → webhook_security_quickstart.md} +1 -1
- data/docs/{WEBHOOK_SIGNATURE.md → webhook_signature.md} +2 -2
- data/examples/items.md +598 -0
- data/examples/users.md +69 -50
- data/{IMPLEMENTATION.md → implementation.md} +10 -10
- data/{IMPLEMENTATION_SUMMARY.md → implementation_summary.md} +4 -4
- data/lib/zai_payment/resources/item.rb +363 -0
- data/lib/zai_payment/resources/user.rb +61 -23
- data/lib/zai_payment/response.rb +6 -1
- data/lib/zai_payment/version.rb +1 -1
- data/lib/zai_payment.rb +6 -0
- data/{README.md → readme.md} +65 -19
- metadata +22 -19
- /data/{CODE_OF_CONDUCT.md → code_of_conduct.md} +0 -0
- /data/docs/{ARCHITECTURE.md → architecture.md} +0 -0
- /data/docs/{README.md → readme.md} +0 -0
- /data/docs/{USER_ID_FIELD.md → user_id_field.md} +0 -0
- /data/docs/{USERS.md → users.md} +0 -0
- /data/docs/{WEBHOOKS.md → webhooks.md} +0 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ZaiPayment
|
|
4
|
+
module Resources
|
|
5
|
+
# Item resource for managing Zai items (transactions/payments)
|
|
6
|
+
#
|
|
7
|
+
# @see https://developer.hellozai.com/reference/listitems
|
|
8
|
+
class Item
|
|
9
|
+
attr_reader :client
|
|
10
|
+
|
|
11
|
+
# Map of attribute keys to API field names
|
|
12
|
+
FIELD_MAPPING = {
|
|
13
|
+
id: :id,
|
|
14
|
+
name: :name,
|
|
15
|
+
amount: :amount,
|
|
16
|
+
payment_type: :payment_type,
|
|
17
|
+
buyer_id: :buyer_id,
|
|
18
|
+
seller_id: :seller_id,
|
|
19
|
+
fee_ids: :fee_ids,
|
|
20
|
+
description: :description,
|
|
21
|
+
currency: :currency,
|
|
22
|
+
custom_descriptor: :custom_descriptor,
|
|
23
|
+
buyer_url: :buyer_url,
|
|
24
|
+
seller_url: :seller_url,
|
|
25
|
+
tax_invoice: :tax_invoice
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
def initialize(client: nil)
|
|
29
|
+
@client = client || Client.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# List all items
|
|
33
|
+
#
|
|
34
|
+
# @param limit [Integer] number of records to return (default: 10, max: 200)
|
|
35
|
+
# @param offset [Integer] number of records to skip (default: 0)
|
|
36
|
+
# @param search [String] optional text value to search within item description
|
|
37
|
+
# @param created_before [String] optional ISO 8601 date/time to filter items created before
|
|
38
|
+
# (e.g. '2020-02-27T23:54:59Z')
|
|
39
|
+
# @param created_after [String] optional ISO 8601 date/time to filter items created after
|
|
40
|
+
# (e.g. '2020-02-27T23:54:59Z')
|
|
41
|
+
# @return [Response] the API response containing items array
|
|
42
|
+
#
|
|
43
|
+
# @example List all items
|
|
44
|
+
# items = ZaiPayment::Resources::Item.new
|
|
45
|
+
# response = items.list
|
|
46
|
+
# response.data # => [{"id" => "...", "name" => "..."}, ...]
|
|
47
|
+
#
|
|
48
|
+
# @example List items with search
|
|
49
|
+
# response = items.list(search: "product")
|
|
50
|
+
#
|
|
51
|
+
# @example List items created within a date range
|
|
52
|
+
# response = items.list(
|
|
53
|
+
# created_after: "2024-01-01T00:00:00Z",
|
|
54
|
+
# created_before: "2024-12-31T23:59:59Z"
|
|
55
|
+
# )
|
|
56
|
+
#
|
|
57
|
+
# @see https://developer.hellozai.com/reference/listitems
|
|
58
|
+
def list(limit: 10, offset: 0, search: nil, created_before: nil, created_after: nil)
|
|
59
|
+
params = {
|
|
60
|
+
limit: limit,
|
|
61
|
+
offset: offset
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
params[:search] = search if search
|
|
65
|
+
params[:created_before] = created_before if created_before
|
|
66
|
+
params[:created_after] = created_after if created_after
|
|
67
|
+
|
|
68
|
+
client.get('/items', params: params)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Get a specific item by ID
|
|
72
|
+
#
|
|
73
|
+
# @param item_id [String] the item ID
|
|
74
|
+
# @return [Response] the API response containing item details
|
|
75
|
+
#
|
|
76
|
+
# @example
|
|
77
|
+
# items = ZaiPayment::Resources::Item.new
|
|
78
|
+
# response = items.show("item_id")
|
|
79
|
+
# response.data # => {"items" => {"id" => "item_id", "name" => "...", ...}}
|
|
80
|
+
#
|
|
81
|
+
# @see https://developer.hellozai.com/reference/showitem
|
|
82
|
+
def show(item_id)
|
|
83
|
+
validate_id!(item_id, 'item_id')
|
|
84
|
+
client.get("/items/#{item_id}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Create a new item
|
|
88
|
+
#
|
|
89
|
+
# @param attributes [Hash] item attributes
|
|
90
|
+
# @option attributes [String] :id Optional unique ID for the item
|
|
91
|
+
# @option attributes [String] :name (Required) Name of the item
|
|
92
|
+
# @option attributes [Integer] :amount (Required) Amount in cents
|
|
93
|
+
# @option attributes [String] :payment_type (Required) Payment type (1-7, default: 2)
|
|
94
|
+
# @option attributes [String] :buyer_id (Required) Buyer user ID
|
|
95
|
+
# @option attributes [String] :seller_id (Required) Seller user ID
|
|
96
|
+
# @option attributes [Array<String>] :fee_ids Optional array of fee IDs
|
|
97
|
+
# @option attributes [String] :description Optional description
|
|
98
|
+
# @option attributes [String] :currency Optional currency code (e.g., 'AUD')
|
|
99
|
+
# @option attributes [String] :custom_descriptor Optional custom descriptor
|
|
100
|
+
# @option attributes [String] :buyer_url Optional buyer URL
|
|
101
|
+
# @option attributes [String] :seller_url Optional seller URL
|
|
102
|
+
# @option attributes [Boolean] :tax_invoice Optional tax invoice flag
|
|
103
|
+
# @return [Response] the API response containing created item
|
|
104
|
+
#
|
|
105
|
+
# @example
|
|
106
|
+
# items = ZaiPayment::Resources::Item.new
|
|
107
|
+
# response = items.create(
|
|
108
|
+
# name: "Product Purchase",
|
|
109
|
+
# amount: 10000,
|
|
110
|
+
# payment_type: 2,
|
|
111
|
+
# buyer_id: "buyer-123",
|
|
112
|
+
# seller_id: "seller-456",
|
|
113
|
+
# description: "Purchase of product XYZ"
|
|
114
|
+
# )
|
|
115
|
+
#
|
|
116
|
+
# @see https://developer.hellozai.com/reference/createitem
|
|
117
|
+
def create(**attributes)
|
|
118
|
+
validate_create_attributes!(attributes)
|
|
119
|
+
|
|
120
|
+
body = build_item_body(attributes)
|
|
121
|
+
client.post('/items', body: body)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Update an existing item
|
|
125
|
+
#
|
|
126
|
+
# @param item_id [String] the item ID
|
|
127
|
+
# @param attributes [Hash] item attributes to update
|
|
128
|
+
# @option attributes [String] :name Name of the item
|
|
129
|
+
# @option attributes [Integer] :amount Amount in cents
|
|
130
|
+
# @option attributes [String] :description Description
|
|
131
|
+
# @option attributes [String] :buyer_id Buyer user ID
|
|
132
|
+
# @option attributes [String] :seller_id Seller user ID
|
|
133
|
+
# @option attributes [Array<String>] :fee_ids Array of fee IDs
|
|
134
|
+
# @option attributes [String] :custom_descriptor Custom descriptor
|
|
135
|
+
# @option attributes [String] :buyer_url Buyer URL
|
|
136
|
+
# @option attributes [String] :seller_url Seller URL
|
|
137
|
+
# @option attributes [Boolean] :tax_invoice Tax invoice flag
|
|
138
|
+
# @return [Response] the API response containing updated item
|
|
139
|
+
#
|
|
140
|
+
# @example
|
|
141
|
+
# items = ZaiPayment::Resources::Item.new
|
|
142
|
+
# response = items.update(
|
|
143
|
+
# "item_id",
|
|
144
|
+
# name: "Updated Product Name",
|
|
145
|
+
# description: "Updated description"
|
|
146
|
+
# )
|
|
147
|
+
#
|
|
148
|
+
# @see https://developer.hellozai.com/reference/updateitem
|
|
149
|
+
def update(item_id, **attributes)
|
|
150
|
+
validate_id!(item_id, 'item_id')
|
|
151
|
+
|
|
152
|
+
body = build_item_body(attributes)
|
|
153
|
+
|
|
154
|
+
raise Errors::ValidationError, 'At least one attribute must be provided for update' if body.empty?
|
|
155
|
+
|
|
156
|
+
client.patch("/items/#{item_id}", body: body)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Delete an item
|
|
160
|
+
#
|
|
161
|
+
# @param item_id [String] the item ID
|
|
162
|
+
# @return [Response] the API response
|
|
163
|
+
#
|
|
164
|
+
# @example
|
|
165
|
+
# items = ZaiPayment::Resources::Item.new
|
|
166
|
+
# response = items.delete("item_id")
|
|
167
|
+
#
|
|
168
|
+
# @see https://developer.hellozai.com/reference/deleteitem
|
|
169
|
+
def delete(item_id)
|
|
170
|
+
validate_id!(item_id, 'item_id')
|
|
171
|
+
client.delete("/items/#{item_id}")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Show item seller
|
|
175
|
+
#
|
|
176
|
+
# @param item_id [String] the item ID
|
|
177
|
+
# @return [Response] the API response containing seller details
|
|
178
|
+
#
|
|
179
|
+
# @example
|
|
180
|
+
# items = ZaiPayment::Resources::Item.new
|
|
181
|
+
# response = items.show_seller("item_id")
|
|
182
|
+
# response.data # => {"users" => {"id" => "...", "email" => "...", ...}}
|
|
183
|
+
#
|
|
184
|
+
# @see https://developer.hellozai.com/reference/showitemseller
|
|
185
|
+
def show_seller(item_id)
|
|
186
|
+
validate_id!(item_id, 'item_id')
|
|
187
|
+
client.get("/items/#{item_id}/sellers")
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Show item buyer
|
|
191
|
+
#
|
|
192
|
+
# @param item_id [String] the item ID
|
|
193
|
+
# @return [Response] the API response containing buyer details
|
|
194
|
+
#
|
|
195
|
+
# @example
|
|
196
|
+
# items = ZaiPayment::Resources::Item.new
|
|
197
|
+
# response = items.show_buyer("item_id")
|
|
198
|
+
# response.data # => {"users" => {"id" => "...", "email" => "...", ...}}
|
|
199
|
+
#
|
|
200
|
+
# @see https://developer.hellozai.com/reference/showitembuyer
|
|
201
|
+
def show_buyer(item_id)
|
|
202
|
+
validate_id!(item_id, 'item_id')
|
|
203
|
+
client.get("/items/#{item_id}/buyers")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Show item fees
|
|
207
|
+
#
|
|
208
|
+
# @param item_id [String] the item ID
|
|
209
|
+
# @return [Response] the API response containing fees details
|
|
210
|
+
#
|
|
211
|
+
# @example
|
|
212
|
+
# items = ZaiPayment::Resources::Item.new
|
|
213
|
+
# response = items.show_fees("item_id")
|
|
214
|
+
# response.data # => {"fees" => [{"id" => "...", "amount" => "...", ...}]}
|
|
215
|
+
#
|
|
216
|
+
# @see https://developer.hellozai.com/reference/showitemfees
|
|
217
|
+
def show_fees(item_id)
|
|
218
|
+
validate_id!(item_id, 'item_id')
|
|
219
|
+
client.get("/items/#{item_id}/fees")
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Show item wire details
|
|
223
|
+
#
|
|
224
|
+
# @param item_id [String] the item ID
|
|
225
|
+
# @return [Response] the API response containing wire transfer details
|
|
226
|
+
#
|
|
227
|
+
# @example
|
|
228
|
+
# items = ZaiPayment::Resources::Item.new
|
|
229
|
+
# response = items.show_wire_details("item_id")
|
|
230
|
+
# response.data # => {"items" => {"wire_details" => {...}}}
|
|
231
|
+
#
|
|
232
|
+
# @see https://developer.hellozai.com/reference/showitemwiredetails
|
|
233
|
+
def show_wire_details(item_id)
|
|
234
|
+
validate_id!(item_id, 'item_id')
|
|
235
|
+
client.get("/items/#{item_id}/wire_details")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# List item transactions
|
|
239
|
+
#
|
|
240
|
+
# @param item_id [String] the item ID
|
|
241
|
+
# @param limit [Integer] number of records to return (default: 10)
|
|
242
|
+
# @param offset [Integer] number of records to skip (default: 0)
|
|
243
|
+
# @return [Response] the API response containing transactions array
|
|
244
|
+
#
|
|
245
|
+
# @example
|
|
246
|
+
# items = ZaiPayment::Resources::Item.new
|
|
247
|
+
# response = items.list_transactions("item_id")
|
|
248
|
+
# response.data # => {"transactions" => [{"id" => "...", "amount" => "...", ...}]}
|
|
249
|
+
#
|
|
250
|
+
# @see https://developer.hellozai.com/reference/listitemtransactions
|
|
251
|
+
def list_transactions(item_id, limit: 10, offset: 0)
|
|
252
|
+
validate_id!(item_id, 'item_id')
|
|
253
|
+
|
|
254
|
+
params = {
|
|
255
|
+
limit: limit,
|
|
256
|
+
offset: offset
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
client.get("/items/#{item_id}/transactions", params: params)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# List item batch transactions
|
|
263
|
+
#
|
|
264
|
+
# @param item_id [String] the item ID
|
|
265
|
+
# @param limit [Integer] number of records to return (default: 10)
|
|
266
|
+
# @param offset [Integer] number of records to skip (default: 0)
|
|
267
|
+
# @return [Response] the API response containing batch transactions array
|
|
268
|
+
#
|
|
269
|
+
# @example
|
|
270
|
+
# items = ZaiPayment::Resources::Item.new
|
|
271
|
+
# response = items.list_batch_transactions("item_id")
|
|
272
|
+
# response.data # => {"batch_transactions" => [{"id" => "...", ...}]}
|
|
273
|
+
#
|
|
274
|
+
# @see https://developer.hellozai.com/reference/listitembatchtransactions
|
|
275
|
+
def list_batch_transactions(item_id, limit: 10, offset: 0)
|
|
276
|
+
validate_id!(item_id, 'item_id')
|
|
277
|
+
|
|
278
|
+
params = {
|
|
279
|
+
limit: limit,
|
|
280
|
+
offset: offset
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
client.get("/items/#{item_id}/batch_transactions", params: params)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Show item status
|
|
287
|
+
#
|
|
288
|
+
# @param item_id [String] the item ID
|
|
289
|
+
# @return [Response] the API response containing status details
|
|
290
|
+
#
|
|
291
|
+
# @example
|
|
292
|
+
# items = ZaiPayment::Resources::Item.new
|
|
293
|
+
# response = items.show_status("item_id")
|
|
294
|
+
# response.data # => {"items" => {"state" => "...", ...}}
|
|
295
|
+
#
|
|
296
|
+
# @see https://developer.hellozai.com/reference/showitemstatus
|
|
297
|
+
def show_status(item_id)
|
|
298
|
+
validate_id!(item_id, 'item_id')
|
|
299
|
+
client.get("/items/#{item_id}/status")
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
private
|
|
303
|
+
|
|
304
|
+
def validate_id!(value, field_name)
|
|
305
|
+
return unless value.nil? || value.to_s.strip.empty?
|
|
306
|
+
|
|
307
|
+
raise Errors::ValidationError, "#{field_name} is required and cannot be blank"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def validate_presence!(value, field_name)
|
|
311
|
+
return unless value.nil? || value.to_s.strip.empty?
|
|
312
|
+
|
|
313
|
+
raise Errors::ValidationError, "#{field_name} is required and cannot be blank"
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def validate_create_attributes!(attributes)
|
|
317
|
+
validate_required_attributes!(attributes)
|
|
318
|
+
validate_amount!(attributes[:amount]) if attributes[:amount]
|
|
319
|
+
validate_payment_type!(attributes[:payment_type]) if attributes[:payment_type]
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def validate_required_attributes!(attributes)
|
|
323
|
+
required_fields = %i[name amount payment_type buyer_id seller_id]
|
|
324
|
+
|
|
325
|
+
missing_fields = required_fields.select do |field|
|
|
326
|
+
attributes[field].nil? || (attributes[field].respond_to?(:empty?) && attributes[field].to_s.strip.empty?)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
return if missing_fields.empty?
|
|
330
|
+
|
|
331
|
+
raise Errors::ValidationError,
|
|
332
|
+
"Missing required fields: #{missing_fields.join(', ')}"
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def validate_amount!(amount)
|
|
336
|
+
return if amount.is_a?(Integer) && amount.positive?
|
|
337
|
+
|
|
338
|
+
raise Errors::ValidationError, 'amount must be a positive integer (in cents)'
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def validate_payment_type!(payment_type)
|
|
342
|
+
# Payment types: 1-7 (2 is default)
|
|
343
|
+
valid_types = %w[1 2 3 4 5 6 7]
|
|
344
|
+
return if valid_types.include?(payment_type.to_s)
|
|
345
|
+
|
|
346
|
+
raise Errors::ValidationError, 'payment_type must be between 1 and 7'
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def build_item_body(attributes)
|
|
350
|
+
body = {}
|
|
351
|
+
|
|
352
|
+
attributes.each do |key, value|
|
|
353
|
+
next if value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
|
354
|
+
|
|
355
|
+
api_field = FIELD_MAPPING[key]
|
|
356
|
+
body[api_field] = value if api_field
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
body
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|
|
@@ -107,19 +107,22 @@ module ZaiPayment
|
|
|
107
107
|
# @option attributes [String] :id Optional unique ID for the user. If not provided,
|
|
108
108
|
# Zai will generate one automatically. Cannot contain '.' character.
|
|
109
109
|
# Useful for mapping to your existing system's user IDs.
|
|
110
|
+
# @option attributes [String] :user_type User type ('payin' or 'payout').
|
|
111
|
+
# This determines which fields are required.
|
|
110
112
|
# @option attributes [String] :email (Required) user's email address
|
|
111
113
|
# @option attributes [String] :first_name (Required) user's first name
|
|
112
114
|
# @option attributes [String] :last_name (Required) user's last name
|
|
113
115
|
# @option attributes [String] :country (Required) user's country code (ISO 3166-1 alpha-3)
|
|
114
|
-
# @option attributes [String] :
|
|
116
|
+
# @option attributes [String] :address_line1 (Required for payout) user's address line 1
|
|
117
|
+
# @option attributes [String] :city (Required for payout) user's city
|
|
118
|
+
# @option attributes [String] :state (Required for payout) user's state
|
|
119
|
+
# @option attributes [String] :zip (Required for payout) user's postal/zip code
|
|
120
|
+
# @option attributes [String] :dob (Required for payout) user's date of birth (DD/MM/YYYY)
|
|
121
|
+
# @option attributes [String] :device_id device ID for fraud prevention (required when charging card)
|
|
122
|
+
# @option attributes [String] :ip_address IP address for fraud prevention (required when charging card)
|
|
123
|
+
# @option attributes [String] :address_line2 user's address line 2
|
|
115
124
|
# @option attributes [String] :mobile user's mobile phone number (international format with '+')
|
|
116
125
|
# @option attributes [String] :phone user's phone number
|
|
117
|
-
# @option attributes [String] :address_line1 user's address line 1
|
|
118
|
-
# @option attributes [String] :address_line2 user's address line 2
|
|
119
|
-
# @option attributes [String] :city user's city
|
|
120
|
-
# @option attributes [String] :state user's state
|
|
121
|
-
# @option attributes [String] :zip user's postal/zip code
|
|
122
|
-
# @option attributes [String] :dob user's date of birth (DD/MM/YYYY)
|
|
123
126
|
# @option attributes [String] :government_number user's government ID number (SSN, TFN, etc.)
|
|
124
127
|
# @option attributes [String] :drivers_license_number driving license number
|
|
125
128
|
# @option attributes [String] :drivers_license_state state section of the user's driving license
|
|
@@ -129,13 +132,12 @@ module ZaiPayment
|
|
|
129
132
|
# @option attributes [String] :custom_descriptor custom descriptor for bundle direct debit statements
|
|
130
133
|
# @option attributes [String] :authorized_signer_title job title for AMEX merchants (e.g., Director)
|
|
131
134
|
# @option attributes [Hash] :company company details (creates a company for the user)
|
|
132
|
-
# @option attributes [String] :device_id device ID for fraud prevention
|
|
133
|
-
# @option attributes [String] :ip_address IP address for fraud prevention
|
|
134
135
|
# @return [Response] the API response containing created user
|
|
135
136
|
#
|
|
136
137
|
# @example Create a payin user (buyer) with auto-generated ID
|
|
137
138
|
# users = ZaiPayment::Resources::User.new
|
|
138
139
|
# response = users.create(
|
|
140
|
+
# user_type: "payin",
|
|
139
141
|
# email: "buyer@example.com",
|
|
140
142
|
# first_name: "John",
|
|
141
143
|
# last_name: "Doe",
|
|
@@ -146,25 +148,29 @@ module ZaiPayment
|
|
|
146
148
|
# state: "NY",
|
|
147
149
|
# zip: "10001"
|
|
148
150
|
# )
|
|
151
|
+
# # Note: device_id and ip_address are not required at user creation,
|
|
152
|
+
# # but will be required when creating an item and charging a card
|
|
149
153
|
#
|
|
150
154
|
# @example Create a payin user with custom ID
|
|
151
155
|
# users = ZaiPayment::Resources::User.new
|
|
152
156
|
# response = users.create(
|
|
153
157
|
# id: "buyer-#{your_user_id}",
|
|
158
|
+
# user_type: "payin",
|
|
154
159
|
# email: "buyer@example.com",
|
|
155
160
|
# first_name: "John",
|
|
156
161
|
# last_name: "Doe",
|
|
157
162
|
# country: "USA"
|
|
158
163
|
# )
|
|
159
164
|
#
|
|
160
|
-
# @example Create a payout user (seller/merchant)
|
|
165
|
+
# @example Create a payout user (seller/merchant) - individual
|
|
161
166
|
# users = ZaiPayment::Resources::User.new
|
|
162
167
|
# response = users.create(
|
|
168
|
+
# user_type: "payout",
|
|
163
169
|
# email: "seller@example.com",
|
|
164
170
|
# first_name: "Jane",
|
|
165
171
|
# last_name: "Smith",
|
|
166
172
|
# country: "AUS",
|
|
167
|
-
# dob: "
|
|
173
|
+
# dob: "01/01/1990",
|
|
168
174
|
# address_line1: "456 Market St",
|
|
169
175
|
# city: "Sydney",
|
|
170
176
|
# state: "NSW",
|
|
@@ -172,13 +178,19 @@ module ZaiPayment
|
|
|
172
178
|
# mobile: "+61412345678"
|
|
173
179
|
# )
|
|
174
180
|
#
|
|
175
|
-
# @example Create a user with company details
|
|
181
|
+
# @example Create a payout user with company details
|
|
176
182
|
# users = ZaiPayment::Resources::User.new
|
|
177
183
|
# response = users.create(
|
|
184
|
+
# user_type: "payout",
|
|
178
185
|
# email: "business@example.com",
|
|
179
186
|
# first_name: "John",
|
|
180
187
|
# last_name: "Doe",
|
|
181
188
|
# country: "AUS",
|
|
189
|
+
# dob: "15/06/1985",
|
|
190
|
+
# address_line1: "789 Business Ave",
|
|
191
|
+
# city: "Melbourne",
|
|
192
|
+
# state: "VIC",
|
|
193
|
+
# zip: "3000",
|
|
182
194
|
# mobile: "+61412345678",
|
|
183
195
|
# authorized_signer_title: "Director",
|
|
184
196
|
# company: {
|
|
@@ -186,13 +198,12 @@ module ZaiPayment
|
|
|
186
198
|
# legal_name: "ABC Pty Ltd",
|
|
187
199
|
# tax_number: "123456789",
|
|
188
200
|
# business_email: "admin@abc.com",
|
|
189
|
-
# country: "AUS",
|
|
190
|
-
# charge_tax: true,
|
|
191
201
|
# address_line1: "123 Business St",
|
|
192
202
|
# city: "Melbourne",
|
|
193
203
|
# state: "VIC",
|
|
194
204
|
# zip: "3000",
|
|
195
|
-
# phone: "+61398765432"
|
|
205
|
+
# phone: "+61398765432",
|
|
206
|
+
# country: "AUS"
|
|
196
207
|
# }
|
|
197
208
|
# )
|
|
198
209
|
#
|
|
@@ -274,12 +285,23 @@ module ZaiPayment
|
|
|
274
285
|
validate_country!(attributes[:country])
|
|
275
286
|
validate_dob!(attributes[:dob]) if attributes[:dob]
|
|
276
287
|
validate_user_id!(attributes[:id]) if attributes[:id]
|
|
277
|
-
validate_company!(attributes[:company]) if attributes[:company]
|
|
288
|
+
validate_company!(attributes[:company], attributes[:user_type]) if attributes[:company]
|
|
278
289
|
end
|
|
279
290
|
|
|
280
291
|
def validate_required_attributes!(attributes)
|
|
292
|
+
# Base required fields for all users
|
|
281
293
|
required_fields = %i[email first_name last_name country]
|
|
282
294
|
|
|
295
|
+
# Additional required fields for payout users
|
|
296
|
+
user_type = attributes[:user_type]&.to_s&.downcase
|
|
297
|
+
if user_type == USER_TYPE_PAYOUT
|
|
298
|
+
# For payout users, these fields become required
|
|
299
|
+
required_fields += %i[address_line1 city state zip dob]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# NOTE: device_id and ip_address are NOT required at user creation for payin users.
|
|
303
|
+
# They are only required later when an item is created and a card is charged.
|
|
304
|
+
|
|
283
305
|
missing_fields = required_fields.select do |field|
|
|
284
306
|
attributes[field].nil? || attributes[field].to_s.strip.empty?
|
|
285
307
|
end
|
|
@@ -329,15 +351,11 @@ module ZaiPayment
|
|
|
329
351
|
raise Errors::ValidationError, 'id cannot be blank if provided'
|
|
330
352
|
end
|
|
331
353
|
|
|
332
|
-
def validate_company!(company)
|
|
354
|
+
def validate_company!(company, user_type = nil)
|
|
333
355
|
return unless company.is_a?(Hash)
|
|
334
356
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
missing_fields = required_company_fields.select do |field|
|
|
339
|
-
company[field].nil? || company[field].to_s.strip.empty?
|
|
340
|
-
end
|
|
357
|
+
required_fields = required_company_fields(user_type)
|
|
358
|
+
missing_fields = find_missing_company_fields(company, required_fields)
|
|
341
359
|
|
|
342
360
|
return if missing_fields.empty?
|
|
343
361
|
|
|
@@ -345,6 +363,26 @@ module ZaiPayment
|
|
|
345
363
|
"Company is missing required fields: #{missing_fields.join(', ')}"
|
|
346
364
|
end
|
|
347
365
|
|
|
366
|
+
def required_company_fields(user_type)
|
|
367
|
+
base_fields = %i[name legal_name tax_number business_email]
|
|
368
|
+
additional_fields = payout_company?(user_type) ? payout_company_fields : %i[country]
|
|
369
|
+
base_fields + additional_fields
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def payout_company?(user_type)
|
|
373
|
+
user_type&.to_s&.downcase == USER_TYPE_PAYOUT
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def payout_company_fields
|
|
377
|
+
%i[address_line1 city state zip phone country]
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def find_missing_company_fields(company, required_fields)
|
|
381
|
+
required_fields.select do |field|
|
|
382
|
+
company[field].nil? || company[field].to_s.strip.empty?
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
348
386
|
def build_user_body(attributes) # rubocop:disable Metrics/CyclomaticComplexity
|
|
349
387
|
body = {}
|
|
350
388
|
|
data/lib/zai_payment/response.rb
CHANGED
|
@@ -30,9 +30,14 @@ module ZaiPayment
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# Get the data from the response body
|
|
33
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
33
34
|
def data
|
|
34
|
-
body.is_a?(Hash)
|
|
35
|
+
return body unless body.is_a?(Hash)
|
|
36
|
+
|
|
37
|
+
body['webhooks'] || body['users'] || body['items'] || body['fees'] ||
|
|
38
|
+
body['transactions'] || body['batch_transactions'] || body
|
|
35
39
|
end
|
|
40
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
36
41
|
|
|
37
42
|
# Get pagination or metadata info
|
|
38
43
|
def meta
|
data/lib/zai_payment/version.rb
CHANGED
data/lib/zai_payment.rb
CHANGED
|
@@ -12,6 +12,7 @@ require_relative 'zai_payment/client'
|
|
|
12
12
|
require_relative 'zai_payment/response'
|
|
13
13
|
require_relative 'zai_payment/resources/webhook'
|
|
14
14
|
require_relative 'zai_payment/resources/user'
|
|
15
|
+
require_relative 'zai_payment/resources/item'
|
|
15
16
|
|
|
16
17
|
module ZaiPayment
|
|
17
18
|
class << self
|
|
@@ -45,5 +46,10 @@ module ZaiPayment
|
|
|
45
46
|
def users
|
|
46
47
|
@users ||= Resources::User.new(client: Client.new(base_endpoint: :core_base))
|
|
47
48
|
end
|
|
49
|
+
|
|
50
|
+
# @return [ZaiPayment::Resources::Item] item resource instance
|
|
51
|
+
def items
|
|
52
|
+
@items ||= Resources::Item.new
|
|
53
|
+
end
|
|
48
54
|
end
|
|
49
55
|
end
|