yetanothernguyen-activemerchant 1.16.0 → 1.21.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 (86) hide show
  1. data/CHANGELOG +95 -0
  2. data/CONTRIBUTORS +29 -0
  3. data/lib/active_merchant/billing/credit_card.rb +105 -19
  4. data/lib/active_merchant/billing/credit_card_methods.rb +5 -1
  5. data/lib/active_merchant/billing/gateway.rb +1 -1
  6. data/lib/active_merchant/billing/gateways/authorize_net.rb +24 -2
  7. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +104 -18
  8. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +110 -4
  9. data/lib/active_merchant/billing/gateways/beanstream.rb +29 -1
  10. data/lib/active_merchant/billing/gateways/braintree_blue.rb +9 -4
  11. data/lib/active_merchant/billing/gateways/braintree_orange.rb +4 -0
  12. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  13. data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
  14. data/lib/active_merchant/billing/gateways/efsnet.rb +9 -9
  15. data/lib/active_merchant/billing/gateways/elavon.rb +2 -1
  16. data/lib/active_merchant/billing/gateways/epay.rb +12 -6
  17. data/lib/active_merchant/billing/gateways/eway_managed.rb +46 -12
  18. data/lib/active_merchant/billing/gateways/exact.rb +5 -0
  19. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +3 -3
  20. data/lib/active_merchant/billing/gateways/ipay88.rb +157 -0
  21. data/lib/active_merchant/billing/gateways/iridium.rb +3 -3
  22. data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
  23. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +1 -0
  24. data/lib/active_merchant/billing/gateways/moneris.rb +4 -0
  25. data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
  26. data/lib/active_merchant/billing/gateways/ogone.rb +94 -56
  27. data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
  28. data/lib/active_merchant/billing/gateways/orbital.rb +57 -34
  29. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -1
  30. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  31. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +2 -2
  32. data/lib/active_merchant/billing/gateways/payflow.rb +10 -2
  33. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +8 -5
  34. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
  35. data/lib/active_merchant/billing/gateways/paypal_express.rb +93 -40
  36. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
  37. data/lib/active_merchant/billing/gateways/qbms.rb +4 -0
  38. data/lib/active_merchant/billing/gateways/quickpay.rb +97 -22
  39. data/lib/active_merchant/billing/gateways/realex.rb +5 -1
  40. data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
  41. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +136 -49
  42. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +1 -1
  43. data/lib/active_merchant/billing/gateways/skip_jack.rb +7 -2
  44. data/lib/active_merchant/billing/gateways/stripe.rb +51 -19
  45. data/lib/active_merchant/billing/gateways/usa_epay.rb +13 -184
  46. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1496 -0
  47. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
  48. data/lib/active_merchant/billing/gateways/verifi.rb +2 -2
  49. data/lib/active_merchant/billing/gateways/viaklix.rb +1 -1
  50. data/lib/active_merchant/billing/gateways/worldpay.rb +1 -1
  51. data/lib/active_merchant/billing/integrations/action_view_helper.rb +6 -2
  52. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  53. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  54. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  55. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +4 -4
  56. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
  57. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
  58. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  59. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  60. data/lib/active_merchant/billing/integrations/helper.rb +19 -2
  61. data/lib/active_merchant/billing/integrations/ipay88/helper.rb +120 -0
  62. data/lib/active_merchant/billing/integrations/ipay88/return.rb +121 -0
  63. data/lib/active_merchant/billing/integrations/ipay88.rb +40 -0
  64. data/lib/active_merchant/billing/integrations/nochex.rb +1 -1
  65. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
  66. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  67. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  68. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +4 -4
  69. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +18 -2
  70. data/lib/active_merchant/billing/integrations/two_checkout.rb +1 -2
  71. data/lib/active_merchant/railtie.rb +7 -7
  72. data/lib/active_merchant/railtie.rb.orig +19 -0
  73. data/lib/active_merchant/version.rb +1 -1
  74. data/lib/active_merchant.rb +23 -10
  75. data/lib/active_merchant.rb.orig +78 -0
  76. metadata +147 -63
  77. data/lib/active_merchant/common/connection.rb +0 -177
  78. data/lib/active_merchant/common/country.rb +0 -328
  79. data/lib/active_merchant/common/error.rb +0 -26
  80. data/lib/active_merchant/common/post_data.rb +0 -24
  81. data/lib/active_merchant/common/posts_data.rb +0 -63
  82. data/lib/active_merchant/common/requires_parameters.rb +0 -16
  83. data/lib/active_merchant/common/utils.rb +0 -22
  84. data/lib/active_merchant/common/validateable.rb +0 -81
  85. data/lib/active_merchant/common.rb +0 -14
  86. data/lib/certs/cacert.pem +0 -7815
