authorizenet 1.8.0

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 (42) hide show
  1. checksums.yaml +7 -0
  2. data/lib/app/helpers/authorize_net_helper.rb +24 -0
  3. data/lib/authorize_net.rb +92 -0
  4. data/lib/authorize_net/addresses/address.rb +29 -0
  5. data/lib/authorize_net/addresses/shipping_address.rb +26 -0
  6. data/lib/authorize_net/aim/response.rb +131 -0
  7. data/lib/authorize_net/aim/transaction.rb +184 -0
  8. data/lib/authorize_net/arb/response.rb +34 -0
  9. data/lib/authorize_net/arb/subscription.rb +72 -0
  10. data/lib/authorize_net/arb/transaction.rb +146 -0
  11. data/lib/authorize_net/authorize_net.rb +154 -0
  12. data/lib/authorize_net/cim/customer_profile.rb +19 -0
  13. data/lib/authorize_net/cim/payment_profile.rb +37 -0
  14. data/lib/authorize_net/cim/response.rb +110 -0
  15. data/lib/authorize_net/cim/transaction.rb +678 -0
  16. data/lib/authorize_net/customer.rb +27 -0
  17. data/lib/authorize_net/email_receipt.rb +24 -0
  18. data/lib/authorize_net/fields.rb +736 -0
  19. data/lib/authorize_net/key_value_response.rb +117 -0
  20. data/lib/authorize_net/key_value_transaction.rb +291 -0
  21. data/lib/authorize_net/line_item.rb +25 -0
  22. data/lib/authorize_net/order.rb +42 -0
  23. data/lib/authorize_net/payment_methods/credit_card.rb +74 -0
  24. data/lib/authorize_net/payment_methods/echeck.rb +72 -0
  25. data/lib/authorize_net/reporting/batch.rb +19 -0
  26. data/lib/authorize_net/reporting/batch_statistics.rb +19 -0
  27. data/lib/authorize_net/reporting/fds_filter.rb +11 -0
  28. data/lib/authorize_net/reporting/response.rb +127 -0
  29. data/lib/authorize_net/reporting/transaction.rb +116 -0
  30. data/lib/authorize_net/reporting/transaction_details.rb +25 -0
  31. data/lib/authorize_net/response.rb +27 -0
  32. data/lib/authorize_net/sim/hosted_payment_form.rb +38 -0
  33. data/lib/authorize_net/sim/hosted_receipt_page.rb +37 -0
  34. data/lib/authorize_net/sim/response.rb +142 -0
  35. data/lib/authorize_net/sim/transaction.rb +138 -0
  36. data/lib/authorize_net/transaction.rb +66 -0
  37. data/lib/authorize_net/xml_response.rb +172 -0
  38. data/lib/authorize_net/xml_transaction.rb +275 -0
  39. data/lib/authorizenet.rb +4 -0
  40. data/lib/generators/authorize_net/direct_post_generator.rb +51 -0
  41. data/lib/generators/authorize_net/sim_generator.rb +47 -0
  42. metadata +104 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 05a6564190f0053229964b6eb9420e268cb52840
