authorizenet 1.8.7 → 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
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