@@ -0,0 +1,206 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+
4
+ class UsaEpayTransactionGateway < Gateway
5
+ URL = 'https://www.usaepay.com/gate.php'
6
+
7
+ self.supported_cardtypes = [:visa, :master, :american_express]
8
+ self.supported_countries = ['US']
9
+ self.homepage_url = 'http://www.usaepay.com/'
10
+ self.display_name = 'USA ePay'
11
+
12
+ TRANSACTIONS = {
13
+ :authorization => 'authonly',
14
+ :purchase => 'sale',
15
+ :capture => 'capture',
16
+ :refund => 'refund',
17
+ :void => 'void'
18
+ }
19
+
20
+ def initialize(options = {})
21
+ requires!(options, :login)
22
+ @options = options
23
+ super
24
+ end
25
+
26
+ def authorize(money, credit_card, options = {})
27
+ post = {}
28
+
29
+ add_amount(post, money)
30
+ add_invoice(post, options)
31
+ add_credit_card(post, credit_card)
32
+ add_address(post, credit_card, options)
33
+ add_customer_data(post, options)
34
+
35
+ commit(:authorization, post)
36
+ end
37
+
38
+ def purchase(money, credit_card, options = {})
39
+ post = {}
40
+
41
+ add_amount(post, money)
42
+ add_invoice(post, options)
43
+ add_credit_card(post, credit_card)
44
+ add_address(post, credit_card, options)
45
+ add_customer_data(post, options)
46
+
47
+ commit(:purchase, post)
48
+ end
49
+
50
+ def capture(money, authorization, options = {})
51
+ post = { :refNum => authorization }
52
+
53
+ add_amount(post, money)
54
+ commit(:capture, post)
55
+ end
56
+
57
+ def refund(money, authorization, options = {})
58
+ post = { :refNum => authorization }
59
+
60
+ add_amount(post, money)
61
+ commit(:refund, post)
62
+ end
63
+
64
+ def void(authorization, options = {})
65
+ post = { :refNum => authorization }
66
+ commit(:void, post)
67
+ end
68
+
69
+ private
70
+
71
+ def add_amount(post, money)
72
+ post[:amount] = amount(money)
73
+ end
74
+
75
+ def expdate(credit_card)
76
+ year = format(credit_card.year, :two_digits)
77
+ month = format(credit_card.month, :two_digits)
78
+
79
+ "#{month}#{year}"
80
+ end
81
+
82
+ def add_customer_data(post, options)
83
+ address = options[:billing_address] || options[:address] || {}
84
+ post[:street] = address[:address1]
85
+ post[:zip] = address[:zip]
86
+
87
+ if options.has_key? :email
88
+ post[:custemail] = options[:email]
89
+ post[:custreceipt] = 'No'
90
+ end
91
+
92
+ if options.has_key? :customer
93
+ post[:custid] = options[:customer]
94
+ end
95
+
96
+ if options.has_key? :ip
97
+ post[:ip] = options[:ip]
98
+ end
99
+ end
100
+
101
+ def add_address(post, credit_card, options)
102
+ billing_address = options[:billing_address] || options[:address]
103
+
104
+ add_address_for_type(:billing, post, credit_card, billing_address) if billing_address
105
+ add_address_for_type(:shipping, post, credit_card, options[:shipping_address]) if options[:shipping_address]
106
+ end
107
+
108
+ def add_address_for_type(type, post, credit_card, address)
109
+ prefix = address_key_prefix(type)
110
+
111
+ post[address_key(prefix, 'fname')] = credit_card.first_name
112
+ post[address_key(prefix, 'lname')] = credit_card.last_name
113
+ post[address_key(prefix, 'company')] = address[:company] unless address[:company].blank?
114
+ post[address_key(prefix, 'street')] = address[:address1] unless address[:address1].blank?
115
+ post[address_key(prefix, 'street2')] = address[:address2] unless address[:address2].blank?
116
+ post[address_key(prefix, 'city')] = address[:city] unless address[:city].blank?
117
+ post[address_key(prefix, 'state')] = address[:state] unless address[:state].blank?
118
+ post[address_key(prefix, 'zip')] = address[:zip] unless address[:zip].blank?
119
+ post[address_key(prefix, 'country')] = address[:country] unless address[:country].blank?
120
+ post[address_key(prefix, 'phone')] = address[:phone] unless address[:phone].blank?
121
+ end
122
+
123
+ def address_key_prefix(type)
124
+ case type
125
+ when :shipping then 'ship'
126
+ when :billing then 'bill'
127
+ end
128
+ end
129
+
130
+ def address_key(prefix, key)
131
+ "#{prefix}#{key}".to_sym
132
+ end
133
+
134
+ def add_invoice(post, options)
135
+ post[:invoice] = options[:order_id]
136
+ end
137
+
138
+ def add_credit_card(post, credit_card)
139
+ post[:card] = credit_card.number
140
+ post[:cvv2] = credit_card.verification_value if credit_card.verification_value?
141
+ post[:expir] = expdate(credit_card)
142
+ post[:name] = credit_card.name
143
+ end
144
+
145
+ def parse(body)
146
+ fields = {}
147
+ for line in body.split('&')
148
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
149
+ fields[key] = CGI.unescape(value.to_s)
150
+ end
151
+
152
+ {
153
+ :status => fields['UMstatus'],
154
+ :auth_code => fields['UMauthCode'],
155
+ :ref_num => fields['UMrefNum'],
156
+ :batch => fields['UMbatch'],
157
+ :avs_result => fields['UMavsResult'],
158
+ :avs_result_code => fields['UMavsResultCode'],
159
+ :cvv2_result => fields['UMcvv2Result'],
160
+ :cvv2_result_code => fields['UMcvv2ResultCode'],
161
+ :vpas_result_code => fields['UMvpasResultCode'],
162
+ :result => fields['UMresult'],
163
+ :error => fields['UMerror'],
164
+ :error_code => fields['UMerrorcode'],
165
+ :acs_url => fields['UMacsurl'],
166
+ :payload => fields['UMpayload']
167
+ }.delete_if{|k, v| v.nil?}
168
+ end
169
+
170
+
171
+ def commit(action, parameters)
172
+ response = parse( ssl_post(URL, post_data(action, parameters)) )
173
+
174
+ Response.new(response[:status] == 'Approved', message_from(response), response,
175
+ :test => @options[:test] || test?,
176
+ :authorization => response[:ref_num],
177
+ :cvv_result => response[:cvv2_result_code],
178
+ :avs_result => {
179
+ :street_match => response[:avs_result_code].to_s[0,1],
180
+ :postal_match => response[:avs_result_code].to_s[1,1],
181
+ :code => response[:avs_result_code].to_s[2,1]
182
+ }
183
+ )
184
+ end
185
+
186
+ def message_from(response)
187
+ if response[:status] == "Approved"
188
+ return 'Success'
189
+ else
190
+ return 'Unspecified error' if response[:error].blank?
191
+ return response[:error]
192
+ end
193
+ end
194
+
195
+ def post_data(action, parameters = {})
196
+ parameters[:command] = TRANSACTIONS[action]
197
+ parameters[:key] = @options[:login]
198
+ parameters[:software] = 'Active Merchant'
199
+ parameters[:testmode] = @options[:test] ? 1 : 0
200
+
201
+ parameters.collect { |key, value| "UM#{key}=#{CGI.escape(value.to_s)}" }.join("&")
202
+ end
203
+ end
204
+ end
205
+ end
206
+
@@ -63,11 +63,11 @@ module ActiveMerchant #:nodoc:
63
63
  self.homepage_url = 'http://www.verifi.com/'
64
64
  self.display_name = 'Verifi'
65
65
 
66
- def initialize(options = {})
66
+ def initialize(options = {})
67
67
  requires!(options, :login, :password)
68
68
  @options = options
69
69
  super
70
- end
70
+ end
71
71
 
72
72
  def purchase(money, credit_card, options = {})
73
73
  sale_authorization_or_credit_template(:purchase, money, credit_card, options)
@@ -14,7 +14,7 @@ module ActiveMerchant #:nodoc:
14
14
 
15
15
  APPROVED = '0'
16
16
 
17
- self.supported_cardtypes = [:visa, :master, :american_express]
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
18
18
  self.supported_countries = ['US']
19
19
  self.display_name = 'ViaKLIX'
20
20
  self.homepage_url = 'http://viaklix.com'
@@ -27,7 +27,7 @@ module ActiveMerchant #:nodoc:
27
27
  def purchase(money, payment_method, options = {})
28
28
  response = MultiResponse.new
29
29
  response << authorize(money, payment_method, options)
30
- response << capture(money, response.authorization, :authorization_validated => true) if response.success?
30
+ response << capture(money, response.authorization, options.merge(:authorization_validated => true)) if response.success?
31
31
  response
32
32
  end
33
33
 
@@ -1,4 +1,4 @@
1
- require_library_or_gem 'action_pack'
1
+ require 'action_pack'
2
2
 