4
+ data.tar.gz: d871b9c10bfb798c784b3b9242b5c230a5896ce3
5
+ SHA512:
6
+ metadata.gz: abffcf5aca709932fc317311af410d21f3329b6b799dbaa0903c20a928c75ffb6f95ecea2b93a2482972ee96fd25975842f99b40d2270ec41aa12f980f6f1dfd
7
+ data.tar.gz: b4cfaf36863847afbb9ddfa0943bd8cf6e12e2562ee1314a375448e8c4e3e7f87740605d41f339b507a93b6cdca59f44c89f2e29f198dba1ba364158890fc6be
@@ -0,0 +1,24 @@
1
+ # The Authorize.Net Rails Helper module. Provides methods to assist with integrating the various APIs.
2
+
3
+ module AuthorizeNetHelper
4
+
5
+ # Generates a collection of hidden form fields (as a raw HTML string) for a AuthorizeNet::SIM::Transaction
6
+ # (sim_transaction). You can specify any html_options that hidden_field_tag accepts, and the
7
+ # hidden fields will be built with those options.
8
+ def sim_fields(sim_transaction, html_options = {})
9
+ fields = sim_transaction.form_fields.collect do |k, v|
10
+ if v.kind_of? Array
11
+ v.collect { |val| hidden_field_tag(k, val, html_options) }
12
+ else
13
+ hidden_field_tag(k, v, html_options)
14
+ end
15
+ end
16
+ fields.flatten!
17
+ field_str = fields.join("\n")
18
+ if field_str.respond_to?(:html_safe)
19
+ return field_str.html_safe
20
+ else
21
+ return field_str
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,92 @@
1
+ # The SDK initialization enters here. Loads all needed libraries and files. Inspects
2
+ # the current runtime to see if Rails is present. If it is, we inject our helper into
3
+ # ActiveSupport.
4
+
5
+ require "cgi"
6
+ require "net/https"
7
+ require "uri"
8
+ require "openssl"
9
+ require 'bigdecimal'
10
+ require 'nokogiri'
11
+ require 'date'
12
+
13
+ # TODO: Add local data validation where possible
14
+
15
+ $:.unshift File.dirname(__FILE__)
16
+
17
+ require "authorize_net/authorize_net"
18
+ require "authorize_net/payment_methods/credit_card"
19
+ require "authorize_net/payment_methods/echeck"
20
+ require "authorize_net/addresses/address"
21
+ require "authorize_net/addresses/shipping_address"
22
+ require "authorize_net/customer"
23
+ require "authorize_net/email_receipt"
24
+ require "authorize_net/order"
25
+ require "authorize_net/line_item"
26
+ require "authorize_net/cim/payment_profile"
27
+ require "authorize_net/cim/customer_profile"
28
+ require "authorize_net/reporting/batch"
29
+ require "authorize_net/reporting/batch_statistics"
30
+ require "authorize_net/reporting/transaction_details"
31
+ require "authorize_net/reporting/fds_filter"
32
+ require "authorize_net/response"
33
+ require "authorize_net/key_value_response"
34
+ require "authorize_net/xml_response"
35
+ require "authorize_net/transaction"
36
+ require "authorize_net/key_value_transaction"
37
+ require "authorize_net/xml_transaction"
38
+ require "authorize_net/fields"
39
+
40
+ # AIM
41
+
42
+ require "authorize_net/aim/transaction"
43
+ require "authorize_net/aim/response"
44
+
45
+ # SIM
46
+
47
+ require "authorize_net/sim/hosted_payment_form"
48
+ require "authorize_net/sim/hosted_receipt_page"
49
+ require "authorize_net/sim/transaction"
50
+ require "authorize_net/sim/response"
51
+
52
+ # ARB
53
+
54
+ require "authorize_net/arb/subscription"
55
+ require "authorize_net/arb/response"
56
+ require "authorize_net/arb/transaction"
57
+
58
+ # CIM
59
+
60
+ require "authorize_net/cim/response"
61
+ require "authorize_net/cim/transaction"
62
+
63
+ # Reporting
64
+
65
+ require "authorize_net/reporting/response"
66
+ require "authorize_net/reporting/transaction"
67
+
68
+ # Load our Rails plugin
69
+
70
+ if defined?(Rails)
71
+ if defined?(Rails::Railtie)
72
+ module AuthorizeNet
73
+ class Railtie < Rails::Railtie
74
+ initializer "authorize_net.load_path_initialize" do |app|
75
+ %w{ models controllers helpers }.each do |dir|
76
+ path = File.join(File.dirname(__FILE__), 'app', dir)
77
+ $LOAD_PATH << path
78
+ ActiveSupport::Dependencies.autoload_paths << path
79
+ ActiveSupport::Dependencies.autoload_once_paths.delete(path)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ else
85
+ %w{ models controllers helpers }.each do |dir|
86
+ path = File.join(File.dirname(__FILE__), 'app', dir)
87
+ $LOAD_PATH << path
88
+ ActiveSupport::Dependencies.load_paths << path
89
+ ActiveSupport::Dependencies.load_once_paths.delete(path)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,29 @@
1
+ module AuthorizeNet
2
+
3
+ # Models an address.
4
+ class Address
5
+
6
+ include AuthorizeNet::Model
7
+
8
+ attr_accessor :first_name, :last_name, :company, :street_address, :city, :state, :zip, :country, :phone, :fax, :customer_address_id
9
+
10
+ def to_hash
11
+ hash = {
12
+ :first_name => @first_name,
13
+ :last_name => @last_name,
14
+ :company => @company,
15
+ :address => @street_address,
16
+ :city => @city,
17
+ :state => @state,
18
+ :zip => @zip,
19
+ :country => @country,
20
+ :phone => @phone,
21
+ :fax => @fax,
22
+ :customer_address_id => @customer_address_id
23
+ }
24
+ hash.delete_if {|k, v| v.nil?}
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,26 @@
1
+ module AuthorizeNet
2
+
3
+ # Models a shipping address.
4
+ class ShippingAddress < Address
5
+
6
+ include AuthorizeNet::Model
7
+
8
+ def to_hash
9
+ hash = {
10
+ :ship_to_first_name => @first_name,
11
+ :ship_to_last_name => @last_name,
12
+ :ship_to_company => @company,
13
+ :ship_to_address => @street_address,
14
+ :ship_to_city => @city,
15
+ :ship_to_state => @state,
16
+ :ship_to_zip => @zip,
17
+ :ship_to_country => @country,
18
+ :ship_to_phone => @phone,
19
+ :ship_to_fax => @fax
20
+ }
21
+ hash.delete_if {|k, v| v.nil?}
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,131 @@
1
+ module AuthorizeNet::AIM
2
+
3
+ # The AIM response class. Handles parsing the response from the gateway.
4
+ class Response < AuthorizeNet::KeyValueResponse
5
+
6
+ # Our MD5 digest generator.
7
+ @@digest = OpenSSL::Digest::Digest.new('md5')
8
+
9
+ include AuthorizeNet::AIM::Fields
10
+
11
+ # Fields to convert to/from booleans.
12
+ @@boolean_fields = [:tax_exempt]
13
+
14
+ # Fields to convert to/from BigDecimal.
15
+ @@decimal_fields = [:amount, :tax, :freight, :duty, :requested, :balance_on_card]
16
+
17
+
18
+ # Constructs a new response object from a +raw_response+ and the +transaction+ that generated
19
+ # the +raw_response+. You don't typically construct this object yourself, as AuthorizeNet::AIM::Transaction
20
+ # will build one for you when it makes the request to the gateway.
21
+ def initialize(raw_response, transaction)
22
+ @version = transaction.version
23
+ raise "AuthorizeNet gem only supports AIM version 3.1" unless @version.to_s == '3.1'
24
+ @raw_response = raw_response
25
+ @fields = {}
26
+ @transaction = transaction
27
+ custom_field_names = transaction.custom_fields.keys.collect(&:to_s).sort.collect(&:to_sym)
28
+ @custom_fields = {}
29
+ split_on = transaction.delimiter
30
+ if @raw_response.kind_of?(Net::HTTPOK) || @raw_response.kind_of?(Nokogiri::XML::Element)
31
+ if @raw_response.kind_of?(Net::HTTPOK)
32
+ raw_data = @raw_response.body
33
+ else
34
+ raw_data = @raw_response.text
35
+ end
36
+ unless transaction.encapsulation_character.nil?
37
+ split_on = transaction.encapsulation_character + split_on + transaction.encapsulation_character
38
+ raw_data = raw_data[1..raw_data.length - 2]
39
+ end
40
+ raw_data.split(split_on).each_with_index do |field, index|
41
+ if transaction.cp_version.nil?
42
+ field_desc = FIELDS
43
+ else
44
+ field_desc = CP_FIELDS
45
+ end
46
+ if index < field_desc.length
47
+ @fields[field_desc[index]] = field
48
+ else
49
+ @custom_fields[custom_field_names[index - field_desc.length]] = field
50
+ end
51
+ end
52
+ @fields.delete(nil)
53
+ @fields.each do |k, v|
54
+ if @@boolean_fields.include?(k)
55
+ @fields[k] = value_to_boolean(v)
56
+ elsif @@decimal_fields.include?(k)
57
+ @fields[k] = value_to_decimal(v)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ # Returns True if the MD5 hash found in the response payload validates using
64
+ # the supplied api_login and secret merchant_value (THIS IS NOT YOUR API KEY).
65
+ def valid_md5?(api_login, merchant_value)
66
+ if @fields[:md5_hash].nil?
67
+ return false
68
+ end
69
+ @@digest.hexdigest("#{merchant_value}#{api_login}#{@fields[:transaction_id]}#{@transaction.fields[:amount]}").downcase == @fields[:md5_hash].downcase
70
+ end
71
+
72
+ # Returns the current API version that we are adhering to.
73
+ def version
74
+ @version
75
+ end
76
+
77
+ # Check to see if the response indicated success. Success is defined as a 200 OK response indicating
78
+ # that the transaction was approved.
79
+ def success?
80
+ !connection_failure? && approved?
81
+ end
82
+
83
+ # Returns true if we failed to open a connection to the gateway or got back a non-200 OK HTTP response.
84
+ def connection_failure?
85
+ !@raw_response.kind_of?(Net::HTTPOK) && !@raw_response.kind_of?(Nokogiri::XML::Element)
86
+ end
87
+
88
+ # Returns the underlying Net::HTTPResponse object. This has the original response body along with
89
+ # headers and such. Note that if an exception is generated while making the request (which happens
90
+ # if there is no internet connection for example), you will get the exception object here instead of
91
+ # a Net::HTTPResponse object.
92
+ def raw
93
+ @raw_response
94
+ end
95
+
96
+ # Returns the AuthorizeNet::Transaction instance that owns this response.
97
+ def transaction
98
+ @transaction
99
+ end
100
+
101
+ # Returns the transaction's authorization code. This should be shown to the
102
+ # end user.
103
+ def authorization_code
104
+ @fields[:authorization_code]
105
+ end
106
+
107
+ # Returns the transaction's authorization id. You will need this for future void, refund
108
+ # and prior authorization capture requests.
109
+ def transaction_id
110
+ @fields[:transaction_id]
111
+ end
112
+
113
+ # Returns the customer id from the response.
114
+ def customer_id
115
+ @fields[:customer_id]
116
+ end
117
+
118
+ # Returns a response code (from AVSResponseCode) indicating the result of any Address Verification
119
+ # Service checks.
120
+ def avs_response
121
+ @fields[:avs_response]
122
+ end
123
+
124
+ # Returns the credit card type used in the transaction. The values returned can be found in CardType.
125
+ def card_type
126
+ @fields[:card_type]
127
+ end
128
+
129
+ end
130
+
131
+ end
@@ -0,0 +1,184 @@
1
+ module AuthorizeNet::AIM
2
+
3
+ # The AIM transaction class. Handles building the transaction payload and
4
+ # transmitting it to the gateway.
5
+ class Transaction < AuthorizeNet::KeyValueTransaction
6
+
7
+ # The default options for the constructor.
8
+ @@option_defaults = {
9
+ :transaction_type => Type::AUTHORIZE_AND_CAPTURE,
10
+ :gateway => :production,
11
+ :test => false,
12
+ :allow_split => false,
13
+ :delimiter => ',',
14
+ :encapsulation_character => nil,
15
+ :verify_ssl => false,
16
+ :device_type => DeviceType::UNKNOWN,
17
+ :market_type => MarketType::RETAIL
18
+ }
19
+
20
+ # Fields to convert to/from booleans.
21
+ @@boolean_fields = [:tax_exempt, :test_request, :recurring_billing, :allow_partial_auth, :delim_data, :email_customer, :relay_response]
22
+
23
+ # Fields to convert to/from BigDecimal.
24
+ @@decimal_fields = [:amount]
25
+
26
+ # Constructs an AIM transaction. You can use the new AIM transaction object
27
+ # to issue a request to the payment gateway and parse the response into a new
28
+ # AuthorizeNet::AIM::Response object.
29
+ #
30
+ # +api_login_id+:: Your API login ID, as a string.
31
+ # +api_transaction_key+:: Your API transaction key, as a string.
32
+ # +options+:: A hash of options. See below for values.
33
+ #
34
+ # Options
35
+ # +transaction_type+:: The type of transaction to perform. Defaults to AuthorizeNet::Type::AUTHORIZE_AND_CAPTURE. This value is only used if run is called directly.
36
+ # +gateway+:: The gateway to submit the transaction to. Can be a URL string, an AuthorizeNet::AIM::Transaction::Gateway constant, or one of the convenience symbols :sandbox, :test, :card_present_test, :card_present_live, :card_present_sandbox, :card_present_production, :production, or :live (:test is an alias for :sandbox, :card_present_test is an alias for :card_present_sandbox, :card_present_production is an alias for :card_present_live, and :live is an alias for :production).
37
+ # +test+:: A boolean indicating if the transaction should be run in test mode or not (defaults to false).
38
+ # +allow_split+:: A boolean indicating if split transactions should be allowed (defaults to false).
39
+ # +delimiter+:: A single character (as a string) that will be used to delimit the response from the gateway. Defaults to ','.
40
+ # +encapsulation_character+:: A single character (as a string) that will be used to encapsulate each field in the response from the gateway. Defaults to nil.
41
+ # +verify_ssl+:: A boolean indicating if the SSL certificate of the +gateway+ should be verified. Defaults to false.
42
+ # +device_type+:: A constant from DeviceType indicating the type of POS device used in a card present transaction. Defaults to DeviceType::UNKNOWN.
43
+ # +market_type+:: A constant from MarketType indicating your industry. Used for card present transactions. Defaults to MarketType::RETAIL.
44
+ #
45
+ def initialize(api_login_id, api_transaction_key, options = {})
46
+ super()
47
+ options = @@option_defaults.merge(options)
48
+ @api_login_id = api_login_id
49
+ @api_transaction_key = api_transaction_key
50
+ @test_mode = options[:test]
51
+ @response ||= nil
52
+ @delimiter = options[:delimiter]
53
+ @type = options[:transaction_type]
54
+ @cp_version = nil
55
+ case options[:gateway]
56
+ when :sandbox, :test
57
+ @gateway = Gateway::TEST
58
+ when :production, :live
59
+ @gateway = Gateway::LIVE
60
+ when :card_present_live, :card_present_production
61
+ @gateway = Gateway::CARD_PRESENT_LIVE
62
+ @cp_version = '1.0'
63
+ when :card_present_test, :card_present_sandbox
64
+ @gateway = Gateway::CARD_PRESENT_TEST
65
+ @cp_version = '1.0'
66
+ else
67
+ @gateway = options[:gateway]
68
+ end
69
+ @allow_split_transaction = options[:allow_split]
70
+ @encapsulation_character = options[:encapsulation_character]
71
+ @verify_ssl = options[:verify_ssl]
72
+ @market_type = options[:market_type]
73
+ @device_type = options[:device_type]
74
+ end
75
+
76
+ # Checks if the transaction has been configured for test mode or not. Return TRUE if the
77
+ # transaction is a test transaction, FALSE otherwise. All transactions run against the sandbox
78
+ # are considered test transactions.
79
+ def test?
80
+ super || @gateway == Gateway::TEST
81
+ end
82
+
83
+ # Returns TRUE if split transactions are allowed, FALSE otherwise.
84
+ def split_transaction_allowed?
85
+ !!@allow_split_transaction
86
+ end
87
+
88
+ # Returns the current encapsulation character unless there is none, in which case Nil is returned.
89
+ def encapsulation_character
90
+ @encapsulation_character
91
+ end
92
+
93
+ # Returns the gateway to be used for this transaction.
94
+ def gateway
95
+ @gateway
96
+ end
97
+
98
+ # Checks to see if the transaction has a response (meaning it has been submitted to the gateway).
99
+ # Returns TRUE if a response is present, FALSE otherwise.
100
+ def has_response?
101
+ !@response.nil?
102
+ end
103
+
104
+ # Retrieve the response object (or Nil if transaction hasn't been sent to the gateway).
105
+ def response
106
+ @response
107
+ end
108
+
109
+ # Returns the current delimiter we are using to parse the fields returned by the
110
+ # gateway.
111
+ def delimiter
112
+ @delimiter
113
+ end
114
+
115
+ # Sets the delimiter used to parse the response from the gateway.
116
+ def delimiter=(delimiter)
117
+ @delimiter = delimiter
118
+ end
119
+
120
+ # Submits the transaction to the gateway for processing. Returns a response object. If the transaction
121
+ # has already been run, it will return nil.
122
+ def run
123
+ make_request
124
+ end
125
+
126
+ # Returns the current card present API version that we are adhering to.
127
+ def cp_version
128
+ @cp_version
129
+ end
130
+
131
+ #:enddoc:
132
+ protected
133
+
134
+ # An internal method that builds the POST body, submits it to the gateway, and constructs a Response object with the response.
135
+ def make_request
136
+ if has_response?
137
+ return nil
138
+ end
139
+ url = URI.parse(@gateway)
140
+ fields = @fields.merge(:type => @type, :delim_char => @delimiter, :delim_data => "TRUE", :login => @api_login_id, :tran_key => @api_transaction_key, :relay_response => "FALSE")
141
+
142
+ if @cp_version.nil?
143
+ fields.merge!(:version => @version)
144
+ else
145
+ fields.merge!(:cp_version => @cp_version, :market_type => @market_type, :device_type => @device_type, :response_format => "1")
146
+ end
147
+ fields[:test_request] = boolean_to_value(@test_mode)
148
+ fields[:allow_partial_auth] = 'TRUE' if @allow_split_transaction
149
+ fields[:encap_char] = @encapsulation_character unless @encapsulation_character.nil?
150
+ fields.each do |k, v|
151
+ if @@boolean_fields.include?(k)
152
+ fields[k] = boolean_to_value(v)
153
+ elsif @@decimal_fields.include?(k)
154
+ fields[k] = decimal_to_value(v)
155
+ end
156
+ end
157
+ data = fields.collect do |key, val|
158
+ self.to_param(key, val)
159
+ end
160
+ custom_field_keys = @custom_fields.keys.collect(&:to_s).sort.collect(&:to_sym)
161
+ for key in custom_field_keys
162
+ data += [self.to_param(key, @custom_fields[key.to_sym], '')]
163
+ end
164
+ data.flatten!
165
+ request = Net::HTTP::Post.new(url.path)
166
+ request.content_type = 'application/x-www-form-urlencoded'
167
+ request.body = data.join("&")
168
+ connection = Net::HTTP.new(url.host, url.port)
169
+ connection.use_ssl = true
170
+ if @verify_ssl
171
+ connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
172
+ else
173
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
174
+ end
175
+ begin
176
+ @response = AuthorizeNet::AIM::Response.new((connection.start {|http| http.request(request)}), self)
177
+ rescue
178
+ @response = AuthorizeNet::AIM::Response.new($!, self)
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ end