agms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +15 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +4 -0
  4. data/README.md +51 -0
  5. data/Rakefile +40 -0
  6. data/agms.gemspec +29 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +7 -0
  9. data/example/hpp.rb +18 -0
  10. data/example/invoicing.rb +23 -0
  11. data/example/recurring.rb +23 -0
  12. data/example/report.rb +16 -0
  13. data/example/safe.rb +17 -0
  14. data/example/transaction.rb +17 -0
  15. data/init.yml +9 -0
  16. data/lib/agms.rb +59 -0
  17. data/lib/agms/agms.rb +109 -0
  18. data/lib/agms/configuration.rb +71 -0
  19. data/lib/agms/connect.rb +176 -0
  20. data/lib/agms/error/agms_error.rb +9 -0
  21. data/lib/agms/error/authentication_error.rb +7 -0
  22. data/lib/agms/error/authorization_error.rb +7 -0
  23. data/lib/agms/error/client_error_error.rb +7 -0
  24. data/lib/agms/error/configuation_error.rb +7 -0
  25. data/lib/agms/error/down_for_maintenance_error.rb +7 -0
  26. data/lib/agms/error/forged_query_String_error.rb +7 -0
  27. data/lib/agms/error/invalid_parameter_error.rb +7 -0
  28. data/lib/agms/error/invalid_request_error.rb +7 -0
  29. data/lib/agms/error/invalid_signature_error.rb +7 -0
  30. data/lib/agms/error/not_found_error.rb +7 -0
  31. data/lib/agms/error/request_validation_error.rb +7 -0
  32. data/lib/agms/error/response_error.rb +7 -0
  33. data/lib/agms/error/server_error_error.rb +7 -0
  34. data/lib/agms/error/ssl_certificate_error.rb +7 -0
  35. data/lib/agms/error/unexpected_error.rb +7 -0
  36. data/lib/agms/error/upgrade_required_error.rb +7 -0
  37. data/lib/agms/hpp.rb +65 -0
  38. data/lib/agms/invoicing.rb +63 -0
  39. data/lib/agms/recurring.rb +76 -0
  40. data/lib/agms/report.rb +53 -0
  41. data/lib/agms/request/hpp_request.rb +181 -0
  42. data/lib/agms/request/invoicing_request.rb +8 -0
  43. data/lib/agms/request/recurring_request.rb +115 -0
  44. data/lib/agms/request/report_request.rb +106 -0
  45. data/lib/agms/request/request.rb +455 -0
  46. data/lib/agms/request/safe_request.rb +211 -0
  47. data/lib/agms/request/transaction_request.rb +217 -0
  48. data/lib/agms/response/hpp_response.rb +39 -0
  49. data/lib/agms/response/invoicing_response.rb +10 -0
  50. data/lib/agms/response/recurring_response.rb +28 -0
  51. data/lib/agms/response/report_response.rb +141 -0
  52. data/lib/agms/response/response.rb +48 -0
  53. data/lib/agms/response/safe_response.rb +51 -0
  54. data/lib/agms/response/transaction_response.rb +50 -0
  55. data/lib/agms/safe.rb +66 -0
  56. data/lib/agms/transaction.rb +37 -0
  57. data/lib/agms/version.rb +3 -0
  58. metadata +156 -0
@@ -0,0 +1,106 @@
1
+ module Agms
2
+ class ReportRequest < Request
3
+ # A class representing AGMS Report Request objects.
4
+
5
+ alias AgmsAutoValidate autoValidate
6
+
7
+ def initialize(op)
8
+ super(op)
9
+ @trans_fields = {
10
+ :TransactionType => {:setting => '', :value => ''},
11
+ :PaymentType => {:setting => '', :value => 'creditcard'},
12
+ :Amount => {:setting => '', :value => ''}, # Required for sale or auth
13
+ :FirstName => {:setting => '', :value => ''},
14
+ :LastName => {:setting => '', :value => ''},
15
+ :Company => {:setting => '', :value => ''},
16
+ :Address1 => {:setting => '', :value => ''},
17
+ :Address2 => {:setting => '', :value => ''},
18
+ :City => {:setting => '', :value => ''},
19
+ :State => {:setting => '', :value => ''},
20
+ :Zip => {:setting => '', :value => ''},
21
+ :Country => {:setting => '', :value => ''},
22
+ :Phone => {:setting => '', :value => ''},
23
+ :Fax => {:setting => '', :value => ''},
24
+ :EMail => {:setting => '', :value => ''},
25
+ :ProcessorID => {:setting => '', :value => ''},
26
+ :TransactionID => {:setting => '', :value => ''},
27
+ :SAFE_ID => {:setting => '', :value => ''},
28
+ :StartDate => {:setting => '', :value => ''},
29
+ :EndDate => {:setting => '', :value => ''},
30
+ :CreditCardLast4 => {:setting => '', :value => ''}
31
+ }
32
+
33
+ @safe_fields = {
34
+ :Active => {:setting => '', :value => ''},
35
+ :PaymentType => {:setting => '', :value => 'creditcard'},
36
+ :FirstName => {:setting => '', :value => ''},
37
+ :LastName => {:setting => '', :value => ''},
38
+ :Company => {:setting => '', :value => ''},
39
+ :EMail => {:setting => '', :value => ''},
40
+ :SafeID => {:setting => '', :value => ''},
41
+ :StartDate => {:setting => '', :value => ''},
42
+ :EndDate => {:setting => '', :value => ''},
43
+ :Expiring30 => {:setting => '', :value => ''}
44
+ }
45
+
46
+ @numeric = %w(Amount ProcessorID TransactionID CreditCardLast4)
47
+
48
+ @date = %w(StartDate EndDate)
49
+
50
+ @digit_2 = %w(State)
51
+
52
+ if @op == 'TransactionAPI'
53
+ @fields = @trans_fields
54
+ # Override mapping with api-specific field maps
55
+ @mapping[:safe_id] = :Safe_ID
56
+ @mapping[:gateway_username] = :GatewayUsername
57
+ elsif @op == 'QuerySAFE'
58
+ @fields = @safe_fields
59
+ # Override mapping with api-specific field maps
60
+ @mapping[:safe_id] = :SafeID
61
+ @mapping[:gateway_username] = :GatewayUsername
62
+ @mapping[:gateway_key] = :APIKey
63
+ else
64
+ raise InvalidRequestError, "Invalid op #{@op} in Request."
65
+ end
66
+
67
+ @needs_account = true
68
+ @needs_key = true
69
+
70
+ end
71
+
72
+ def validate
73
+ @required = []
74
+
75
+ error_array = AgmsAutoValidate();
76
+
77
+ errors = error_array['errors'];
78
+ messages = error_array['messages'];
79
+
80
+ @validate_errors = errors;
81
+ @validate_messages = messages;
82
+
83
+ if errors == 0
84
+ return {'errors' => errors, 'messages' => messages}
85
+ else
86
+ raise RequestValidationError, "Request validation failed with #{messages.join(' ')}."
87
+ end
88
+
89
+ end
90
+
91
+ def getFields
92
+ return getFieldArray
93
+ end
94
+
95
+ def getParams(request)
96
+ if @op == 'TransactionAPI'
97
+ return {:objparameters => request}
98
+ elsif @op == 'QuerySAFE'
99
+ return request
100
+ else
101
+ return {:objparameters => request}
102
+ end
103
+
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,455 @@
1
+ module Agms
2
+ class Request
3
+ def initialize(op)
4
+ @op = op
5
+ @validateErrors = 0
6
+ @validateMessages = nil
7
+ @fields = nil
8
+ @required = nil
9
+ @numeric = nil
10
+ @optionable = nil
11
+ @enums = nil
12
+ @date = nil
13
+ @time = nil
14
+ @boolean = nil
15
+ @digit_2 = nil
16
+ @amount = nil
17
+
18
+ @needs_account = nil
19
+ @needs_key = nil
20
+
21
+ @mapping_alias = nil
22
+
23
+ @mapping = {
24
+ :gateway_username => :GatewayUserName,
25
+ :gateway_password => :GatewayPassword,
26
+ :gateway_account => :AccountNumber,
27
+ :gateway_key => :TransactionAPIKey,
28
+ :amount => :Amount,
29
+ :description => :OrderDescription,
30
+ :order_description => :OrderDescription,
31
+ :return_url => :RetURL,
32
+ :enable_ach => :ACHEnabled,
33
+ :transaction_type => :TransactionType,
34
+ :payment_type => :PaymentType,
35
+ :enable_auto_add_to_safe => :AutoSAFE,
36
+ :processing_account_id => :ProcessorID,
37
+ :enable_donation => :Donation,
38
+ :max_link_uses => :UsageCount,
39
+ :cc_number => :CCNumber,
40
+ :cc_exp_date => :CCExpDate,
41
+ :cc_cvv => :CVV,
42
+ :cc_track_1 => :Track1,
43
+ :cc_track_2 => :Track2,
44
+ :cc_track_3 => :Track3,
45
+ :cc_encrypted_data => :MagData,
46
+ :cc_encrypted_hardware => :MagHardware,
47
+ :ach_name => :CheckName,
48
+ :ach_routing_number => :CheckABA,
49
+ :ach_account_number => :CheckAccount,
50
+ :ach_business_or_personal => :AccountHolderType,
51
+ :ach_checking_or_savings => :AccountType,
52
+ :ach_sec_code => :SecCode,
53
+ :safe_action => :SAFE_Action,
54
+ :safe_id => :SAFE_ID,
55
+ :first_name => :FirstName,
56
+ :last_name => :LastName,
57
+ :company_name => :Company,
58
+ :company => :Company,
59
+ :address => :Address1,
60
+ :address_1 => :Address1,
61
+ :address_2 => :Address2,
62
+ :city => :City,
63
+ :state => :State,
64
+ :zip => :Zip,
65
+ :country => :Country,
66
+ :phone => :Phone,
67
+ :fax => :Fax,
68
+ :email => :EMail,
69
+ :website => :Website,
70
+ :tax_amount => :Tax,
71
+ :shipping_amount => :Shipping,
72
+ :tip_amount => :TipAmount,
73
+ :order_id => :OrderID,
74
+ :po_number => :PONumber,
75
+ :clerk_id => :ClerkID,
76
+ :ip_address => :IPAddress,
77
+ :receipt_type => :ReceiptType,
78
+ :shipping_first_name => :ShippingFirstName,
79
+ :shipping_last_name => :ShippingLastName,
80
+ :shipping_company_name => :ShippingCompany,
81
+ :shipping_company => :ShippingCompany,
82
+ :shipping_address => :ShippingAddress1,
83
+ :shipping_address_1 => :ShippingAddress1,
84
+ :shipping_address_2 => :ShippingAddress2,
85
+ :shipping_city => :ShippingCity,
86
+ :shipping_state => :ShippingState,
87
+ :shipping_zip => :ShippingZip,
88
+ :shipping_country => :ShippingCountry,
89
+ :shipping_email => :ShippingEmail,
90
+ :shipping_phone => :ShippingPhone,
91
+ :shipping_fax => :ShippingFax,
92
+ :shipping_tracking_number => :ShippingTrackingNumber,
93
+ :shipping_carrier => :ShippingCarrier,
94
+ :custom_field_1 => :Custom_Field_1,
95
+ :custom_field_2 => :Custom_Field_2,
96
+ :custom_field_3 => :Custom_Field_3,
97
+ :custom_field_4 => :Custom_Field_4,
98
+ :custom_field_5 => :Custom_Field_5,
99
+ :custom_field_6 => :Custom_Field_6,
100
+ :custom_field_7 => :Custom_Field_7,
101
+ :custom_field_8 => :Custom_Field_8,
102
+ :custom_field_9 => :Custom_Field_9,
103
+ :custom_field_10 => :Custom_Field_10,
104
+ :custom_field_11 => :Custom_Field_11,
105
+ :custom_field_12 => :Custom_Field_12,
106
+ :custom_field_13 => :Custom_Field_13,
107
+ :custom_field_14 => :Custom_Field_14,
108
+ :custom_field_15 => :Custom_Field_15,
109
+ :custom_field_16 => :Custom_Field_16,
110
+ :custom_field_17 => :Custom_Field_17,
111
+ :custom_field_18 => :Custom_Field_18,
112
+ :custom_field_19 => :Custom_Field_19,
113
+ :custom_field_20 => :Custom_Field_20,
114
+ :expiring_in_30_days => :Expiring30,
115
+ :recurring_id => :RecurringID,
116
+ :merchant_id => :MerchantID,
117
+ :initial_amount => :InitialAmount,
118
+ :recurring_amount => :RecurringAmount,
119
+ :frequency => :Frequency,
120
+ :quantity => :Quantity,
121
+ :number_of_times_to_bill => :NumberOfOccurrences,
122
+ :number_of_retries => :NumberOfRetries,
123
+ :hpp_format => :HPPFormat,
124
+ :cc_last_4 => :CreditCardLast4,
125
+ :transaction_id => :TransactionID,
126
+ :start_date => :StartDate,
127
+ :end_date => :EndDate,
128
+ :start_time => :StartTime,
129
+ :end_time => :EndTime,
130
+ :suppress_safe_option => :SupressAutoSAFE
131
+ }
132
+
133
+ @states = %w(AL AK AS AZ AR CA CO CT DE DC FM FL GA GU HI ID IL IN IA KS KY LA ME MH MD MA MI MN MS MO MT NE NV NH NJ NM NY NC ND MP OH OK OR PW PA PR RI SC SD TN TX UT VT VI VA WA WV WI WY AE AA AP)
134
+ end
135
+
136
+ def get(username, password, account, api_key)
137
+ request_body = getFields()
138
+ request_body[:GatewayUserName] = username
139
+ request_body[:GatewayPassword] = password
140
+
141
+ # Adjust for a field name variation in the Reporting API
142
+ if @op == 'TransactionAPI' or @op == 'QuerySAFE'
143
+ request_body.delete(:GatewayUserName)
144
+ request_body[:GatewayUsername] = username
145
+ end
146
+
147
+ # Add Account # and API Key field to request when necessary for specific API
148
+ if @needs_account
149
+ request_body[:AccountNumber] = account
150
+ end
151
+
152
+ if @needs_key
153
+ # Adjust for a field name variation in the Reporting API
154
+ if @op == 'TransactionAPI'
155
+ request_body[:TransactionAPIKey] = api_key
156
+ elsif @op == 'QuerySAFE'
157
+ request_body[:APIKey] = api_key
158
+ end
159
+ end
160
+
161
+ return request_body
162
+ end
163
+
164
+ def setField(name, parameter, value)
165
+ field_name = mapToField(name)
166
+ # Fix for odd capitalization of Email
167
+ if field_name == :Email
168
+ field_name = :EMail
169
+ end
170
+
171
+ # Check that field exists
172
+ if not @fields.has_key?(field_name)
173
+ raise InvalidParameterError, "Invalid field name #{name}."
174
+ end
175
+
176
+ # Ensure that setting parameters are forced to all lowercase and are case insensitive
177
+ if parameter == :setting
178
+ value = value.downcase
179
+ end
180
+
181
+ # Check that it is a valid setting
182
+ if ( parameter == :setting and
183
+ value != '' and
184
+ value != 'required' and
185
+ value != 'disabled' and
186
+ value != 'visible' and
187
+ value != 'excluded' and
188
+ value != 'hidden' )
189
+ raise InvalidParameterError, "Invalid parameter #{parameter} for #{name}."
190
+ end
191
+
192
+ if parameter == :setting
193
+ @fields[field_name][:setting] = value
194
+ return true
195
+ elsif parameter == :value
196
+ @fields[field_name][:value] = value
197
+ return true
198
+ else
199
+ raise InvalidParameterError, "Invalid parameter #{parameter} for #{name}."
200
+ end
201
+ end
202
+
203
+ def getField(name)
204
+ field_name = mapToField(name)
205
+ return @fields[field_name]
206
+ end
207
+
208
+ def getValidationErrors
209
+ return @validateErrors
210
+ end
211
+
212
+
213
+ def getValidationMessages
214
+ return @validateMessages
215
+ end
216
+
217
+ protected
218
+ def autoValidate
219
+ errors = 0
220
+ messages = Array.new
221
+
222
+ if @required
223
+ @required.each do | field_name |
224
+ if @fields[field_name][:value] == ''
225
+ errors +=1
226
+ messages.push("Missing required field #{field_name}.")
227
+ end
228
+ end
229
+ end
230
+
231
+ # Validate enumerated types
232
+ if @enums
233
+ @enums.each do | field_name, valid_values |
234
+
235
+ if @fields.has_key?(field_name) and
236
+ @fields[field_name][:value] != '' and
237
+ not valid_values.include?@fields[field_name][:value]
238
+ errors += 1
239
+ messages.push("Invalid #{field_name}, value " + @fields[field_name][:value] + ', must be one of ' + valid_values.join(' ') + '.')
240
+ end
241
+ end
242
+ end
243
+
244
+ # Validate numeric fields
245
+ if @numeric
246
+ @numeric.each do | field_name |
247
+ if @fields.has_key?(field_name) and
248
+ @fields[field_name][:value] != '' and
249
+ not isNumber(@fields[field_name][:value])
250
+ errors += 1
251
+ messages.push("Field #{field_name} has value " + @fields[field_name][:value] + ' must be numeric.')
252
+ end
253
+ end
254
+ end
255
+
256
+ # Validate optionable fields
257
+ if @optionable
258
+ @optionable.each do | field_name |
259
+ if ( @fields.has_key?(field_name) and
260
+ @fields[field_name][:setting] != '' and
261
+ @fields[field_name][:setting] != :required and
262
+ @fields[field_name][:setting] != :disabled and
263
+ @fields[field_name][:setting] != :visible and
264
+ @fields[field_name][:setting] != :excluded and
265
+ @fields[field_name][:setting] != :hidden )
266
+ errors += 1
267
+ messages.push("Field #{field_name} has setting " + @fields[field_name][:value] + ', must be required, disabled, visible, hidden, or empty.')
268
+ end
269
+ end
270
+ end
271
+
272
+ # Validate date fields
273
+ if @date
274
+ @date.each do | field_name |
275
+
276
+ if @fields.has_key?(field_name) and
277
+ @fields[field_name][:value] != '' and
278
+ not /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/.match(@fields[field_name][:value])
279
+ errors += 1
280
+ messages.push("Field #{field_name} has setting " + @fields[field_name][:value] + ', must be in date format YYYY-MM-DD.')
281
+ end
282
+ end
283
+ end
284
+
285
+
286
+ # Validate time fields
287
+ if @time
288
+ @time.each do | field_name |
289
+ if not @fields[field_name][:value] != '' and
290
+ not /([01][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])/.match(@fields[field_name][:value])
291
+ errors += 1
292
+ messages.push("Field #{field_name} has setting " + @fields[field_name]['value'] + ', must be in 24h time format HH:MM:SS or HH:MM.')
293
+ end
294
+ end
295
+ end
296
+
297
+
298
+ # Validate boolean fields
299
+ if @boolean
300
+ @boolean.each do | field_name |
301
+ if ( @fields.has_key?(field_name) and
302
+ not @fields[field_name][:value] != '' and
303
+ not @fields[field_name][:value] != true and
304
+ @fields[field_name][:value] != false and
305
+ not @fields[field_name][:value] != 'TRUE' and
306
+ @fields[field_name][:value] != 'FALSE'
307
+ )
308
+ errors += 1
309
+ messages.push("Field #{field_name} has setting " + @fields[field_name][:value] + ', must be boolean TRUE or FALSE.')
310
+ end
311
+ end
312
+ end
313
+
314
+ # Validate state code fields
315
+ if @digit_2
316
+ @digit_2.each do | field_name |
317
+ if @fields.has_key?(field_name) and
318
+ @fields[field_name][:value] != '' and
319
+ not @digit_2.has_key?@fields[field_name][:value]
320
+ errors += 1
321
+ messages.push("Field #{field_name} has setting " + @fields[field_name][:value] + ', must be valid 2 digit US State code.')
322
+ end
323
+ end
324
+ end
325
+
326
+ # Validate amount fields
327
+ if @amount
328
+ @amount.each do | field_name |
329
+ if @fields.key?(field_name) and
330
+ @fields[field_name][:value] != '' and
331
+ @fields[field_name][:value] > Configuration.max_amount
332
+ errors += 1
333
+ messages.push("Field #{field_name} amount " + @fields[field_name][:value] + ", is above maximum allowable value of #{Configuration.max_amount}")
334
+ end
335
+ if @fields.key?(field_name) and
336
+ @fields[field_name][:value] != '' and
337
+ @fields[field_name][:value] < Configuration.min_amount
338
+ errors += 1
339
+ messages.push("Field #{field_name} amount " + @fields[field_name][:value] + ", is below minimum allowable value of #{Configuration.min_amount}")
340
+ end
341
+ end
342
+ end
343
+
344
+ return {'errors' => errors, 'messages' => messages}
345
+ end
346
+
347
+
348
+ def getFieldArray
349
+ request = {}
350
+
351
+ # Call validation, which ensures we've validated and done so against current data
352
+ validate()
353
+
354
+ if @validateErrors > 0
355
+ raise RequestValidationError , 'Request validation failed with ' + ' '.join(@validateMessages) + '.'
356
+ end
357
+
358
+ @fields.each do | field_name, settings |
359
+ if settings[:setting] == :required
360
+ request[field_name] = ''
361
+ request[field_name + '_Visible'] = true
362
+ request[field_name + '_Required'] = true
363
+ if field_name == :EMail
364
+ request['Email_Disabled'] = false
365
+ else
366
+ request[field_name + '_Disabled'] = false
367
+ end
368
+
369
+ elsif settings[:setting] == :disabled
370
+ request[field_name] = ''
371
+ request[field_name + '_Visible'] = true
372
+ request[field_name + '_Required'] =true
373
+ if field_name == :EMail
374
+ request['Email_Disabled'] = false
375
+ else
376
+ request[field_name + '_Disabled'] = false
377
+ end
378
+
379
+ elsif settings[:setting] == :visible
380
+ request[field_name] = ''
381
+ request[field_name + '_Visible'] = true
382
+ request[field_name + '_Required'] = true
383
+ if field_name == :EMail
384
+ request['Email_Disabled'] = false
385
+ else
386
+ request[field_name + '_Disabled'] = false
387
+ end
388
+
389
+ elsif settings[:setting] == :hidden
390
+ next
391
+
392
+ elsif settings[:setting] == :excluded
393
+ next
394
+
395
+ else
396
+ if @optionable and @optionable.include?(field_name)
397
+ request[field_name + '_Visible'] = true
398
+ request[field_name + '_Required'] = true
399
+ if field_name == :EMail
400
+ request['Email_Disabled'] = false
401
+ else
402
+ request[field_name + '_Disabled'] = false
403
+ end
404
+ end
405
+ end
406
+
407
+ if settings[:value]
408
+ if settings[:value].upcase == 'TRUE'
409
+ request[field_name] = true
410
+ elsif settings[:value].upcase == 'FALSE'
411
+ request[field_name] = false
412
+ else
413
+ request[field_name] = settings[:value]
414
+ end
415
+ end
416
+ end
417
+ return request
418
+ end
419
+
420
+
421
+ def mapToField(field_name)
422
+ if @mapping.has_key?(field_name)
423
+ return @mapping[field_name]
424
+ elsif @mapping_alias and @mapping_alias.has_key?(field_name)
425
+ return @mapping_alias[field_name]
426
+ elsif @fields.has_key?(field_name)
427
+ return field_name
428
+ else
429
+ raise InvalidParameterError, "Invalid field name #{field_name}."
430
+ end
431
+ end
432
+
433
+ def mapToName(field_name)
434
+ if @mapping.has_key?(field_name)
435
+ return @mapping[field_name]
436
+ elsif @mapping_alias and @mapping_alias.has_key?(field_name)
437
+ return @mapping_alias[field_name]
438
+ elsif @fields.has_key?(field_name)
439
+ return field_name
440
+ else
441
+ raise InvalidParameterError, "Invalid field name #{field_name}."
442
+ end
443
+ end
444
+
445
+
446
+ def isNumber(str)
447
+ begin
448
+ !!Integer(str)
449
+ rescue ArgumentError, TypeError
450
+ false
451
+ end
452
+ end
453
+
454
+ end
455
+ end