tlconnor-activemerchant 1.20.4

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 (195) hide show
  1. data/CHANGELOG +805 -0
  2. data/CONTRIBUTORS +274 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +63 -0
  6. data/lib/active_merchant/billing.rb +9 -0
  7. data/lib/active_merchant/billing/avs_result.rb +98 -0
  8. data/lib/active_merchant/billing/base.rb +57 -0
  9. data/lib/active_merchant/billing/check.rb +68 -0
  10. data/lib/active_merchant/billing/credit_card.rb +264 -0
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  12. data/lib/active_merchant/billing/credit_card_methods.rb +129 -0
  13. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  14. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  15. data/lib/active_merchant/billing/gateway.rb +170 -0
  16. data/lib/active_merchant/billing/gateways.rb +18 -0
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +694 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +944 -0
  19. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +167 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +388 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  24. data/lib/active_merchant/billing/gateways/bogus.rb +142 -0
  25. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  26. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  27. data/lib/active_merchant/billing/gateways/braintree_blue.rb +308 -0
  28. data/lib/active_merchant/billing/gateways/braintree_orange.rb +21 -0
  29. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  30. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  31. data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
  32. data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
  33. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  34. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  35. data/lib/active_merchant/billing/gateways/elavon.rb +135 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +265 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  40. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  41. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  42. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  44. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  45. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  46. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  47. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  48. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  49. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  50. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  51. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  52. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +157 -0
  53. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  54. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  55. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  56. data/lib/active_merchant/billing/gateways/moneris.rb +239 -0
  57. data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
  58. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  59. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  60. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  61. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  62. data/lib/active_merchant/billing/gateways/ogone.rb +330 -0
  63. data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
  64. data/lib/active_merchant/billing/gateways/orbital.rb +344 -0
  65. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  66. data/lib/active_merchant/billing/gateways/pay_junction.rb +397 -0
  67. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  68. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow.rb +261 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +208 -0
  71. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  72. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  73. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  74. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  75. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  76. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  77. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  78. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +354 -0
  79. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  80. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  81. data/lib/active_merchant/billing/gateways/paypal_express.rb +229 -0
  82. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  83. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  84. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  85. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  86. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  87. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  88. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  89. data/lib/active_merchant/billing/gateways/quickpay.rb +298 -0
  90. data/lib/active_merchant/billing/gateways/realex.rb +315 -0
  91. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  92. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  93. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  94. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  95. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  96. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  97. data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
  98. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  99. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  100. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  102. data/lib/active_merchant/billing/gateways/skip_jack.rb +458 -0
  103. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  104. data/lib/active_merchant/billing/gateways/stripe.rb +244 -0
  105. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  106. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  107. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  108. data/lib/active_merchant/billing/gateways/usa_epay.rb +23 -0
  109. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1496 -0
  110. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
  111. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  112. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  113. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  114. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  115. data/lib/active_merchant/billing/integrations.rb +17 -0
  116. data/lib/active_merchant/billing/integrations/action_view_helper.rb +72 -0
  117. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  118. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  119. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  120. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  121. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  122. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  123. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  124. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  125. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  126. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  127. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  128. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  129. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  130. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  131. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  132. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  133. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  134. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  135. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  136. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  137. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  138. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
  139. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
  140. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  141. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  142. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  143. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  144. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  145. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  146. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  147. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  148. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  149. data/lib/active_merchant/billing/integrations/helper.rb +113 -0
  150. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  151. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  152. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  153. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  154. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  155. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  156. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  157. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  158. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  159. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  160. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  161. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  162. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  163. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
  164. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  165. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  166. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  167. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  168. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  169. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  170. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  171. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  172. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  173. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  174. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  175. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +127 -0
  176. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  177. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  178. data/lib/active_merchant/billing/integrations/two_checkout.rb +22 -0
  179. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  180. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  181. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  182. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  183. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  184. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  185. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  186. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  187. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  188. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  189. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  190. data/lib/active_merchant/billing/response.rb +32 -0
  191. data/lib/active_merchant/version.rb +3 -0
  192. data/lib/activemerchant.rb +1 -0
  193. data/lib/support/gateway_support.rb +58 -0
  194. data/lib/support/outbound_hosts.rb +25 -0
  195. metadata +411 -0
