yankl 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/lib/app/helpers/authorize_net_helper.rb +24 -0
  3. data/lib/authorize-net.rb +4 -0
  4. data/lib/authorize_net.rb +92 -0
  5. data/lib/authorize_net/addresses/address.rb +29 -0
  6. data/lib/authorize_net/addresses/shipping_address.rb +26 -0
  7. data/lib/authorize_net/aim/response.rb +131 -0
  8. data/lib/authorize_net/aim/transaction.rb +184 -0
  9. data/lib/authorize_net/arb/response.rb +34 -0
  10. data/lib/authorize_net/arb/subscription.rb +72 -0
  11. data/lib/authorize_net/arb/transaction.rb +146 -0
  12. data/lib/authorize_net/authorize_net.rb +154 -0
  13. data/lib/authorize_net/cim/customer_profile.rb +19 -0
  14. data/lib/authorize_net/cim/payment_profile.rb +37 -0
  15. data/lib/authorize_net/cim/response.rb +110 -0
  16. data/lib/authorize_net/cim/transaction.rb +678 -0
  17. data/lib/authorize_net/customer.rb +27 -0
  18. data/lib/authorize_net/email_receipt.rb +24 -0
  19. data/lib/authorize_net/fields.rb +736 -0
  20. data/lib/authorize_net/key_value_response.rb +117 -0
  21. data/lib/authorize_net/key_value_transaction.rb +297 -0
  22. data/lib/authorize_net/line_item.rb +25 -0
  23. data/lib/authorize_net/order.rb +42 -0
  24. data/lib/authorize_net/payment_methods/credit_card.rb +74 -0
  25. data/lib/authorize_net/payment_methods/echeck.rb +72 -0
  26. data/lib/authorize_net/reporting/batch.rb +19 -0
  27. data/lib/authorize_net/reporting/batch_statistics.rb +19 -0
  28. data/lib/authorize_net/reporting/fds_filter.rb +11 -0
  29. data/lib/authorize_net/reporting/response.rb +127 -0
  30. data/lib/authorize_net/reporting/transaction.rb +116 -0
  31. data/lib/authorize_net/reporting/transaction_details.rb +25 -0
  32. data/lib/authorize_net/response.rb +27 -0
  33. data/lib/authorize_net/sim/hosted_payment_form.rb +38 -0
  34. data/lib/authorize_net/sim/hosted_receipt_page.rb +37 -0
  35. data/lib/authorize_net/sim/response.rb +142 -0
  36. data/lib/authorize_net/sim/transaction.rb +138 -0
  37. data/lib/authorize_net/transaction.rb +66 -0
  38. data/lib/authorize_net/xml +65 -0
  39. data/lib/authorize_net/xml_response.rb +172 -0
  40. data/lib/authorize_net/xml_transaction.rb +277 -0
  41. data/lib/generators/authorize_net/direct_post_generator.rb +51 -0
  42. data/lib/generators/authorize_net/sim_generator.rb +47 -0
  43. data/lib/yankl.rb +4 -0
  44. metadata +105 -0
@@ -0,0 +1,65 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <createCustomerProfileTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
3
+ <merchantAuthentication>
4
+ <name>4Pf3E54zCsW</name>
5
+ <transactionKey>337UTt4y6DB64ft8</transactionKey>
6
+ </merchantAuthentication>
7
+ <transaction>
8
+ <profileTransRefund>
9
+ <amount>66.35</amount>
10
+ <customerProfileId>24580093</customerProfileId>
11
+ <customerPaymentProfileId>22514176</customerPaymentProfileId>
12
+ <transId>2208268756</transId>
13
+ </profileTransRefund>
14
+ </transaction>
15
+ </createCustomerProfileTransactionRequest>
16
+
17
+ <?xml version="1.0" encoding="utf-8"?>
18
+ <createCustomerProfileTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
19
+ <merchantAuthentication>
20
+ <name>API_LOGIN_ID</name>
21
+ <transactionKey>API_TRANSACTION_KEY</transactionKey>
22
+ </merchantAuthentication>
23
+ <transaction>
24
+ <profileTransRefund>
25
+ <amount>10.95</amount>
26
+ <tax>
27
+ <amount>1.00</amount>
28
+ <name>WA state sales tax</name>
29
+ <description>Washington state sales tax</description>
30
+ </tax>
31
+ <shipping>
32
+ <amount>2.00</amount>
33
+ <name>ground based shipping</name>
34
+ <description>Ground based 5 to 10 day shipping</description>
35
+ </shipping>
36
+ <lineItems>
37
+ <itemId>ITEM00001</itemId>
38
+ <name>name of item sold</name>
39
+ <description>Description of item sold</description>
40
+ <quantity>1</quantity>
41
+ <unitPrice>6.95</unitPrice>
42
+ <taxable>true</taxable>
43
+ </lineItems>
44
+ <lineItems>
45
+ <itemId>ITEM00002</itemId>
46
+ <name>name of other item sold</name>
47
+ <description>Description of other item sold</description>
48
+ <quantity>1</quantity>
49
+ <unitPrice>1.00</unitPrice>
50
+ <taxable>true</taxable>
51
+ </lineItems>
52
+ <customerProfileId>10000</customerProfileId>
53
+ <customerPaymentProfileId>20000</customerPaymentProfileId>
54
+ <customerShippingAddressId>30000</customerShippingAddressId>
55
+ <creditCardNumberMasked>XXXX1111</creditCardNumberMasked>
56
+ <order>
57
+ <invoiceNumber>INV000001</invoiceNumber>
58
+ <description>description of transaction</description>
59
+ <purchaseOrderNumber>PONUM000001</purchaseOrderNumber>
60
+ </order>
61
+ <transId>40000</transId>
62
+ </profileTransRefund>
63
+ </transaction>
64
+ <extraOptions><![CDATA[]]></extraOptions>
65
+ </createCustomerProfileTransactionRequest>
@@ -0,0 +1,172 @@
1
+ module AuthorizeNet
2
+
3
+ # The core, xml response class. You shouldn't instantiate this one.
4
+ # Instead you should use AuthorizeNet::ARB::Response.
5
+ class XmlResponse < AuthorizeNet::Response
6
+
7
+ # DO NOT USE. Instantiate AuthorizeNet::ARB::Response or AuthorizeNet::CIM::Response instead.
8
+ def initialize(raw_response, transaction)
9
+ @raw_response = raw_response
10
+ @transaction = transaction
11
+ unless connection_failure?
12
+ begin
13
+ xml = Nokogiri::XML(@raw_response.body) do |config|
14
+ # confirm noent is the right flag
15
+ config.recover.noent.nonet
16
+ end
17
+ @root = xml.children[0]
18
+ @result_code = node_content_unless_nil(@root.at_css('messages resultCode'))
19
+ @message_code = node_content_unless_nil(@root.at_css('messages message code'))
20
+ @message_text = node_content_unless_nil(@root.at_css('messages message text'))
21
+ @reference_id = node_content_unless_nil(@root.at_css('refId'))
22
+ rescue
23
+ @raw_response = $!
24
+ end
25
+ end
26
+ end
27
+
28
+ # Check to see if the response indicated success. Success is defined as a 200 OK response with a resultCode
29
+ # of 'Ok'.
30
+ def success?
31
+ !connection_failure? && @result_code == 'Ok'
32
+ end
33
+
34
+ # Returns true if we failed to open a connection to the gateway or got back a non-200 OK HTTP response.
35
+ def connection_failure?
36
+ !@raw_response.kind_of?(Net::HTTPOK)
37
+ end
38
+
39
+ # Returns the underlying Net::HTTPResponse object. This has the original response body along with
40
+ # headers and such. Note that if an exception is generated while making the request (which happens
41
+ # if there is no internet connection for example), you will get the exception object here instead of
42
+ # a Net::HTTPResponse object.
43
+ def raw
44
+ @raw_response
45
+ end
46
+
47
+ # Returns a deep-copy of the XML object received from the payment gateway. Or nil if there was no XML payload.
48
+ def xml
49
+ @root.dup unless @root.nil?
50
+ end
51
+
52
+ # Returns the resultCode from the XML response. resultCode will be either 'Ok' or 'Error'.
53
+ def result_code
54
+ @result_code
55
+ end
56
+
57
+ # Returns the messageCode from the XML response. This is a code indicating the details of an error
58
+ # or success.
59
+ def message_code
60
+ @message_code
61
+ end
62
+
63
+ # Returns the messageText from the XML response. This is a text description of the message_code.
64
+ def message_text
65
+ @message_text
66
+ end
67
+
68
+ # Alias for result_code.
69
+ def response_code
70
+ result_code
71
+ end
72
+
73
+ # Alias for message_code.
74
+ def response_reason_code
75
+ message_code
76
+ end
77
+
78
+ # Alias for message_text.
79
+ def response_reason_text
80
+ message_text
81
+ end
82
+
83
+ # Returns the refId from the response if there is one. Otherwise returns nil.
84
+ def reference_id
85
+ @reference_id
86
+ end
87
+
88
+ #:enddoc:
89
+ protected
90
+
91
+ def node_content_unless_nil(node)
92
+ if node.nil?
93
+ nil
94
+ else
95
+ node.content
96
+ end
97
+ end
98
+
99
+ def node_child_content_unless_nil(node)
100
+ if node.nil?
101
+ nil
102
+ else
103
+ if node.children.length > 0
104
+ node.children.collect(&:content)
105
+ else
106
+ nil
107
+ end
108
+ end
109
+ end
110
+
111
+ # Transforms a block of XML into a model Object defined by entity_desc.
112
+ def build_entity(xml, entity_desc)
113
+ args = {}
114
+ entity_desc.node_structure.each do |node_desc|
115
+ node_name = (node_desc.keys.reject {|k| k.to_s[0..0] == '_' }).first
116
+ args.merge!(handle_node_type(xml, node_desc, node_name, args, ''))
117
+ end
118
+
119
+ if args.length == 0
120
+ return nil
121
+ end
122
+
123
+ if entity_desc.arg_mapping.nil?
124
+ return entity_desc.entity_class.new(args)
125
+ else
126
+ args_list = []
127
+ entity_desc.arg_mapping.each do |arg|
128
+ args_list <<= args[arg]
129
+ args.delete(arg)
130
+ end
131
+ args_list <<= args
132
+ return entity_desc.entity_class.new(*args_list)
133
+ end
134
+ end
135
+
136
+ # Parses an XML fragment into an internal representation.
137
+ def handle_node_type(xml, node_desc, node_name, args, base_name)
138
+ case node_desc[node_name]
139
+ when Symbol
140
+ node = xml.at_css(base_name + node_name.to_s)
141
+ unless node.nil?
142
+ content = node.content
143
+ case node_desc[:_converter]
144
+ when Method, Proc
145
+ content = node_desc[:_converter].call(content)
146
+ when Symbol
147
+ content = self.send(node_desc[:_converter], content)
148
+ end
149
+ args[node_desc[node_name]] = content unless content.nil?
150
+ end
151
+ when AuthorizeNet::EntityDescription
152
+ unless node_desc[:_multivalue].nil?
153
+ xml.css(base_name + node_name.to_s).each do |node|
154
+ entity = build_entity(node, node_desc[node_name])
155
+ args[node_desc[:_multivalue]] = args[node_desc[:_multivalue]].to_a + entity.to_a unless entity.nil?
156
+ end
157
+ else
158
+ entity = build_entity(xml.css(base_name + node_name.to_s), node_desc[node_name])
159
+ args[node_desc[:_value]] = entity unless entity.nil?
160
+ end
161
+ when Array
162
+ node_desc[node_name].each do |inner_node|
163
+ inner_node_name = (inner_node.keys.reject {|k| k.to_s[0..0] == '_' }).first
164
+ args.merge!(handle_node_type(xml, inner_node, inner_node_name, args, node_name.to_s + ' '))
165
+ end
166
+ end
167
+ return args
168
+ end
169
+
170
+ end
171
+
172
+ end
@@ -0,0 +1,277 @@
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://api.authorize.net/xml/v1/request.api'
12
+ TEST = 'https://apitest.authorize.net/xml/v1/request.api'
13
+ #TEST = 'https://qavercp1d.vposdownload.qa.intra/xml/v1/reseller.api'
14
+ #TEST = 'http://10.43.73.163/xml/v1/reseller.api'
15
+ end
16
+
17
+ # Constants for both the various Authorize.Net transaction types are defined here.
18
+ module Type
19
+ ARB_CREATE = "ARBCreateSubscriptionRequest"
20
+ ARB_UPDATE = "ARBUpdateSubscriptionRequest"
21
+ ARB_GET_STATUS = "ARBGetSubscriptionStatusRequest"
22
+ ARB_CANCEL = "ARBCancelSubscriptionRequest"
23
+ CIM_CREATE_PROFILE = "createCustomerProfileRequest"
24
+ CIM_CREATE_PAYMENT = "createCustomerPaymentProfileRequest"
25
+ CIM_CREATE_ADDRESS = "createCustomerShippingAddressRequest"
26
+ CIM_CREATE_TRANSACTION = "createCustomerProfileTransactionRequest"
27
+ CIM_DELETE_PROFILE = "deleteCustomerProfileRequest"
28
+ CIM_DELETE_PAYMENT = "deleteCustomerPaymentProfileRequest"
29
+ CIM_DELETE_ADDRESS = "deleteCustomerShippingAddressRequest"
30
+ CIM_GET_PROFILE_IDS = "getCustomerProfileIdsRequest"
31
+ CIM_GET_PROFILE = "getCustomerProfileRequest"
32
+ CIM_GET_PAYMENT = "getCustomerPaymentProfileRequest"
33
+ CIM_GET_ADDRESS = "getCustomerShippingAddressRequest"
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_TRANSACTION_DETAILS = "getTransactionDetailsRequest"
42
+ end
43
+
44
+ # Fields to convert to/from booleans.
45
+ @@boolean_fields = []
46
+
47
+ # Fields to convert to/from BigDecimal.
48
+ @@decimal_fields = []
49
+
50
+ # Fields to convert to/from Date.
51
+ @@date_fields = []
52
+
53
+ # Fields to convert to/from DateTime.
54
+ @@datetime_fields = []
55
+
56
+ # The class to wrap our response in.
57
+ @response_class = AuthorizeNet::XmlResponse
58
+
59
+ # The default options for the constructor.
60
+ @@option_defaults = {
61
+ :gateway => :production,
62
+ :verify_ssl => false,
63
+ :reference_id => nil
64
+ }
65
+
66
+ # DO NOT USE. Instantiate AuthorizeNet::ARB::Transaction or AuthorizeNet::CIM::Transaction instead.
67
+ def initialize(api_login_id, api_transaction_key, options = {})
68
+ super()
69
+ @api_login_id = api_login_id
70
+ @api_transaction_key = api_transaction_key
71
+
72
+ @response ||= nil
73
+ @type ||= nil
74
+
75
+ options = @@option_defaults.merge(options)
76
+ @verify_ssl = options[:verify_ssl]
77
+ @reference_id = options[:reference_id]
78
+ case options[:gateway]
79
+ when :sandbox, :test
80
+ @gateway = Gateway::TEST
81
+ when :production, :live
82
+ @gateway = Gateway::LIVE
83
+ else
84
+ @gateway = options[:gateway]
85
+ end
86
+ end
87
+
88
+ # Checks if the transaction has been configured for the sandbox or not. Return FALSE if the
89
+ # transaction is running against the production, TRUE otherwise.
90
+ def test?
91
+ @gateway != Gateway::LIVE
92
+ end
93
+
94
+ # Checks to see if the transaction has a response (meaning it has been submitted to the gateway).
95
+ # Returns TRUE if a response is present, FALSE otherwise.
96
+ def has_response?
97
+ !@response.nil?
98
+ end
99
+
100
+ # Retrieve the response object (or Nil if transaction hasn't been sent to the gateway).
101
+ def response
102
+ @response
103
+ end
104
+
105
+ # Submits the transaction to the gateway for processing. Returns a response object. If the transaction
106
+ # has already been run, it will return nil.
107
+ def run
108
+ make_request
109
+ end
110
+
111
+ # Returns a deep-copy of the XML object sent to the payment gateway. Or nil if there was no XML payload.
112
+ def xml
113
+ @xml
114
+ end
115
+
116
+ #:enddoc:
117
+ protected
118
+
119
+ # Takes a list of nodes (a Hash is a node, and Array is a list) and returns True if any nodes
120
+ # would be built by build_nodes. False if no new nodes would be generated.
121
+ def has_content(nodeList, data)
122
+ nodeList.each do |node|
123
+ nodeName = (node.keys.reject {|k| nodeName.to_s[0..0] == '_' }).first
124
+ multivalue = node[:_multivalue]
125
+ conditional = node[:_conditional]
126
+ value = node[nodeName]
127
+ unless conditional.nil?
128
+ value = self.send(conditional, nodeName)
129
+ end
130
+ case value
131
+ when Array
132
+ if multivalue.nil?
133
+ if has_content(value, data)
134
+ return true
135
+ end
136
+ else
137
+ data[multivalue].each do |v|
138
+ if has_content(value, v)
139
+ return true
140
+ end
141
+ end
142
+ end
143
+ when Symbol
144
+ converted = convert_field(value, data[value])
145
+ return true unless converted.nil?
146
+ else
147
+ return true
148
+ end
149
+ end
150
+ false
151
+ end
152
+
153
+ # Takes a list of nodes (a Hash is a node, and Array is a list) and recursively builds the XML by pulling
154
+ # values as needed from data.
155
+ def build_nodes(builder, nodeList, data)
156
+ nodeList.each do |node|
157
+ # TODO - ADD COMMENTS HERE
158
+ nodeName = (node.keys.reject {|k| k.to_s[0..0] == '_' }).first
159
+ multivalue = node[:_multivalue]
160
+ conditional = node[:_conditional]
161
+ value = node[nodeName]
162
+ unless conditional.nil?
163
+ value = self.send(conditional, nodeName)
164
+ end
165
+ case value
166
+ when Array # node containing other nodes
167
+ if multivalue.nil?
168
+ proc = Proc.new { build_nodes(builder, value, data) }
169
+ builder.send(nodeName, &proc) if has_content(value, data)
170
+ else
171
+ data[multivalue].to_a.each do |v|
172
+ proc = Proc.new { build_nodes(builder, value, v) }
173
+ builder.send(nodeName, &proc) if has_content(value, v)
174
+ end
175
+ end
176
+ when Symbol # node containing actual data
177
+ if data[value].kind_of?(Array)
178
+ data[value].each do |v|
179
+ converted = convert_field(value, v)
180
+ builder.send(nodeName, converted) unless converted.nil?
181
+ end
182
+ else
183
+ converted = convert_field(value, data[value])
184
+ builder.send(nodeName, converted) unless converted.nil?
185
+ end
186
+ else
187
+ builder.send(nodeName, value)
188
+ end
189
+ end
190
+ end
191
+
192
+ def convert_field(field, value)
193
+ if @@boolean_fields.include?(field) and !value.nil?
194
+ return boolean_to_value(value)
195
+ elsif @@decimal_fields.include?(field) and !value.nil?
196
+ return decimal_to_value(value)
197
+ elsif @@date_fields.include?(field) and !value.nil?
198
+ return date_to_value(value)
199
+ elsif @@datetime_fields.include?(field) and !value.nil?
200
+ return datetime_to_value(value)
201
+ elsif field == :extra_options
202
+ # handle converting extra options
203
+ options = []
204
+ unless value.nil?
205
+ value.each_pair{|k,v| options <<= self.to_param(k, v)}
206
+ end
207
+ unless @custom_fields.nil?
208
+ # special sort to maintain compatibility with AIM custom field ordering
209
+ # FIXME - This should be DRY'd up.
210
+ custom_field_keys = @custom_fields.keys.collect(&:to_s).sort.collect(&:to_sym)
211
+ for key in custom_field_keys
212
+ options <<= self.to_param(key, @custom_fields[key.to_sym], '')
213
+ end
214
+ end
215
+
216
+ if options.length > 0
217
+ return options.join('&')
218
+ else
219
+ return nil
220
+ end
221
+ elsif field == :exp_date
222
+ # convert MMYY expiration dates into the XML equivalent
223
+ unless value.nil?
224
+ begin
225
+ return Date.strptime(value.to_s, '%m%y').strftime('%Y-%m')
226
+ rescue
227
+ # If we didn't get the exp_date in MMYY format, try our best to convert it
228
+ return Date.parse(value.to_s).strftime('%Y-%m')
229
+ end
230
+ end
231
+ end
232
+
233
+ value
234
+ end
235
+
236
+ # An internal method that builds the POST body, submits it to the gateway, and constructs a Response object with the response.
237
+ def make_request
238
+ if has_response?
239
+ return nil
240
+ end
241
+
242
+ fields = @fields
243
+
244
+ builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |x|
245
+ x.send(@type.to_sym, :xmlns => XML_NAMESPACE) {
246
+ x.merchantAuthentication {
247
+ x.name @api_login_id
248
+ x.transactionKey @api_transaction_key
249
+ }
250
+ build_nodes(x, self.class.const_get(:FIELDS)[@type], fields)
251
+ }
252
+ end
253
+ @xml = builder.to_xml
254
+
255
+ url = URI.parse(@gateway)
256
+
257
+ request = Net::HTTP::Post.new(url.path)
258
+ request.content_type = 'text/xml'
259
+ request.body = @xml
260
+ connection = Net::HTTP.new(url.host, url.port)
261
+ connection.use_ssl = true
262
+ if @verify_ssl
263
+ connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
264
+ else
265
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
266
+ end
267
+
268
+ # Use our Class's @response_class variable to find the Response class we are supposed to use.
269
+ begin
270
+ @response = self.class.instance_variable_get(:@response_class).new((connection.start {|http| http.request(request)}), self)
271
+ rescue
272
+ @response = self.class.instance_variable_get(:@response_class).new($!, self)
273
+ end
274
+ end
275
+
276
+ end
277
+ end