yankl 2.0.1

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 (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