@@ -0,0 +1,17 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module Integrations
4
+
5
+ Dir[File.dirname(__FILE__) + '/integrations/*.rb'].each do |f|
6
+
7
+ # Get camelized class name
8
+ filename = File.basename(f, '.rb')
9
+ # Camelize the string to get the class name
10
+ gateway_class = filename.camelize.to_sym
11
+
12
+ # Register for autoloading
13
+ autoload gateway_class, f
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ require 'action_pack'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module ActionViewHelper
7
+ # This helper allows the usage of different payment integrations
8
+ # through a single form helper. Payment integrations are the
9
+ # type of service where the user is redirected to the secure
10
+ # site of the service, like Paypal or Chronopay.
11
+ #
12
+ # The helper creates a scope around a payment service helper
13
+ # which provides the specific mapping for that service.
14
+ #
15
+ # <% payment_service_for 1000, 'paypalemail@mystore.com',
16
+ # :amount => 50.00,
17
+ # :currency => 'CAD',
18
+ # :service => :paypal,
19
+ # :html => { :id => 'payment-form' } do |service| %>
20
+ #
21
+ # <% service.customer :first_name => 'Cody',
22
+ # :last_name => 'Fauser',
23
+ # :phone => '(555)555-5555',
24
+ # :email => 'cody@example.com' %>
25
+ #
26
+ # <% service.billing_address :city => 'Ottawa',
27
+ # :address1 => '21 Snowy Brook Lane',
28
+ # :address2 => 'Apt. 36',
29
+ # :state => 'ON',
30
+ # :country => 'CA',
31
+ # :zip => 'K1J1E5' %>
32
+ #
33
+ # <% service.invoice '#1000' %>
34
+ # <% service.shipping '0.00' %>
35
+ # <% service.tax '0.00' %>
36
+ #
37
+ # <% service.notify_url url_for(:only_path => false, :action => 'notify') %>
38
+ # <% service.return_url url_for(:only_path => false, :action => 'done') %>
39
+ # <% service.cancel_return_url 'http://mystore.com' %>
40
+ # <% end %>
41
+ #
42
+ def payment_service_for(order, account, options = {}, &proc)
43
+ raise ArgumentError, "Missing block" unless block_given?
44
+
45
+ integration_module = ActiveMerchant::Billing::Integrations.const_get(options.delete(:service).to_s.camelize)
46
+
47
+ result = []
48
+ result << form_tag(integration_module.service_url, options.delete(:html) || {})
49
+
50
+ service_class = integration_module.const_get('Helper')
51
+ service = service_class.new(order, account, options)
52
+
53
+ result << capture(service, &proc)
54
+
55
+ service.form_fields.each do |field, value|
56
+ result << hidden_field_tag(field, value)
57
+ end
58
+
59
+ service.raw_html_fields.each do |field, value|
60
+ result << "<input id=\"#{field}\" name=\"#{field}\" type=\"hidden\" value=\"#{value}\" />\n"
61
+ end
62
+
63
+ result << '</form>'
64
+ result= result.join("\n")
65
+
66
+ concat(result.respond_to?(:html_safe) ? result.html_safe : result)
67
+ nil
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,38 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module AuthorizeNetSim
5
+ autoload :Helper, 'active_merchant/billing/integrations/authorize_net_sim/helper.rb'
6
+ autoload :Notification, 'active_merchant/billing/integrations/authorize_net_sim/notification.rb'
7
+
8
+ # Overwrite this if you want to change the ANS test url
9
+ mattr_accessor :test_url
10
+ self.test_url = 'https://test.authorize.net/gateway/transact.dll'
11
+
12
+ # Overwrite this if you want to change the ANS production url
13
+ mattr_accessor :production_url
14
+ self.production_url = 'https://secure.authorize.net/gateway/transact.dll'
15
+
16
+ def self.service_url
17
+ mode = ActiveMerchant::Billing::Base.integration_mode
18
+ case mode
19
+ when :production
20
+ self.production_url
21
+ when :test
22
+ self.test_url
23
+ else
24
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
25
+ end
26
+ end
27
+
28
+ def self.notification(post)
29
+ Notification.new(post)
30
+ end
31
+
32
+ def self.return(query_string)
33
+ Return.new(query_string)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -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
@@ -0,0 +1,340 @@
1
+ require 'net/http'
2
+ module ActiveMerchant #:nodoc:
3
+ module Billing #:nodoc:
4
+ module Integrations #:nodoc:
5
+
6
+ # # Example:
7
+ # parser = AuthorizeNetSim::Notification.new(request.raw_post)
8
+ # passed = parser.complete?
9
+ #
10
+ # order = Order.find_by_order_number(parser.invoice_num)
11
+ #
12
+ # unless order
13
+ # @message = 'Error--unable to find your transaction! Please contact us directly.'
14
+ # return render :partial => 'authorize_net_sim_payment_response'
15
+ # end
16
+ #
17
+ # if order.total != parser.gross.to_f
18
+ # logger.error "Authorize.Net sim said they paid for #{parser.gross} and it should have been #{order.total}!"
19
+ # passed = false
20
+ # end
21
+ #
22
+ # # Theoretically, Authorize.net will *never* pass us the same transaction
23
+ # # ID twice, but we can double check that... by using
24
+ # # parser.transaction_id, and checking against previous orders' transaction
25
+ # # id's (which you can save when the order is completed)....
26
+ # unless parser.acknowledge MD5_HASH_SET_IN_AUTHORIZE_NET, AUTHORIZE_LOGIN
27
+ # passed = false
28
+ # logger.error "ALERT POSSIBLE FRAUD ATTEMPT either that or you haven't setup your md5 hash setting right in #{__FILE__}
29
+ # because a transaction came back from Authorize.Net with the wrong hash value--rejecting!"
30
+ # end
31
+ #
32
+ # unless parser.cavv_matches? and parser.avs_code_matches?
33
+ # logger.error 'Warning--non matching CC!' + params.inspect
34
+ # # Could fail them here, as well (recommended)...
35
+ # end
36
+ #
37
+ # if passed
38
+ # # Set up your session, and render something that will redirect them to
39
+ # # your site, most likely.
40
+ # else
41
+ # # Render failure or redirect them to your site where you will render failure
42
+ # end
43
+
44
+ module AuthorizeNetSim
45
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
46
+
47
+ def unescape(val) #:nodoc:
48
+ if val
49
+ CGI::unescape val
50
+ else
51
+ val
52
+ end
53
+ end
54
+
55
+ # Passes a hash of the address the user entered in at Authorize.Net
56
+ def billing_address
57
+ all = {}
58
+ [:fax, :city, :company, :last_name, :country, :zip, :first_name, :address, :email, :state].each do |key_out|
59
+ all[key_out] = unescape params['x_' + key_out.to_s]
60
+ end
61
+ all
62
+ end
63
+
64
+ def customer_id
65
+ unescape params['x_cust_id']
66
+ end
67
+
68
+ def auth_code
69
+ unescape params['x_auth_code']
70
+ end
71
+
72
+ def po_num
73
+ unescape params['x_po_num']
74
+ end
75
+
76
+ def ship_to_address
77
+ all = {}
78
+ [:city, :last_name, :first_name, :country, :zip, :address].each do |key_out|
79
+ all[key_out] = unescape params['x_ship_to_' + key_out.to_s]
80
+ end
81
+ all
82
+ end
83
+
84
+ # Tax amount we sent them.
85
+ def tax
86
+ unescape params['x_tax']
87
+ end
88
+
89
+ # Transaction type (probably going to be auth_capture, since that's
90
+ # all we set it as).
91
+ def transaction_type
92
+ unescape params['x_type']
93
+ end
94
+
95
+ # Payment method used--almost always CC (for credit card).
96
+ def method
97
+ unescape params['x_method']
98
+ end
99
+
100
+ # Ff our payment method is available. Almost always "true".
101
+ def method_available
102
+ params['x_method_available']
103
+ end
104
+
105
+ # Invoice num we passed in as invoice_num to them.
106
+ def invoice_num
107
+ item_id
108
+ end
109
+
110
+ # If you pass any values to authorize that aren't its expected, it
111
+ # will pass them back to you verbatim, returned by this method.
112
+ # custom values:
113
+ def all_custom_values_passed_in_and_now_passed_back_to_us
114
+ all = {}
115
+ params.each do |key, value|
116
+ if key[0..1] != 'x_'
117
+ all[key] = unescape value
118
+ end
119
+ end
120
+ all
121
+ end
122
+
123
+ def duty
124
+ unescape params['x_duty']
125
+ end
126
+
127
+ # Shipping we sent them.
128
+ def freight
129
+ unescape params['x_freight']
130
+ end
131
+ alias_method :shipping, :freight
132
+
133
+ def description
134
+ unescape params['x_description']
135
+ end
136
+
137
+ # Returns the response code as a symbol.
138
+ # {'1' => :approved, '2' => :declined, '3' => :error, '4' => :held_for_review}
139
+ def response_code_as_ruby_symbol
140
+ map = {'1' => :approved, '2' => :declined, '3' => :error, '4' => :held_for_review}
141
+ map[params['x_response_code']]
142
+ end
143
+
144
+ def response_reason_text
145
+ unescape params['x_response_reason_text']
146
+ end
147
+
148
+ # The response reason text's numeric id [equivalent--just a number]
149
+ def response_reason_code
150
+ unescape params['x_response_reason_code']
151
+ end
152
+
153
+ # 'used internally by their gateway'
154
+ def response_subcode
155
+ params['x_response_subcode']
156
+ end
157
+
158
+ # They pass back a tax_exempt value.
159
+ def tax_exempt
160
+ params['x_tax_exempt']
161
+ end
162
+
163
+ # avs [address verification] code
164
+ # A = Address (Street)
165
+ # matches, ZIP does not
166
+ # B = Address information
167
+ # not provided for AVS
168
+ # check
169
+ # E = AVS error
170
+ # G = Non-U.S. Card Issuing
171
+ # Bank
172
+ # N = No Match on Address
173
+ # (Street) or ZIP
174
+ # P = AVS not applicable for
175
+ # this transaction
176
+ # R = Retry – System
177
+ # unavailable or timed out
178
+ # S = Service not supported
179
+ # by issuer
180
+ # U = Address information is
181
+ # unavailable
182
+ # W = Nine digit ZIP
183
+ # matches, Address (Street)
184
+ # does not
185
+ # X = Address (Street) and
186
+ # nine digit ZIP match
187
+ # Y = Address (Street) and
188
+ # five digit ZIP match
189
+ # Z = Five digit ZIP matches
190
+ # Address (Street) does not
191
+ def avs_code
192
+ params['x_avs_code']
193
+ end
194
+
195
+ # Returns true if their address completely matched [Y or X, P from
196
+ # #avs_code, which mean 'add+zip match', 'address + 9-zip match', and
197
+ # not applicable, respectively].
198
+ def avs_code_matches?
199
+ return ['Y', 'X', 'P'].include? params['x_avs_code']
200
+ end
201
+
202
+ # cvv2 response
203
+ # M = Match
204
+ # N = No Match
205
+ # P = Not Processed
206
+ # S = Should have been
207
+ # present
208
+ # U = Issuer unable to
209
+ # process request
210
+ def cvv2_resp_code
211
+ params['x_cvv2_resp_code']
212
+ end
213
+
214
+ # check if #cvv2_resp_code == 'm' for Match. otherwise false
215
+ def cvv2_resp_code_matches?
216
+ return ['M'].include? cvv2_resp_code
217
+ end
218
+
219
+ # cavv_response--'cardholder authentication verification response code'--most likely not use for SIM
220
+ # Blank or not present =
221
+ # CAVV not validated
222
+ # 0 = CAVV not validated
223
+ # because erroneous data
224
+ # was submitted
225
+ # 1 = CAVV failed validation
226
+ # 2 = CAVV passed
227
+ # validation
228
+ # 3 = CAVV validation could
229
+ # not be performed; issuer
230
+ # attempt incomplete
231
+ # 4 = CAVV validation could
232
+ # not be performed; issuer
233
+ # system error
234
+ # 5 = Reserved for future
235
+ # use
236
+ # 6 = Reserved for future
237
+ # use
238
+ # 7 = CAVV attempt – failed
239
+ # validation – issuer
240
+ # available (U.S.-issued
241
+ # card/non-U.S acquirer)
242
+ # 8 = CAVV attempt –
243
+ # passed validation – issuer
244
+ # available (U.S.-issued
245
+ # card/non-U.S. acquirer)
246
+ # 9 = CAVV attempt – failed
247
+ # validation – issuer
248
+ def cavv_response
249
+ params['x_cavv_response']
250
+ end
251
+
252
+ # Check if #cavv_response == '', '2', '8' one of those [non failing]
253
+ # [blank means no validated, 2 is passed, 8 is passed issuer
254
+ # available]
255
+ def cavv_matches?
256
+ ['','2','8'].include? cavv_response
257
+ end
258
+
259
+ # Payment is complete -- returns true if x_response_code == '1'
260
+ def complete?
261
+ params["x_response_code"] == '1'
262
+ end
263
+
264
+ # Alias for invoice number--this is the only id they pass back to us
265
+ # that we passed to them, except customer id is also passed back.
266
+ def item_id
267
+ unescape params['x_invoice_num']
268
+ end
269
+
270
+ # They return this number to us [it's unique to Authorize.net].
271
+ def transaction_id
272
+ params['x_trans_id']
273
+ end
274
+
275
+ # When was this payment was received by the client. --unimplemented --
276
+ # always returns nil
277
+ def received_at
278
+ nil
279
+ end
280
+
281
+ # End-user's email
282
+ def payer_email
283
+ unescape params['x_email']
284
+ end
285
+
286
+ # They don't pass merchant email back to us -- unimplemented -- always
287
+ # returns nil
288
+ def receiver_email
289
+ nil
290
+ end
291
+
292
+ # md5 hash used internally
293
+ def security_key
294
+ params['x_MD5_Hash']
295
+ end
296
+
297
+ # The money amount we received in X.2 decimal. Returns a string
298
+ def gross
299
+ unescape params['x_amount']
300
+ end
301
+
302
+ # Was this a test transaction?
303
+ def test?
304
+ params['x_test_request'] == 'true'
305
+ end
306
+
307
+ # #method_available alias
308
+ def status
309
+ complete?
310
+ end
311
+
312
+ # Called to request back and check if it was a valid request.
313
+ # Authorize.net passes us back a hash that includes a hash of our
314
+ # 'unique' MD5 value that we set within their system.
315
+ #
316
+ # Example:
317
+ # acknowledge('my secret md5 hash that I set within Authorize.Net', 'authorize_login')
318
+ #
319
+ # Note this is somewhat unsafe unless you actually set that md5 hash
320
+ # to something (defaults to '' in their system).
321
+ def acknowledge(md5_hash_set_in_authorize_net, authorize_net_login_name)
322
+ Digest::MD5.hexdigest(md5_hash_set_in_authorize_net + authorize_net_login_name + params['x_trans_id'] + gross) == params['x_MD5_Hash'].downcase
323
+ end
324
+
325
+ private
326
+
327
+ # Take the posted data and move the relevant data into a hash.
328
+ def parse(post)
329
+ @raw = post
330
+ post.split('&').each do |line|
331
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
332
+ params[key] = value
333
+ end
334
+ end
335
+
336
+ end
337
+ end
338
+ end
339
+ end
340
+ end