authorizenet 1.9.6 → 1.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +5 -5
  2. data/lib/app/helpers/authorize_net_helper.rb +23 -23
  3. data/lib/authorize_net.rb +107 -107
  4. data/lib/authorize_net/addresses/address.rb +25 -25
  5. data/lib/authorize_net/addresses/shipping_address.rb +22 -22
  6. data/lib/authorize_net/aim/response.rb +120 -120
  7. data/lib/authorize_net/aim/transaction.rb +171 -171
  8. data/lib/authorize_net/api/LogHelper.rb +97 -0
  9. data/lib/authorize_net/api/SensitiveDataFilter.rb +92 -0
  10. data/lib/authorize_net/api/api_transaction.rb +129 -119
  11. data/lib/authorize_net/api/constants.yml +1 -1
  12. data/lib/authorize_net/api/schema.rb +5421 -5165
  13. data/lib/authorize_net/api/transaction.rb +265 -261
  14. data/lib/authorize_net/arb/fields.rb +24 -24
  15. data/lib/authorize_net/arb/paging.rb +29 -29
  16. data/lib/authorize_net/arb/response.rb +26 -26
  17. data/lib/authorize_net/arb/sorting.rb +39 -39
  18. data/lib/authorize_net/arb/subscription.rb +68 -68
  19. data/lib/authorize_net/arb/subscription_detail.rb +10 -10
  20. data/lib/authorize_net/arb/subscription_list_response.rb +36 -36
  21. data/lib/authorize_net/arb/transaction.rb +171 -171
  22. data/lib/authorize_net/authorize_net.rb +154 -154
  23. data/lib/authorize_net/cim/customer_profile.rb +15 -15
  24. data/lib/authorize_net/cim/payment_profile.rb +35 -35
  25. data/lib/authorize_net/cim/response.rb +111 -111
  26. data/lib/authorize_net/cim/transaction.rb +721 -721
  27. data/lib/authorize_net/customer.rb +24 -24
  28. data/lib/authorize_net/email_receipt.rb +20 -20
  29. data/lib/authorize_net/fields.rb +760 -760
  30. data/lib/authorize_net/key_value_response.rb +109 -109
  31. data/lib/authorize_net/key_value_transaction.rb +281 -281
  32. data/lib/authorize_net/line_item.rb +21 -21
  33. data/lib/authorize_net/order.rb +38 -38
  34. data/lib/authorize_net/payment_methods/credit_card.rb +61 -61
  35. data/lib/authorize_net/payment_methods/echeck.rb +70 -70
  36. data/lib/authorize_net/reporting/batch.rb +16 -16
  37. data/lib/authorize_net/reporting/batch_statistics.rb +15 -15
  38. data/lib/authorize_net/reporting/fds_filter.rb +8 -8
  39. data/lib/authorize_net/reporting/response.rb +157 -157
  40. data/lib/authorize_net/reporting/returned_item.rb +45 -45
  41. data/lib/authorize_net/reporting/transaction.rb +131 -131
  42. data/lib/authorize_net/reporting/transaction_details.rb +22 -22
  43. data/lib/authorize_net/response.rb +25 -25
  44. data/lib/authorize_net/sim/hosted_payment_form.rb +34 -34
  45. data/lib/authorize_net/sim/hosted_receipt_page.rb +32 -32
  46. data/lib/authorize_net/sim/response.rb +133 -133
  47. data/lib/authorize_net/sim/transaction.rb +128 -128
  48. data/lib/authorize_net/transaction.rb +66 -66
  49. data/lib/authorize_net/xml_response.rb +154 -154
  50. data/lib/authorize_net/xml_transaction.rb +279 -279
  51. data/lib/authorizenet.rb +4 -4
  52. data/lib/generators/authorize_net/direct_post/direct_post_generator.rb +52 -52
  53. data/lib/generators/authorize_net/direct_post/templates/README-AuthorizeNet +48 -48
  54. data/lib/generators/authorize_net/direct_post/templates/config.yml.erb +8 -8
  55. data/lib/generators/authorize_net/direct_post/templates/config.yml.rails3.erb +8 -8
  56. data/lib/generators/authorize_net/direct_post/templates/controller.rb.erb +30 -30
  57. data/lib/generators/authorize_net/direct_post/templates/initializer.rb +4 -4
  58. data/lib/generators/authorize_net/direct_post/templates/layout.erb +17 -17
  59. data/lib/generators/authorize_net/direct_post/templates/payment.erb +9 -9
  60. data/lib/generators/authorize_net/direct_post/templates/payment.rails3.erb +9 -9
  61. data/lib/generators/authorize_net/sim/sim_generator.rb +46 -46
  62. data/lib/generators/authorize_net/sim/templates/README-AuthorizeNet +51 -51
  63. data/lib/generators/authorize_net/sim/templates/config.yml.erb +8 -8
  64. data/lib/generators/authorize_net/sim/templates/config.yml.rails3.erb +8 -8
  65. data/lib/generators/authorize_net/sim/templates/controller.rb.erb +20 -20
  66. data/lib/generators/authorize_net/sim/templates/initializer.rb +4 -4
  67. data/lib/generators/authorize_net/sim/templates/layout.erb +17 -17
  68. data/lib/generators/authorize_net/sim/templates/payment.erb +5 -5
  69. data/lib/generators/authorize_net/sim/templates/payment.rails3.erb +5 -5
  70. data/lib/generators/generator_extensions.rb +73 -73
  71. metadata +5 -3