3
3
  module ActiveMerchant #:nodoc:
4
4
  module Billing #:nodoc:
@@ -57,7 +57,11 @@ module ActiveMerchant #:nodoc:
57
57
  service.form_fields.each do |field, value|
58
58
  result << hidden_field_tag(field, value)
59
59
  end
60
-
60
+
61
+ service.raw_html_fields.each do |field, value|
62
+ result << "<input id=\"#{field}\" name=\"#{field}\" type=\"hidden\" value=\"#{value}\" />\n"
63
+ end
64
+
61
65
  result << '</form>'
62
66
  result= result.join("\n")
63
67
 
@@ -0,0 +1,228 @@
1
+ require 'active_support/core_ext/float/rounding.rb' # Float#round(precision)
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module AuthorizeNetSim
7
+ # An example. Note the username as a parameter and transaction key you
8
+ # will want to use later. The amount that you pass in will be *rounded*,
9
+ # so preferably pass in X.2 decimal so that no rounding occurs. It is
10
+ # rounded because if it looks like 00.000 Authorize.Net fails the
11
+ # transaction as incorrectly formatted.
12
+ #
13
+ # payment_service_for('order_id', 'authorize_net_account', :service => :authorize_net_sim, :amount => 157.0) do |service|
14
+ #
15
+ # # You must call setup_hash and invoice
16
+ #
17
+ # service.setup_hash :transaction_key => '8CP6zJ7uD875J6tY',
18
+ # :order_timestamp => 1206836763
19
+ # service.customer_id 8
20
+ # service.customer :first_name => 'g',
21
+ # :last_name => 'g',
22
+ # :email => 'g@g.com',
23
+ # :phone => '3'
24
+ # service.billing_address :zip => 'g',
25
+ # :country => 'United States of America',
26
+ # :address => 'g'
27
+ #
28
+ # service.ship_to_address :first_name => 'g',
29
+ # :last_name => 'g',
30
+ # :city => '',
31
+ # :address => 'g',
32
+ # :address2 => '',
33
+ # :state => address.state,
34
+ # :country => 'United States of America',
35
+ # :zip => 'g'
36
+ #
37
+ # service.invoice "516428355" # your invoice number
38
+ # # The end-user is presented with the HTML produced by the notify_url.
39
+ # service.notify_url "http://t/authorize_net_sim/payment_received_notification_sub_step"
40
+ # service.payment_header 'My store name'
41
+ # service.add_line_item :name => 'item name', :quantity => 1, :unit_price => 0
42
+ # service.test_request 'true' # only if it's just a test
43
+ # service.shipping '25.0'
44
+ # # Tell it to display a "0" line item for shipping, with the price in
45
+ # # the name, otherwise it isn't shown at all, leaving the end user to
46
+ # # wonder why the total is different than the sum of the line items.
47
+ # service.add_shipping_as_line_item
48
+ # server.add_tax_as_line_item # same with tax
49
+ # # See the helper.rb file for various custom fields
50
+ # end
51
+
52
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
53
+ mapping :order, 'x_fp_sequence'
54
+ mapping :account, 'x_login'
55
+
56
+ mapping :customer, :first_name => 'x_first_name',
57
+ :last_name => 'x_last_name',
58
+ :email => 'x_email',
59
+ :phone => 'x_phone'
60
+
61
+ mapping :notify_url, 'x_relay_url'
62
+ mapping :return_url, '' # unused
63
+ mapping :cancel_return_url, '' # unused
64
+
65
+ # Custom fields for Authorize.net SIM.
66
+ # See http://www.Authorize.Net/support/SIM_guide.pdf for more descriptions.
67
+ mapping :fax, 'x_fax'
68
+ mapping :customer_id, 'x_cust_id'
69
+ mapping :description, 'x_description'
70
+ mapping :tax, 'x_tax'
71
+ mapping :shipping, 'x_freight'
72
+
73
+ # True or false, or 0 or 1 same effect [not required to send one,
74
+ # defaults to false].
75
+ mapping :test_request, 'x_test_request'
76
+
77
+ # This one is necessary for the notify url to be able to parse its
78
+ # information later! They also pass back customer id, if that's
79
+ # useful.
80
+ def invoice(number)
81
+ add_field 'x_invoice_num', number
82
+ end
83
+
84
+ # Set the billing address. Call like service.billing_address {:city =>
85
+ # 'provo, :state => 'UT'}...
86
+ def billing_address(options)
87
+ for setting in [:city, :state, :zip, :country, :po_num] do
88
+ add_field 'x_' + setting.to_s, options[setting]
89
+ end
90
+ raise 'must use address1 and address2' if options[:address]
91
+ add_field 'x_address', (options[:address1].to_s + ' ' + options[:address2].to_s).strip
92
+ end
93
+
94
+ # Adds a custom field which you submit to Authorize.Net. These fields
95
+ # are all passed back to you verbatim when it does its relay
96
+ # (callback) to you note that if you call it twice with the same name,
97
+ # this function only uses keeps the second value you called it with.
98
+ def add_custom_field(name, value)
99
+ add_field name, value
100
+ end
101
+
102
+ # Displays tax as a line item, so they can see it. Otherwise it isn't
103
+ # displayed.
104
+ def add_tax_as_line_item
105
+ raise unless @fields['x_tax']
106
+ add_line_item :name => 'Total Tax', :quantity => 1, :unit_price => @fields['x_tax'], :tax => 0, :line_title => 'Tax'
107
+ end
108
+
109
+ # Displays shipping as a line item, so they can see it. Otherwise it
110
+ # isn't displayed.
111
+ def add_shipping_as_line_item(extra_options = {})
112
+ raise 'must set shipping/freight before calling this' unless @fields['x_freight']
113
+ add_line_item extra_options.merge({:name => 'Shipping and Handling Cost', :quantity => 1, :unit_price => @fields['x_freight'], :line_title => 'Shipping'})
114
+ end
115
+
116
+ # Add ship_to_address in the same format as the normal address is
117
+ # added.
118
+ def ship_to_address(options)
119
+ for setting in [:first_name, :last_name, :company, :city, :state, :zip, :country] do
120
+ if options[setting] then
121
+ add_field 'x_ship_to_' + setting.to_s, options[setting]
122
+ end
123
+ end
124
+ raise 'must use :address1 and/or :address2' if options[:address]
125
+ add_field 'x_ship_to_address', (options[:address1].to_s + ' ' + options[:address2].to_s).strip
126
+ end
127
+
128
+ # These control the look of the SIM payment page. Note that you can
129
+ # include a CSS header in descriptors, etc.
130
+ mapping :color_link, 'x_color_link'
131
+ mapping :color_text, 'x_color_text'
132
+ mapping :logo_url, 'x_logo_url'
133
+ mapping :background_url, 'x_background_url' # background image url for the page
134
+ mapping :payment_header, 'x_header_html_payment_form'
135
+ mapping :payment_footer, 'x_footer_html_payment_form'
136
+
137
+ # For this to work you must have also passed in an email for the
138
+ # purchaser.
139
+ def yes_email_customer_from_authorizes_side
140
+ add_field 'x_email_customer', 'TRUE'
141
+ end
142
+
143
+ # Add a line item to Authorize.Net.
144
+ # Call line add_line_item {:name => 'orange', :unit_price => 30, :tax_value => 'Y', :quantity => 3, }
145
+ # Note you can't pass in a negative unit price, and you can add an
146
+ # optional :line_title => 'special name' if you don't want it to say
147
+ # 'Item 1' or what not, the default coded here.
148
+ # Cannot have a negative price, nor a name with "'s or $
149
+ # You can use the :line_title for the product name and then :name for description, if desired
150
+ def add_line_item(options)
151
+ raise 'needs name' unless options[:name]
152
+
153
+ if @line_item_count == 30
154
+ # Add a note that we are not showing at least one -- AN doesn't
155
+ # display more than 30 or so.
156
+ description_of_last = @raw_html_fields[-1][1]
157
+ # Pull off the second to last section, which is the description.
158
+ description_of_last =~ />([^>]*)<\|>[YN]$/
159
+ # Create a new description, which can't be too big, so truncate here.
160
+ @raw_html_fields[-1][1] = description_of_last.gsub($1, $1[0..200] + ' + more unshown items after this one.')
161
+ end
162
+
163
+ name = options[:name]
164
+ quantity = options[:quantity] || 1
165
+ line_title = options[:line_title] || ('Item ' + (@line_item_count + 1).to_s) # left most field
166
+ unit_price = options[:unit_price] || 0
167
+ unit_price = unit_price.to_f.round(2)
168
+ tax_value = options[:tax_value] || 'N'
169
+
170
+ # Sanitization, in case they include a reserved word here, following
171
+ # their guidelines; unfortunately, they require 'raw' fields here,
172
+ # not CGI escaped, using their own delimiters.
173
+ #
174
+ # Authorize.net ignores the second field (sanitized_short_name)
175
+ raise 'illegal char for line item <|>' if name.include? '<|>'
176
+ raise 'illegal char for line item "' if name.include? '"'
177
+ raise 'cannot pass in dollar sign' if unit_price.to_s.include? '$'
178
+ raise 'must have positive or 0 unit price' if unit_price.to_f < 0
179
+ # Using CGI::escape causes the output to be formated incorrectly in
180
+ # the HTML presented to the end-user's browser (e.g., spaces turn
181
+ # into +'s).
182
+ sanitized_short_name = name[0..30]
183
+ name = name[0..255]
184
+
185
+ add_raw_html_field "x_line_item", "#{line_title}<|>#{sanitized_short_name}<|>#{name}<|>#{quantity}<|>#{unit_price}<|>#{tax_value}"
186
+
187
+ @line_item_count += 1
188
+ end
189
+
190
+ # If you call this it will e-mail to this address a copy of a receipt
191
+ # after successful, from Authorize.Net.
192
+ def email_merchant_from_authorizes_side(to_this_email)
193
+ add_field 'x_email_merchant', to_this_email
194
+ end
195
+
196
+ # You MUST call this at some point for it to actually work. Options
197
+ # must include :transaction_key and :order_timestamp
198
+ def setup_hash(options)
199
+ raise unless options[:transaction_key]
200
+ raise unless options[:order_timestamp]
201
+ amount = @fields['x_amount']
202
+ data = "#{@fields['x_login']}^#{@fields['x_fp_sequence']}^#{options[:order_timestamp].to_i}^#{amount}^#{@fields['x_currency_code']}"
203
+ hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('md5'), options[:transaction_key], data)
204
+ add_field 'x_fp_hash', hmac
205
+ add_field 'x_fp_timestamp', options[:order_timestamp].to_i
206
+ end
207
+
208
+ # Note that you should call #invoice and #setup_hash as well, for the
209
+ # response_url to actually work.
210
+ def initialize(order, account, options = {})
211
+ super
212
+ raise 'missing parameter' unless order and account and options[:amount]
213
+ raise 'error -- amount with no digits!' unless options[:amount].to_s =~ /\d/
214
+ add_field('x_type', 'AUTH_CAPTURE') # the only one we deal with, for now. Not refunds or anything else, currently.
215
+ add_field 'x_show_form', 'PAYMENT_FORM'
216
+ add_field 'x_relay_response', 'TRUE'
217
+ add_field 'x_duplicate_window', '28800' # large default duplicate window.
218
+ add_field 'x_currency_code', currency_code
219
+ add_field 'x_version' , '3.1' # version from doc
220
+ add_field 'x_amount', options[:amount].to_f.round(2)
221
+ @line_item_count = 0
222
+ end
223
+
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end