authorizenet 1.8.7 → 1.8.8

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