@@ -1,279 +1,279 @@
1
- module AuthorizeNet
2
- # The ARB transaction class.
3
- class XmlTransaction < AuthorizeNet::Transaction
4
- # The XML namespace used by the ARB API.
5
- XML_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.freeze
6
-
7
- # Constants for both the various Authorize.Net subscription gateways are defined here.
8
- module Gateway
9
- LIVE = 'https://api2.authorize.net/xml/v1/request.api'.freeze
10
- TEST = 'https://apitest.authorize.net/xml/v1/request.api'.freeze
11
- end
12
-
13
- # Constants for both the various Authorize.Net transaction types are defined here.
14
- module Type
15
- ARB_CREATE = "ARBCreateSubscriptionRequest".freeze
16
- ARB_UPDATE = "ARBUpdateSubscriptionRequest".freeze
17
- ARB_GET_STATUS = "ARBGetSubscriptionStatusRequest".freeze
18
- ARB_CANCEL = "ARBCancelSubscriptionRequest".freeze
19
- ARB_GET_SUBSCRIPTION_LIST = "ARBGetSubscriptionListRequest".freeze
20
- CIM_CREATE_PROFILE = "createCustomerProfileRequest".freeze
21
- CIM_CREATE_PAYMENT = "createCustomerPaymentProfileRequest".freeze
22
- CIM_CREATE_ADDRESS = "createCustomerShippingAddressRequest".freeze
23
- CIM_CREATE_TRANSACTION = "createCustomerProfileTransactionRequest".freeze
24
- CIM_DELETE_PROFILE = "deleteCustomerProfileRequest".freeze
25
- CIM_DELETE_PAYMENT = "deleteCustomerPaymentProfileRequest".freeze
26
- CIM_DELETE_ADDRESS = "deleteCustomerShippingAddressRequest".freeze
27
- CIM_GET_PROFILE_IDS = "getCustomerProfileIdsRequest".freeze
28
- CIM_GET_PROFILE = "getCustomerProfileRequest".freeze
29
- CIM_GET_PAYMENT = "getCustomerPaymentProfileRequest".freeze
30
- CIM_GET_ADDRESS = "getCustomerShippingAddressRequest".freeze
31
- CIM_GET_HOSTED_PROFILE = "getHostedProfilePageRequest".freeze
32
- CIM_UPDATE_PROFILE = "updateCustomerProfileRequest".freeze
33
- CIM_UPDATE_PAYMENT = "updateCustomerPaymentProfileRequest".freeze
34
- CIM_UPDATE_ADDRESS = "updateCustomerShippingAddressRequest".freeze
35
- CIM_UPDATE_SPLIT = "updateSplitTenderGroupRequest".freeze
36
- CIM_VALIDATE_PAYMENT = "validateCustomerPaymentProfileRequest".freeze
37
- REPORT_GET_BATCH_LIST = "getSettledBatchListRequest".freeze
38
- REPORT_GET_TRANSACTION_LIST = "getTransactionListRequest".freeze
39
- REPORT_GET_UNSETTLED_TRANSACTION_LIST = "getUnsettledTransactionListRequest".freeze
40
- REPORT_GET_TRANSACTION_DETAILS = "getTransactionDetailsRequest".freeze
41
- end
42
-
43
- # Fields to convert to/from booleans.
44
- @@boolean_fields = []
45
-
46
- # Fields to convert to/from BigDecimal.
47
- @@decimal_fields = []
48
-
49
- # Fields to convert to/from Date.
50
- @@date_fields = []
51
-
52
- # Fields to convert to/from DateTime.
53
- @@datetime_fields = []
54
-
55
- # The class to wrap our response in.
56
- @response_class = AuthorizeNet::XmlResponse
57
-
58
- # The default options for the constructor.
59
- @@option_defaults = {
60
- gateway: :production,
61
- verify_ssl: true,
62
- reference_id: nil
63
- }
64
-
65
- # DO NOT USE. Instantiate AuthorizeNet::ARB::Transaction or AuthorizeNet::CIM::Transaction instead.
66
- def initialize(api_login_id, api_transaction_key, options = {})
67
- super()
68
- @api_login_id = api_login_id
69
- @api_transaction_key = api_transaction_key
70
-
71
- @response ||= nil
72
- @type ||= nil
73
-
74
- options = @@option_defaults.merge(options)
75
- @verify_ssl = options[:verify_ssl]
76
- @reference_id = options[:reference_id]
77
- @gateway = case options[:gateway].to_s
78
- when 'sandbox', 'test'
79
- Gateway::TEST
80
- when 'production', 'live'
81
- Gateway::LIVE
82
- else
83
- @gateway = options[:gateway]
84
- options[:gateway]
85
- end
86
- end
87
-
88
- def setOAuthOptions
89
- unless @options_OAuth.blank?
90
- @options_OAuth = @@option_defaults.merge(@options_OAuth)
91
- @verify_ssl = options_OAuth[:verify_ssl]
92
- @reference_id = options_OAuth[:reference_id]
93
-
94
- @gateway = case options_OAuth[:gateway].to_s
95
- when 'sandbox', 'test'
96
- Gateway::TEST
97
- when 'production', 'live'
98
- Gateway::LIVE
99
- else
100
- @gateway = options_OAuth[:gateway]
101
- options_OAuth[:gateway]
102
- end
103
- end
104
- end
105
-
106
- # Checks if the transaction has been configured for the sandbox or not. Return FALSE if the
107
- # transaction is running against the production, TRUE otherwise.
108
- def test?
109
- @gateway != Gateway::LIVE
110
- end
111
-
112
- # Checks to see if the transaction has a response (meaning it has been submitted to the gateway).
113
- # Returns TRUE if a response is present, FALSE otherwise.
114
- def has_response?
115
- !@response.nil?
116
- end
117
-
118
- # Retrieve the response object (or Nil if transaction hasn't been sent to the gateway).
119
- attr_reader :response
120
-
121
- # Submits the transaction to the gateway for processing. Returns a response object. If the transaction
122
- # has already been run, it will return nil.
123
- def run
124
- make_request
125
- end
126
-
127
- # Returns a deep-copy of the XML object sent to the payment gateway. Or nil if there was no XML payload.
128
- attr_reader :xml
129
-
130
- #:enddoc:
131
- protected
132
-
133
- # Takes a list of nodes (a Hash is a node, and Array is a list) and returns True if any nodes
134
- # would be built by build_nodes. False if no new nodes would be generated.
135
- def has_content(nodeList, data)
136
- nodeList.each do |node|
137
- nodeName = (node.keys.reject { |_k| nodeName.to_s[0..0] == '_' }).first
138
- multivalue = node[:_multivalue]
139
- conditional = node[:_conditional]
140
- value = node[nodeName]
141
- value = send(conditional, nodeName) unless conditional.nil?
142
- case value
143
- when Array
144
- if multivalue.nil?
145
- return true if has_content(value, data)
146
- else
147
- data[multivalue].each do |v|
148
- return true if has_content(value, v)
149
- end
150
- end
151
- when Symbol
152
- converted = convert_field(value, data[value])
153
- return true unless converted.nil?
154
- else
155
- return true
156
- end
157
- end
158
- false
159
- end
160
-
161
- # Takes a list of nodes (a Hash is a node, and Array is a list) and recursively builds the XML by pulling
162
- # values as needed from data.
163
- def build_nodes(builder, nodeList, data)
164
- nodeList.each do |node|
165
- # TODO: - ADD COMMENTS HERE
166
- nodeName = (node.keys.reject { |k| k.to_s[0..0] == '_' }).first
167
- multivalue = node[:_multivalue]
168
- conditional = node[:_conditional]
169
- value = node[nodeName]
170
-
171
- value = send(conditional, nodeName) unless conditional.nil?
172
- case value
173
- when Array # node containing other nodes
174
- if multivalue.nil?
175
- proc = proc { build_nodes(builder, value, data) }
176
- builder.send(nodeName, &proc) if has_content(value, data)
177
- else
178
- data[multivalue].to_a.each do |v|
179
- proc = proc { build_nodes(builder, value, v) }
180
- builder.send(nodeName, &proc) if has_content(value, v)
181
- end
182
- end
183
- when Symbol # node containing actual data
184
- if data[value].is_a?(Array)
185
- data[value].each do |v|
186
- converted = convert_field(value, v)
187
- builder.send(nodeName, converted) unless converted.nil?
188
- end
189
- else
190
- converted = convert_field(value, data[value])
191
- builder.send(nodeName, converted) unless converted.nil?
192
- end
193
- else
194
- builder.send(nodeName, value)
195
- end
196
- end
197
- end
198
-
199
- def convert_field(field, value)
200
- if @@boolean_fields.include?(field) && !value.nil?
201
- return boolean_to_value(value)
202
- elsif @@decimal_fields.include?(field) && !value.nil?
203
- return decimal_to_value(value)
204
- elsif @@date_fields.include?(field) && !value.nil?
205
- return date_to_value(value)
206
- elsif @@datetime_fields.include?(field) && !value.nil?
207
- return datetime_to_value(value)
208
- elsif field == :extra_options
209
- # handle converting extra options
210
- options = []
211
- value.each_pair { |k, v| options <<= to_param(k, v) } unless value.nil?
212
- unless @custom_fields.nil?
213
- # special sort to maintain compatibility with AIM custom field ordering
214
- # FIXME - This should be DRY'd up.
215
- custom_field_keys = @custom_fields.keys.collect(&:to_s).sort.collect(&:to_sym)
216
- for key in custom_field_keys
217
- options <<= to_param(key, @custom_fields[key.to_sym], '')
218
- end
219
- end
220
-
221
- if !options.empty?
222
- return options.join('&')
223
- else
224
- return nil
225
- end
226
- elsif field == :exp_date
227
- # convert MMYY expiration dates into the XML equivalent
228
- unless value.nil?
229
- begin
230
- return value.to_s.casecmp('xxxx').zero? ? 'XXXX' : Date.strptime(value.to_s, '%m%y').strftime('%Y-%m')
231
- rescue StandardError
232
- # If we didn't get the exp_date in MMYY format, try our best to convert it
233
- return Date.parse(value.to_s).strftime('%Y-%m')
234
- end
235
- end
236
- end
237
-
238
- value
239
- end
240
-
241
- # An internal method that builds the POST body, submits it to the gateway, and constructs a Response object with the response.
242
- def make_request
243
- return nil if has_response?
244
-
245
- fields = @fields
246
-
247
- builder = Nokogiri::XML::Builder.new(encoding: 'utf-8') do |x|
248
- x.send(@type.to_sym, xmlns: XML_NAMESPACE) do
249
- x.merchantAuthentication do
250
- x.name @api_login_id
251
- x.transactionKey @api_transaction_key
252
- end
253
- build_nodes(x, self.class.const_get(:FIELDS)[@type], fields)
254
- end
255
- end
256
- @xml = builder.to_xml
257
-
258
- url = URI.parse(@gateway)
259
-
260
- request = Net::HTTP::Post.new(url.path)
261
- request.content_type = 'text/xml'
262
- request.body = @xml
263
- connection = Net::HTTP.new(url.host, url.port)
264
- connection.use_ssl = true
265
- if @verify_ssl
266
- connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
267
- else
268
- connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
269
- end
270
-
271
- # Use our Class's @response_class variable to find the Response class we are supposed to use.
272
- begin
273
- @response = self.class.instance_variable_get(:@response_class).new((connection.start { |http| http.request(request) }), self)
274
- rescue StandardError
275
- @response = self.class.instance_variable_get(:@response_class).new($ERROR_INFO, self)
276
- end
277
- end
278
- end
279
- end
1
+ module AuthorizeNet
2
+ # The ARB transaction class.
3
+ class XmlTransaction < AuthorizeNet::Transaction
4
+ # The XML namespace used by the ARB API.
5
+ XML_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.freeze
6
+
7
+ # Constants for both the various Authorize.Net subscription gateways are defined here.
8
+ module Gateway
9
+ LIVE = 'https://api2.authorize.net/xml/v1/request.api'.freeze
10
+ TEST = 'https://apitest.authorize.net/xml/v1/request.api'.freeze
11
+ end
12
+
13
+ # Constants for both the various Authorize.Net transaction types are defined here.
14
+ module Type
15
+ ARB_CREATE = "ARBCreateSubscriptionRequest".freeze
16
+ ARB_UPDATE = "ARBUpdateSubscriptionRequest".freeze
17
+ ARB_GET_STATUS = "ARBGetSubscriptionStatusRequest".freeze
18
+ ARB_CANCEL = "ARBCancelSubscriptionRequest".freeze
19
+ ARB_GET_SUBSCRIPTION_LIST = "ARBGetSubscriptionListRequest".freeze
20
+ CIM_CREATE_PROFILE = "createCustomerProfileRequest".freeze
21
+ CIM_CREATE_PAYMENT = "createCustomerPaymentProfileRequest".freeze
22
+ CIM_CREATE_ADDRESS = "createCustomerShippingAddressRequest".freeze
23
+ CIM_CREATE_TRANSACTION = "createCustomerProfileTransactionRequest".freeze
24
+ CIM_DELETE_PROFILE = "deleteCustomerProfileRequest".freeze
25
+ CIM_DELETE_PAYMENT = "deleteCustomerPaymentProfileRequest".freeze
26
+ CIM_DELETE_ADDRESS = "deleteCustomerShippingAddressRequest".freeze
27
+ CIM_GET_PROFILE_IDS = "getCustomerProfileIdsRequest".freeze
28
+ CIM_GET_PROFILE = "getCustomerProfileRequest".freeze
29
+ CIM_GET_PAYMENT = "getCustomerPaymentProfileRequest".freeze
30
+ CIM_GET_ADDRESS = "getCustomerShippingAddressRequest".freeze
31
+ CIM_GET_HOSTED_PROFILE = "getHostedProfilePageRequest".freeze
32
+ CIM_UPDATE_PROFILE = "updateCustomerProfileRequest".freeze
33
+ CIM_UPDATE_PAYMENT = "updateCustomerPaymentProfileRequest".freeze
34
+ CIM_UPDATE_ADDRESS = "updateCustomerShippingAddressRequest".freeze
35
+ CIM_UPDATE_SPLIT = "updateSplitTenderGroupRequest".freeze
36
+ CIM_VALIDATE_PAYMENT = "validateCustomerPaymentProfileRequest".freeze
37
+ REPORT_GET_BATCH_LIST = "getSettledBatchListRequest".freeze
38
+ REPORT_GET_TRANSACTION_LIST = "getTransactionListRequest".freeze
39
+ REPORT_GET_UNSETTLED_TRANSACTION_LIST = "getUnsettledTransactionListRequest".freeze
40
+ REPORT_GET_TRANSACTION_DETAILS = "getTransactionDetailsRequest".freeze
41
+ end
42
+
43
+ # Fields to convert to/from booleans.
44
+ @@boolean_fields = []
45
+
46
+ # Fields to convert to/from BigDecimal.
47
+ @@decimal_fields = []
48
+
49
+ # Fields to convert to/from Date.
50
+ @@date_fields = []
51
+
52
+ # Fields to convert to/from DateTime.
53
+ @@datetime_fields = []
54
+
55
+ # The class to wrap our response in.
56
+ @response_class = AuthorizeNet::XmlResponse
57
+
58
+ # The default options for the constructor.
59
+ @@option_defaults = {
60
+ gateway: :production,
61
+ verify_ssl: true,
62
+ reference_id: nil
63
+ }
64
+
65
+ # DO NOT USE. Instantiate AuthorizeNet::ARB::Transaction or AuthorizeNet::CIM::Transaction instead.
66
+ def initialize(api_login_id, api_transaction_key, options = {})
67
+ super()
68
+ @api_login_id = api_login_id
69
+ @api_transaction_key = api_transaction_key
70
+
71
+ @response ||= nil
72
+ @type ||= nil
73
+
74
+ options = @@option_defaults.merge(options)
75
+ @verify_ssl = options[:verify_ssl]
76
+ @reference_id = options[:reference_id]
77
+ @gateway = case options[:gateway].to_s
78
+ when 'sandbox', 'test'
79
+ Gateway::TEST
80
+ when 'production', 'live'
81
+ Gateway::LIVE
82
+ else
83
+ @gateway = options[:gateway]
84
+ options[:gateway]
85
+ end
86
+ end
87
+
88
+ def setOAuthOptions
89
+ unless @options_OAuth.blank?
90
+ @options_OAuth = @@option_defaults.merge(@options_OAuth)
91
+ @verify_ssl = options_OAuth[:verify_ssl]
92
+ @reference_id = options_OAuth[:reference_id]
93
+
94
+ @gateway = case options_OAuth[:gateway].to_s
95
+ when 'sandbox', 'test'
96
+ Gateway::TEST
97
+ when 'production', 'live'
98
+ Gateway::LIVE
99
+ else
100
+ @gateway = options_OAuth[:gateway]
101
+ options_OAuth[:gateway]
102
+ end
103
+ end
104
+ end
105
+
106
+ # Checks if the transaction has been configured for the sandbox or not. Return FALSE if the
107
+ # transaction is running against the production, TRUE otherwise.
108
+ def test?
109
+ @gateway != Gateway::LIVE
110
+ end
111
+
112
+ # Checks to see if the transaction has a response (meaning it has been submitted to the gateway).
113
+ # Returns TRUE if a response is present, FALSE otherwise.
114
+ def has_response?
115
+ !@response.nil?
116
+ end
117
+
118
+ # Retrieve the response object (or Nil if transaction hasn't been sent to the gateway).
119
+ attr_reader :response
120
+
121
+ # Submits the transaction to the gateway for processing. Returns a response object. If the transaction
122
+ # has already been run, it will return nil.
123
+ def run
124
+ make_request
125
+ end
126
+
127
+ # Returns a deep-copy of the XML object sent to the payment gateway. Or nil if there was no XML payload.
128
+ attr_reader :xml
129
+
130
+ #:enddoc:
131
+ protected
132
+
133
+ # Takes a list of nodes (a Hash is a node, and Array is a list) and returns True if any nodes
134
+ # would be built by build_nodes. False if no new nodes would be generated.
135
+ def has_content(nodeList, data)
136
+ nodeList.each do |node|
137
+ nodeName = (node.keys.reject { |_k| nodeName.to_s[0..0] == '_' }).first
138
+ multivalue = node[:_multivalue]
139
+ conditional = node[:_conditional]
140
+ value = node[nodeName]
141
+ value = send(conditional, nodeName) unless conditional.nil?
142
+ case value
143
+ when Array
144
+ if multivalue.nil?
145
+ return true if has_content(value, data)
146
+ else
147
+ data[multivalue].each do |v|
148
+ return true if has_content(value, v)
149
+ end
150
+ end
151
+ when Symbol
152
+ converted = convert_field(value, data[value])
153
+ return true unless converted.nil?
154
+ else
155
+ return true
156
+ end
157
+ end
158
+ false
159
+ end
160
+
161
+ # Takes a list of nodes (a Hash is a node, and Array is a list) and recursively builds the XML by pulling
162
+ # values as needed from data.
163
+ def build_nodes(builder, nodeList, data)
164
+ nodeList.each do |node|
165
+ # TODO: - ADD COMMENTS HERE
166
+ nodeName = (node.keys.reject { |k| k.to_s[0..0] == '_' }).first
167
+ multivalue = node[:_multivalue]
168
+ conditional = node[:_conditional]
169
+ value = node[nodeName]
170
+
171
+ value = send(conditional, nodeName) unless conditional.nil?
172
+ case value
173
+ when Array # node containing other nodes
174
+ if multivalue.nil?
175
+ proc = proc { build_nodes(builder, value, data) }
176
+ builder.send(nodeName, &proc) if has_content(value, data)
177
+ else
178
+ data[multivalue].to_a.each do |v|
179
+ proc = proc { build_nodes(builder, value, v) }
180
+ builder.send(nodeName, &proc) if has_content(value, v)
181
+ end
182
+ end
183
+ when Symbol # node containing actual data
184
+ if data[value].is_a?(Array)
185
+ data[value].each do |v|
186
+ converted = convert_field(value, v)
187
+ builder.send(nodeName, converted) unless converted.nil?
188
+ end
189
+ else
190
+ converted = convert_field(value, data[value])
191
+ builder.send(nodeName, converted) unless converted.nil?
192
+ end
193
+ else
194
+ builder.send(nodeName, value)
195
+ end
196
+ end
197
+ end
198
+
199
+ def convert_field(field, value)
200
+ if @@boolean_fields.include?(field) && !value.nil?
201
+ return boolean_to_value(value)
202
+ elsif @@decimal_fields.include?(field) && !value.nil?
203
+ return decimal_to_value(value)
204
+ elsif @@date_fields.include?(field) && !value.nil?
205
+ return date_to_value(value)
206
+ elsif @@datetime_fields.include?(field) && !value.nil?
207
+ return datetime_to_value(value)
208
+ elsif field == :extra_options
209
+ # handle converting extra options
210
+ options = []
211
+ value.each_pair { |k, v| options <<= to_param(k, v) } unless value.nil?
212
+ unless @custom_fields.nil?
213
+ # special sort to maintain compatibility with AIM custom field ordering
214
+ # FIXME - This should be DRY'd up.
215
+ custom_field_keys = @custom_fields.keys.collect(&:to_s).sort.collect(&:to_sym)
216
+ for key in custom_field_keys
217
+ options <<= to_param(key, @custom_fields[key.to_sym], '')
218
+ end
219
+ end
220
+
221
+ if !options.empty?
222
+ return options.join('&')
223
+ else
224
+ return nil
225
+ end
226
+ elsif field == :exp_date
227
+ # convert MMYY expiration dates into the XML equivalent
228
+ unless value.nil?
229
+ begin
230
+ return value.to_s.casecmp('xxxx').zero? ? 'XXXX' : Date.strptime(value.to_s, '%m%y').strftime('%Y-%m')
231
+ rescue StandardError
232
+ # If we didn't get the exp_date in MMYY format, try our best to convert it
233
+ return Date.parse(value.to_s).strftime('%Y-%m')
234
+ end
235
+ end
236
+ end
237
+
238
+ value
239
+ end
240
+
241
+ # An internal method that builds the POST body, submits it to the gateway, and constructs a Response object with the response.
242
+ def make_request
243
+ return nil if has_response?
244
+
245
+ fields = @fields
246
+
247
+ builder = Nokogiri::XML::Builder.new(encoding: 'utf-8') do |x|
248
+ x.send(@type.to_sym, xmlns: XML_NAMESPACE) do
249
+ x.merchantAuthentication do
250
+ x.name @api_login_id
251
+ x.transactionKey @api_transaction_key
252
+ end
253
+ build_nodes(x, self.class.const_get(:FIELDS)[@type], fields)
254
+ end
255
+ end
256
+ @xml = builder.to_xml
257
+
258
+ url = URI.parse(@gateway)
259
+
260
+ request = Net::HTTP::Post.new(url.path)
261
+ request.content_type = 'text/xml'
262
+ request.body = @xml
263
+ connection = Net::HTTP.new(url.host, url.port)
264
+ connection.use_ssl = true
265
+ if @verify_ssl
266
+ connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
267
+ else
268
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
269
+ end
270
+
271
+ # Use our Class's @response_class variable to find the Response class we are supposed to use.
272
+ begin
273
+ @response = self.class.instance_variable_get(:@response_class).new((connection.start { |http| http.request(request) }), self)
274
+ rescue StandardError
275
+ @response = self.class.instance_variable_get(:@response_class).new($ERROR_INFO, self)
276
+ end
277
+ end
278
+ end
279
+ end