activemerchant 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +226 -0
  3. data/CONTRIBUTERS +52 -0
  4. data/README +34 -24
  5. data/Rakefile +152 -0
  6. data/gem-public_cert.pem +20 -0
  7. data/init.rb +3 -0
  8. data/lib/active_merchant.rb +3 -1
  9. data/lib/active_merchant/billing/credit_card.rb +21 -17
  10. data/lib/active_merchant/billing/credit_card_methods.rb +17 -19
  11. data/lib/active_merchant/billing/gateway.rb +160 -44
  12. data/lib/active_merchant/billing/gateways.rb +2 -15
  13. data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -21
  14. data/lib/active_merchant/billing/gateways/bogus.rb +6 -6
  15. data/lib/active_merchant/billing/gateways/brain_tree.rb +191 -0
  16. data/lib/active_merchant/billing/gateways/card_stream.rb +207 -0
  17. data/lib/active_merchant/billing/gateways/cyber_source.rb +402 -0
  18. data/lib/active_merchant/billing/gateways/data_cash.rb +41 -97
  19. data/lib/active_merchant/billing/gateways/efsnet.rb +256 -0
  20. data/lib/active_merchant/billing/gateways/eway.rb +77 -29
  21. data/lib/active_merchant/billing/gateways/exact.rb +230 -0
  22. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -33
  23. data/lib/active_merchant/billing/gateways/moneris.rb +155 -125
  24. data/lib/active_merchant/billing/gateways/net_registry.rb +257 -0
  25. data/lib/active_merchant/billing/gateways/pay_junction.rb +407 -0
  26. data/lib/active_merchant/billing/gateways/payflow.rb +163 -25
  27. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +56 -38
  28. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +10 -1
  29. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +9 -0
  30. data/lib/active_merchant/billing/gateways/payflow_express.rb +36 -11
  31. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +6 -0
  32. data/lib/active_merchant/billing/gateways/payflow_uk.rb +7 -3
  33. data/lib/active_merchant/billing/gateways/payment_express.rb +261 -0
  34. data/lib/active_merchant/billing/gateways/paypal.rb +18 -4
  35. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +31 -15
  36. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +8 -0
  37. data/lib/active_merchant/billing/gateways/paypal_express.rb +33 -8
  38. data/lib/active_merchant/billing/gateways/plugnpay.rb +300 -0
  39. data/lib/active_merchant/billing/gateways/protx.rb +285 -0
  40. data/lib/active_merchant/billing/gateways/psigate.rb +13 -12
  41. data/lib/active_merchant/billing/gateways/psl_card.rb +297 -0
  42. data/lib/active_merchant/billing/gateways/quickpay.rb +197 -0
  43. data/lib/active_merchant/billing/gateways/realex.rb +212 -0
  44. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  45. data/lib/active_merchant/billing/gateways/trans_first.rb +136 -0
  46. data/lib/active_merchant/billing/gateways/trust_commerce.rb +43 -20
  47. data/lib/active_merchant/billing/gateways/usa_epay.rb +6 -5
  48. data/lib/active_merchant/billing/gateways/verifi.rb +235 -0
  49. data/lib/active_merchant/billing/gateways/viaklix.rb +171 -0
  50. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +0 -2
  51. data/lib/active_merchant/billing/integrations/helper.rb +8 -1
  52. data/lib/active_merchant/billing/integrations/nochex.rb +62 -1
  53. data/lib/active_merchant/billing/integrations/nochex/notification.rb +9 -16
  54. data/lib/active_merchant/billing/integrations/notification.rb +1 -1
  55. data/lib/active_merchant/billing/integrations/paypal/helper.rb +59 -46
  56. data/lib/active_merchant/billing/integrations/paypal/notification.rb +14 -47
  57. data/lib/active_merchant/lib/error.rb +4 -0
  58. data/lib/active_merchant/lib/post_data.rb +22 -0
  59. data/lib/active_merchant/lib/posts_data.rb +23 -5
  60. data/lib/active_merchant/lib/requires_parameters.rb +2 -2
  61. data/lib/active_merchant/lib/validateable.rb +1 -1
  62. data/lib/support/gateway_support.rb +45 -0
  63. data/lib/tasks/cia.rb +1 -1
  64. data/script/generate +14 -0
  65. data/script/generator/base.rb +45 -0
  66. data/script/generator/generator.rb +24 -0
  67. data/script/generator/generators/gateway/gateway_generator.rb +14 -0
  68. data/script/generator/generators/gateway/templates/gateway.rb +73 -0
  69. data/script/generator/generators/gateway/templates/gateway_test.rb +41 -0
  70. data/script/generator/generators/gateway/templates/remote_gateway_test.rb +56 -0
  71. data/script/generator/generators/integration/integration_generator.rb +25 -0
  72. data/script/generator/generators/integration/templates/helper.rb +34 -0
  73. data/script/generator/generators/integration/templates/helper_test.rb +54 -0
  74. data/script/generator/generators/integration/templates/integration.rb +18 -0
  75. data/script/generator/generators/integration/templates/module_test.rb +9 -0
  76. data/script/generator/generators/integration/templates/notification.rb +100 -0
  77. data/script/generator/generators/integration/templates/notification_test.rb +41 -0
  78. data/script/generator/manifest.rb +20 -0
  79. data/test/extra/binding_of_caller.rb +80 -0
  80. data/test/extra/breakpoint.rb +547 -0
  81. data/test/fixtures.yml +251 -0
  82. data/test/remote_tests/remote_authorize_net_test.rb +113 -0
  83. data/test/remote_tests/remote_brain_tree_test.rb +78 -0
  84. data/test/remote_tests/remote_card_stream_test.rb +160 -0
  85. data/test/remote_tests/remote_cyber_source_test.rb +130 -0
  86. data/test/remote_tests/remote_data_cash_test.rb +155 -0
  87. data/test/remote_tests/remote_efsnet_test.rb +93 -0
  88. data/test/remote_tests/remote_eway_test.rb +71 -0
  89. data/test/remote_tests/remote_exact_test.rb +59 -0
  90. data/test/remote_tests/remote_gestpay_integration_test.rb +37 -0
  91. data/test/remote_tests/remote_linkpoint_test.rb +144 -0
  92. data/test/remote_tests/remote_moneris_test.rb +110 -0
  93. data/test/remote_tests/remote_net_registry_test.rb +120 -0
  94. data/test/remote_tests/remote_pay_junction_test.rb +162 -0
  95. data/test/remote_tests/remote_payflow_express_test.rb +50 -0
  96. data/test/remote_tests/remote_payflow_test.rb +241 -0
  97. data/test/remote_tests/remote_payflow_uk_test.rb +172 -0
  98. data/test/remote_tests/remote_payment_express_test.rb +136 -0
  99. data/test/remote_tests/remote_paypal_express_test.rb +49 -0
  100. data/test/remote_tests/remote_paypal_integration_test.rb +14 -0
  101. data/test/remote_tests/remote_paypal_test.rb +163 -0
  102. data/test/remote_tests/remote_plugnpay_test.rb +70 -0
  103. data/test/remote_tests/remote_protx_test.rb +184 -0
  104. data/test/remote_tests/remote_psigate_test.rb +87 -0
  105. data/test/remote_tests/remote_psl_card_test.rb +105 -0
  106. data/test/remote_tests/remote_quickpay_test.rb +182 -0
  107. data/test/remote_tests/remote_realex_test.rb +227 -0
  108. data/test/remote_tests/remote_secure_pay_test.rb +36 -0
  109. data/test/remote_tests/remote_trans_first_test.rb +37 -0
  110. data/test/remote_tests/remote_trust_commerce_test.rb +136 -0
  111. data/test/remote_tests/remote_usa_epay_test.rb +57 -0
  112. data/test/remote_tests/remote_verifi_test.rb +107 -0
  113. data/test/remote_tests/remote_viaklix_test.rb +53 -0
  114. data/test/test_helper.rb +132 -0
  115. data/test/unit/base_test.rb +61 -0
  116. data/test/unit/country_code_test.rb +33 -0
  117. data/test/unit/country_test.rb +64 -0
  118. data/test/unit/credit_card_formatting_test.rb +24 -0
  119. data/test/unit/credit_card_methods_test.rb +37 -0
  120. data/test/unit/credit_card_test.rb +365 -0
  121. data/test/unit/gateways/authorize_net_test.rb +140 -0
  122. data/test/unit/gateways/bogus_test.rb +43 -0
  123. data/test/unit/gateways/brain_tree_test.rb +77 -0
  124. data/test/unit/gateways/card_stream_test.rb +37 -0
  125. data/test/unit/gateways/cyber_source_test.rb +151 -0
  126. data/test/unit/gateways/data_cash_test.rb +23 -0
  127. data/test/unit/gateways/efsnet_test.rb +70 -0
  128. data/test/unit/gateways/eway_test.rb +105 -0
  129. data/test/unit/gateways/exact_test.rb +118 -0
  130. data/test/unit/gateways/gateway_test.rb +24 -0
  131. data/test/unit/gateways/linkpoint_test.rb +165 -0
  132. data/test/unit/gateways/moneris_test.rb +167 -0
  133. data/test/unit/gateways/net_registry_test.rb +478 -0
  134. data/test/unit/gateways/pay_junction_test.rb +61 -0
  135. data/test/unit/gateways/payflow_express_test.rb +165 -0
  136. data/test/unit/gateways/payflow_express_uk_test.rb +14 -0
  137. data/test/unit/gateways/payflow_test.rb +230 -0
  138. data/test/unit/gateways/payflow_uk_test.rb +68 -0
  139. data/test/unit/gateways/payment_express_test.rb +215 -0
  140. data/test/unit/gateways/paypal_express_test.rb +222 -0
  141. data/test/unit/gateways/paypal_test.rb +241 -0
  142. data/test/unit/gateways/plugnpay_test.rb +79 -0
  143. data/test/unit/gateways/protx_test.rb +110 -0
  144. data/test/unit/gateways/psigate_test.rb +110 -0
  145. data/test/unit/gateways/psl_card_test.rb +51 -0
  146. data/test/unit/gateways/quickpay_test.rb +125 -0
  147. data/test/unit/gateways/realex_test.rb +150 -0
  148. data/test/unit/gateways/secure_pay_test.rb +78 -0
  149. data/test/unit/gateways/trans_first_test.rb +125 -0
  150. data/test/unit/gateways/trust_commerce_test.rb +57 -0
  151. data/test/unit/gateways/usa_epay_test.rb +117 -0
  152. data/test/unit/gateways/verifi_test.rb +91 -0
  153. data/test/unit/gateways/viaklix_test.rb +72 -0
  154. data/test/unit/integrations/action_view_helper_test.rb +54 -0
  155. data/test/unit/integrations/bogus_module_test.rb +16 -0
  156. data/test/unit/integrations/chronopay_module_test.rb +9 -0
  157. data/test/unit/integrations/gestpay_module_test.rb +10 -0
  158. data/test/unit/integrations/helpers/bogus_helper_test.rb +28 -0
  159. data/test/unit/integrations/helpers/chronopay_helper_test.rb +67 -0
  160. data/test/unit/integrations/helpers/gestpay_helper_test.rb +100 -0
  161. data/test/unit/integrations/helpers/nochex_helper_test.rb +53 -0
  162. data/test/unit/integrations/helpers/paypal_helper_test.rb +162 -0
  163. data/test/unit/integrations/helpers/two_checkout_helper_test.rb +92 -0
  164. data/test/unit/integrations/nochex_module_test.rb +9 -0
  165. data/test/unit/integrations/notifications/chronopay_notification_test.rb +66 -0
  166. data/test/unit/integrations/notifications/gestpay_notification_test.rb +60 -0
  167. data/test/unit/integrations/notifications/nochex_notification_test.rb +51 -0
  168. data/test/unit/integrations/notifications/notification_test.rb +41 -0
  169. data/test/unit/integrations/notifications/paypal_notification_test.rb +85 -0
  170. data/test/unit/integrations/notifications/two_checkout_notification_test.rb +55 -0
  171. data/test/unit/integrations/paypal_module_test.rb +24 -0
  172. data/test/unit/integrations/two_checkout_module_test.rb +9 -0
  173. data/test/unit/post_data_test.rb +55 -0
  174. data/test/unit/response_test.rb +14 -0
  175. data/test/unit/validateable_test.rb +56 -0
  176. metadata +160 -7
  177. metadata.gz.sig +0 -0
  178. data/lib/active_merchant/billing/gateways/payflow/f73e89fd.0 +0 -17
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApjb2R5
3
+ ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
4
+ b20wHhcNMDcwMjIyMTcyMTI3WhcNMDgwMjIyMTcyMTI3WjBBMRMwEQYDVQQDDApj
5
+ b2R5ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
6
+ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6T4Iqt5iWvAlU
7
+ iXI6L8UO0URQhIC65X/gJ9hL/x4lwSl/ckVm/R/bPrJGmifT+YooFv824N3y/TIX
8
+ 25o/lZtRj1TUZJK4OCb0aVzosQVxBHSe6rLmxO8cItNTMOM9wn3thaITFrTa1DOQ
9
+ O3wqEjvW2L6VMozVfK1MfjL9IGgy0rCnl+2g4Gh4jDDpkLfnMG5CWI6cTCf3C1ye
10
+ ytOpWgi0XpOEy8nQWcFmt/KCQ/kFfzBo4QxqJi54b80842EyvzWT9OB7Oew/CXZG
11
+ F2yIHtiYxonz6N09vvSzq4CvEuisoUFLKZnktndxMEBKwJU3XeSHAbuS7ix40OKO
12
+ WKuI54fHAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
13
+ BBR9QQpefI3oDCAxiqJW/3Gg6jI6qjANBgkqhkiG9w0BAQUFAAOCAQEAs0lX26O+
14
+ HpyMp7WL+SgZuM8k76AjfOHuKajl2GEn3S8pWYGpsa0xu07HtehJhKLiavrfUYeE
15
+ qlFtyYMUyOh6/1S2vfkH6VqjX7mWjoi7XKHW/99fkMS40B5SbN+ypAUst+6c5R84
16
+ w390mjtLHpdDE6WQYhS6bFvBN53vK6jG3DLyCJc0K9uMQ7gdHWoxq7RnG92ncQpT
17
+ ThpRA+fky5Xt2Q63YJDnJpkYAz79QIama1enSnd4jslKzSl89JS2luq/zioPe/Us
18
+ hbyalWR1+HrhgPoSPq7nk+s2FQUBJ9UZFK1lgMzho/4fZgzJwbu+cO8SNuaLS/bj
19
+ hPaSTyVU0yCSnw==
20
+ -----END CERTIFICATE-----
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'active_merchant'
2
+ require 'active_merchant/billing/integrations/action_view_helper'
3
+ ActionView::Base.send(:include, ActiveMerchant::Billing::Integrations::ActionViewHelper)
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005 Tobias Luetke
2
+ # Copyright (c) 2005-2007 Tobias Luetke
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -40,8 +40,10 @@ end
40
40
 
41
41
  require 'cgi'
42
42
 
43
+ require 'active_merchant/lib/error'
43
44
  require 'active_merchant/lib/validateable'
44
45
  require 'active_merchant/lib/posts_data'
46
+ require 'active_merchant/lib/post_data'
45
47
  require 'active_merchant/lib/requires_parameters'
46
48
 
47
49
  # Require the country class
@@ -3,10 +3,11 @@ require 'date'
3
3
 
4
4
  module ActiveMerchant #:nodoc:
5
5
  module Billing #:nodoc:
6
- # This credit card object can be used as a stand alone object. It acts just like a active record object
6
+ # This credit card object can be used as a stand alone object. It acts just like an ActiveRecord object
7
7
  # but doesn't support the .save method as its not backed by a database.
8
8
  class CreditCard
9
9
  include CreditCardMethods
10
+ include Validateable
10
11
 
11
12
  cattr_accessor :require_verification_value
12
13
  self.require_verification_value = false
@@ -15,8 +16,6 @@ module ActiveMerchant #:nodoc:
15
16
  require_verification_value
16
17
  end
17
18
 
18
- include Validateable
19
-
20
19
  class ExpiryDate #:nodoc:
21
20
  attr_reader :month, :year
22
21
  def initialize(month, year)
@@ -60,30 +59,35 @@ module ActiveMerchant #:nodoc:
60
59
  end
61
60
 
62
61
  def validate
63
- errors.add "year", "expired" if expired?
64
-
65
- errors.add "first_name", "cannot be empty" if @first_name.blank?
66
- errors.add "last_name", "cannot be empty" if @last_name.blank?
67
- errors.add "month", "cannot be empty" unless valid_month?(@month)
68
- errors.add "year", "cannot be empty" unless valid_expiry_year?(@year)
62
+ errors.add :year, "expired" if expired?
63
+
64
+ errors.add :first_name, "cannot be empty" if @first_name.blank?
65
+ errors.add :last_name, "cannot be empty" if @last_name.blank?
66
+ errors.add :month, "is not a valid month" unless valid_month?(@month)
67
+ errors.add :year, "is not a valid year" unless valid_expiry_year?(@year)
69
68
 
70
69
  # Bogus card is pretty much for testing purposes. Lets just skip these extra tests if its used
71
70
 
72
71
  return if type == 'bogus'
73
72
 
74
- errors.add "number", "is not a valid credit card number" unless CreditCard.valid_number?(number)
75
- errors.add "type", "is invalid" unless CreditCard.card_companies.keys.include?(type)
76
- errors.add "type", "is not the correct card type" unless CreditCard.type?(number) == type
77
-
73
+ errors.add :number, "is not a valid credit card number" unless CreditCard.valid_number?(number)
74
+ errors.add :type, "is required" if type.blank?
75
+ errors.add :type, "is invalid" unless CreditCard.card_companies.keys.include?(type)
76
+
77
+ unless errors.on(:number) || errors.on(:type)
78
+ CreditCard.type?(number) == type or
79
+ errors.add :type, "is not the correct card type"
80
+ end
81
+
78
82
  if CreditCard.requires_verification_value?
79
- errors.add "verification_value", "is required" unless verification_value?
83
+ errors.add :verification_value, "is required" unless verification_value?
80
84
  end
81
85
 
82
86
  if [ 'switch', 'solo' ].include?(type)
83
87
  unless valid_month?(@start_month) && valid_start_year?(@start_year) || valid_issue_number?(@issue_number)
84
- errors.add "start_month", "is invalid" unless valid_month?(@start_month)
85
- errors.add "start_year", "is invalid" unless valid_start_year?(@start_year)
86
- errors.add "issue_number", "cannot be empty" unless valid_issue_number?(@issue_number)
88
+ errors.add :start_month, "is invalid" unless valid_month?(@start_month)
89
+ errors.add :start_year, "is invalid" unless valid_start_year?(@start_year)
90
+ errors.add :issue_number, "cannot be empty" unless valid_issue_number?(@issue_number)
87
91
  end
88
92
  end
89
93
  end
@@ -42,38 +42,36 @@ module ActiveMerchant #:nodoc:
42
42
  end
43
43
 
44
44
  # Regular expressions for the known card companies
45
- # == Known card types
46
- # Card Type Prefix Length
47
- # --------------------------------------------------------------------------
48
- # master 51-55 16
49
- # visa 4 13, 16
50
- # american_express 34, 37 15
51
- # diners_club 300-305, 36, 38 14
52
- # discover 6011 16
53
- # jcb 3 16
54
- # jcb 2131, 1800 15
55
- # switch various 16,18,19
56
- # solo 63, 6767 16,18,19
45
+ # http://en.wikipedia.org/wiki/Credit_card_number
46
+ # http://www.barclaycardbusiness.co.uk/information_zone/processing/bin_rules.html
57
47
  def card_companies
58
48
  {
59
49
  'visa' => /^4\d{12}(\d{3})?$/,
60
- 'master' => /^5[1-5]\d{14}$/,
50
+ 'master' => /^(5[1-5]\d{4}|677189)\d{10}$/,
61
51
  'discover' => /^6011\d{12}$/,
62
52
  'american_express' => /^3[47]\d{13}$/,
63
53
  'diners_club' => /^3(0[0-5]|[68]\d)\d{11}$/,
64
- 'jcb' => /^(3\d{4}|2131|1800)\d{11}$/,
65
- 'switch' => [/^49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\d{10}(\d{2,3})?$/, /^564182\d{10}(\d{2,3})?$/, /^6(3(33[0-4][0-9])|759[0-9]{2})\d{10}(\d{2,3})?$/],
66
- 'solo' => /^6(3(34[5-9][0-9])|767[0-9]{2})\d{10}(\d{2,3})?$/
54
+ 'jcb' => /^3528\d{12}$/,
55
+ 'switch' => /^6759\d{12}(\d{2,3})?$/,
56
+ 'solo' => /^6767\d{12}(\d{2,3})?$/,
57
+ 'dankort' => /^5019\d{12}$/,
58
+ 'maestro' => /^(5[06-8]|6\d)\d{14}$/,
59
+ 'forbrugsforeningen' => /^600722\d{10}$/,
60
+ 'laser' => /^(6304[89]\d{11}(\d{2,3})?|670695\d{12})$/
67
61
  }
68
62
  end
69
-
63
+
70
64
  # Returns a string containing the type of card from the list of known information below.
65
+ # Need to check the cards in a particular order, as there is some overlap of the allowable ranges
66
+ #
71
67
  def type?(number)
72
68
  return 'visa' if ActiveMerchant::Billing::Base.gateway_mode == :test and ['1','2','3','success','failure','error'].include?(number.to_s)
73
69
 
74
- card_companies.each do |company, patterns|
75
- return company if [patterns].flatten.any? { |pattern| number =~ pattern }
70
+ card_companies.reject{ |c,p| c == 'maestro' }.each do |company, pattern|
71
+ return company.dup if number =~ pattern
76
72
  end
73
+
74
+ return 'maestro' if number =~ card_companies['maestro']
77
75
 
78
76
  return nil
79
77
  end
@@ -1,58 +1,140 @@
1
1
  require 'net/http'
2
2
  require 'net/https'
3
+ require 'digest/md5'
3
4
  require 'active_merchant/billing/response'
4
5
 
5
6
  module ActiveMerchant #:nodoc:
6
7
  module Billing #:nodoc:
7
- # The Gateway class is the base class for all ActiveMerchant gateway
8
- # implementations. The list of gateway functions that concrete
9
- # gateway classes can and should implement include the following:
10
- #
11
- # === Core operations supported by most gateways
12
- # * purchase(money, creditcard, options = {})
13
- # * authorize(money, creditcard, options = {})
14
- # * capture(money, authorization, options = {})
15
- # * void(identification, options = {})
16
- # * credit(money, identification, options = {})
8
+ #
9
+ # == Description
10
+ # The Gateway class is the base class for all ActiveMerchant gateway implementations.
11
+ #
12
+ # The list of gateway functions that concrete gateway classes can and should implement include
13
+ # the following:
14
+ #
15
+ # * <tt>purchase(money, creditcard, options = {})</tt>
16
+ # * <tt>authorize(money, creditcard, options = {})</tt>
17
+ # * <tt>capture(money, authorization, options = {})</tt>
18
+ # * <tt>void(identification, options = {})</tt>
19
+ # * <tt>credit(money, identification, options = {})</tt>
20
+ #
21
+ # == Setting Up Your Gateway
22
+ # Aside from the obvious authorization parameters (login and password), you can set up your
23
+ # gateway using numerous options. Be sure to reference your gateway of choice's documentation
24
+ # before overriding it's default values that may be defined.
25
+ #
26
+ # * <tt>Gateway.default_currency</tt>: sets the default currency if none is provided. See
27
+ # http://en.wikipedia.org/wiki/ISO_4217#Active_codes for active currency codes.
28
+ #
29
+ # * <tt>Gateway.supported_countries</tt>: sets the countries of _merchants_ the gateway supports.
30
+ #
31
+ # * <tt>Gateway.supported_cardtypes</tt>: sets the card types supported by the gateway.
32
+ #
33
+ # * <tt>Gateway.homepage_url</tt>: sets the URL at which the gateway may be found.
34
+ #
35
+ # * <tt>Gateway.display_name</tt>: sets the name of the gateway for display purposes, such as generating documentation.
36
+ #
37
+ # * <tt>Gateway.application_id</tt>: This is the application making calls to the gateway. This
38
+ # is useful for things like the Paypal build notation (BN) id fields.
39
+ #
40
+ # * <tt>Gateway.money_format</tt>: this attribute may be set to <tt>:dollars</tt> or
41
+ # <tt>:cents</tt>. Use this to set the expected money format you'll be inputting.
42
+ #
43
+ #
44
+ # Gateway.money_format = :dollars # => 12.50
45
+ # Gateway.money_format = :cents # => 1250
46
+ #
47
+ #
48
+ # == Testing Your Code
49
+ # There are two kinds of tests performed with your code: local and remote.
50
+ #
51
+ # === Local Tests
52
+ # Before running any remote tests, it's best to ensure that your code covers the basics
53
+ # locally. Local tests run on your own machine and will run faster than remote tests.
54
+ #
55
+ # To run a local test, first ensure that your gateway is in test mode:
56
+ #
57
+ # ActiveMerchant::Base.mode = :test
58
+ #
59
+ # (See ActiveMerchant::Base for more details.) This is often best set in your test's +setup+
60
+ # or +teardown+ methods, if you are using Test::Unit.
61
+ #
62
+ # The next step is to use one of three test credit card numbers:
63
+ #
64
+ # <tt>1</tt>:: Result will be successful
65
+ # <tt>2</tt>:: Result will be a failure
66
+ # <tt>3</tt>:: Result will raise a miscellaneous error
67
+ #
68
+ # For examples of test requests, please see your gateway of interest's unit test code.
69
+ #
70
+ # === Remote Tests
71
+ # Remote tests aren't mandatory, but it's not a bad idea to write them to ensure everything
72
+ # works as expected. You'll first need authorization parameters from the gateway you'll be
73
+ # working with. Once you have these values you'll be able to use ActiveMerchant to run test
74
+ # requests.
75
+ #
76
+ # As with local tests, first ensure that you are in test mode:
77
+ #
78
+ # ActiveMerchant::Base.mode = :test
79
+ #
80
+ # (See ActiveMerchant::Base for more details.)
81
+ #
82
+ # Test requests may then be made using appropriate parameters provided by your gateway of
83
+ # choice. For instance, the Moneris gateway provides a test MasterCard and Visa number that
84
+ # one may use to process test purchases and authorization requests.
85
+ #
86
+ # Given that these remote tests will take longer to run than local tests, it is recommended
87
+ # that you comment them out, or disable them when not required.
17
88
  class Gateway
18
89
  include PostsData
19
90
  include RequiresParameters
20
91
  include CreditCardFormatting
21
92
 
93
+ ## Constants
94
+
95
+ DEBIT_CARDS = [ :switch, :solo ]
96
+
97
+ ## Attributes
98
+
22
99
  # The format of the amounts used by the gateway
23
100
  # :dollars => '12.50'
24
101
  # :cents => '1250'
25
102
  class_inheritable_accessor :money_format
26
103
  self.money_format = :dollars
27
104
 
28
- # Return the matching gateway for the provider
29
- # * <tt>bogus</tt>: BogusGateway - Does nothing ( for testing)
30
- # * <tt>moneris</tt>: MonerisGateway
31
- # * <tt>authorize_net</tt>: AuthorizeNetGateway
32
- # * <tt>trust_commerce</tt>: TrustCommerceGateway
33
- #
34
- # ActiveMerchant::Base.gateway('moneris').new
35
- def self.gateway(name)
36
- ActiveMerchant::Billing.const_get("#{name.to_s.downcase}_gateway".camelize)
37
- end
38
-
39
- # Does this gateway support credit cards of the passed type?
40
- def self.supports?(type)
41
- supported_cardtypes.include?(type.intern)
42
- end
43
-
44
- # Get a list of supported credit card types for this gateway
45
- def self.supported_cardtypes
46
- []
47
- end
48
-
105
+ # The default currency for the transactions if no currency is provided
106
+ class_inheritable_accessor :default_currency
107
+
108
+ # The countries of merchants the gateway supports
109
+ class_inheritable_accessor :supported_countries
110
+ self.supported_countries = []
111
+
112
+ # The supported card types for the gateway
113
+ class_inheritable_accessor :supported_cardtypes
114
+ self.supported_cardtypes = []
115
+
116
+ class_inheritable_accessor :homepage_url
117
+ class_inheritable_accessor :display_name
118
+
119
+ # The application making the calls to the gateway
120
+ # Useful for things like the PayPal build notation (BN) id fields
121
+ class_inheritable_accessor :application_id
122
+ self.application_id = 'ActiveMerchant'
123
+
49
124
  attr_reader :options
50
- # Initialize a new gateway
125
+
126
+ # Use this method to check if your gateway of interest supports a credit card of some type
127
+ def self.supports?(card_type)
128
+ supported_cardtypes.include?(card_type.to_sym)
129
+ end
130
+
131
+ ## Instance Methods
132
+
133
+ # Initialize a new gateway.
51
134
  #
52
- # See the documentation for the gateway you will be using to make sure there
53
- # are no other required options
54
- def initialize(options = {})
55
- @ssl_strict = options[:ssl_strict] || false
135
+ # See the documentation for the gateway you will be using to make sure there are no other
136
+ # required options.
137
+ def initialize(options = {})
56
138
  end
57
139
 
58
140
  # Are we running in test mode?
@@ -60,15 +142,27 @@ module ActiveMerchant #:nodoc:
60
142
  Base.gateway_mode == :test
61
143
  end
62
144
 
63
- private
145
+ private # :nodoc: all
146
+
64
147
  def name
65
148
  self.class.name.scan(/\:\:(\w+)Gateway/).flatten.first
66
149
  end
67
150
 
68
- def test_result_from_cc_number(number)
151
+ # This is used to check if our credit card number implies that we are seeking a test
152
+ # Response. Of course, this returns false if we are not in test mode.
153
+ #
154
+ # Recognized values:
155
+ # <tt>1</tt>:: Result will be successful
156
+ # <tt>2</tt>:: Result will be a failure
157
+ # <tt>3</tt>:: Result will raise a miscellaneous error
158
+ #
159
+ # All other values will not be recognized.
160
+ #--
161
+ # TODO Refactor this method. It's kind of on the ugly side of things.
162
+ def test_result_from_cc_number(card_number)
69
163
  return false unless test?
70
164
 
71
- case number.to_s
165
+ case card_number.to_s
72
166
  when '1', 'success'
73
167
  Response.new(true, 'Successful test mode response', {:receiptid => '#0001'}, :test => true, :authorization => '5555')
74
168
  when '2', 'failure'
@@ -80,7 +174,9 @@ module ActiveMerchant #:nodoc:
80
174
  end
81
175
  end
82
176
 
83
- # Return a string with the amount in the appropriate format
177
+ # Return a String with the amount in the appropriate format
178
+ #--
179
+ # TODO Refactor this method. It's a tad on the ugly side.
84
180
  def amount(money)
85
181
  return nil if money.nil?
86
182
  cents = money.respond_to?(:cents) ? money.cents : money
@@ -89,13 +185,33 @@ module ActiveMerchant #:nodoc:
89
185
  raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.'
90
186
  end
91
187
 
92
- case self.money_format
93
- when :cents
188
+ if self.money_format == :cents
94
189
  cents.to_s
95
190
  else
96
- sprintf("%.2f", cents.to_f/100)
191
+ sprintf("%.2f", cents.to_f / 100)
97
192
  end
98
- end
193
+ end
194
+
195
+ # Ascertains the currency to be used on the money supplied.
196
+ def currency(money)
197
+ money.respond_to?(:currency) ? money.currency : self.default_currency
198
+ end
199
+
200
+ def requires_start_date_or_issue_number?(credit_card)
201
+ return false if credit_card.type.blank?
202
+ DEBIT_CARDS.include?(credit_card.type.to_sym)
203
+ end
204
+
205
+ def generate_unique_id
206
+ md5 = Digest::MD5.new
207
+ now = Time.now
208
+ md5 << now.to_s
209
+ md5 << String(now.usec)
210
+ md5 << String(rand(0))
211
+ md5 << String($$)
212
+ md5 << self.class.name
213
+ md5.hexdigest
214
+ end
99
215
  end
100
216
  end
101
217
  end
@@ -1,16 +1,3 @@
1
1
  require 'active_merchant/billing/gateway'
2
- require 'active_merchant/billing/gateways/bogus'
3
- require 'active_merchant/billing/gateways/psigate'
4
- require 'active_merchant/billing/gateways/authorize_net'
5
- require 'active_merchant/billing/gateways/moneris'
6
- require 'active_merchant/billing/gateways/trust_commerce'
7
- require 'active_merchant/billing/gateways/linkpoint'
8
- require 'active_merchant/billing/gateways/paypal'
9
- require 'active_merchant/billing/gateways/paypal_express'
10
- require 'active_merchant/billing/gateways/eway'
11
- require 'active_merchant/billing/gateways/usa_epay'
12
- require 'active_merchant/billing/gateways/payflow'
13
- require 'active_merchant/billing/gateways/payflow_express'
14
- require 'active_merchant/billing/gateways/payflow_uk'
15
- require 'active_merchant/billing/gateways/payflow_express_uk'
16
- require 'active_merchant/billing/gateways/data_cash'
2
+
3
+ Dir[File.dirname(__FILE__) + '/gateways/*.rb'].each{|g| require g}
@@ -3,9 +3,12 @@ module ActiveMerchant #:nodoc:
3
3
 
4
4
  class AuthorizeNetGateway < Gateway
5
5
  API_VERSION = '3.1'
6
- LIVE_URL = "https://secure.authorize.net/gateway/transact.dll"
7
- TEST_URL = "https://test.authorize.net/gateway/transact.dll"
8
-
6
+
7
+ class_inheritable_accessor :test_url, :live_url
8
+
9
+ self.test_url = "https://test.authorize.net/gateway/transact.dll"
10
+ self.live_url = "https://secure.authorize.net/gateway/transact.dll"
11
+
9
12
  APPROVED, DECLINED, ERROR = 1, 2, 3
10
13
 
11
14
  RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3
@@ -43,6 +46,11 @@ module ActiveMerchant #:nodoc:
43
46
  attr_reader :url
44
47
  attr_reader :response
45
48
  attr_reader :options
49
+
50
+ self.supported_countries = ['US']
51
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
52
+ self.homepage_url = 'http://www.authorize.net/'
53
+ self.display_name = 'Authorize.net'
46
54
 
47
55
  def initialize(options = {})
48
56
  requires!(options, :login, :password)
@@ -90,21 +98,8 @@ module ActiveMerchant #:nodoc:
90
98
 
91
99
  commit('CREDIT', money, post)
92
100
  end
93
-
94
- # We support visa and master card
95
- def self.supported_cardtypes
96
- [:visa, :master, :american_express, :discover]
97
- end
98
-
101
+
99
102
  private
100
-
101
- def expdate(creditcard)
102
- year = sprintf("%.4i", creditcard.year)
103
- month = sprintf("%.2i", creditcard.month)
104
-
105
- "#{year[-2..-1]}#{month}"
106
- end
107
-
108
103
  def commit(action, money, parameters)
109
104
  parameters[:amount] = amount(money) unless action == 'VOID'
110
105
 
@@ -115,10 +110,11 @@ module ActiveMerchant #:nodoc:
115
110
  return result
116
111
  end
117
112
 
118
- url = test? ? TEST_URL : LIVE_URL
113
+ url = test? ? self.test_url : self.live_url
119
114
  data = ssl_post url, post_data(action, parameters)
120
115
 
121
116
  @response = parse(data)
117
+
122
118
  success = @response[:response_code] == APPROVED
123
119
  message = message_from(@response)
124
120
 
@@ -138,8 +134,8 @@ module ActiveMerchant #:nodoc:
138
134
  end
139
135
 
140
136
  def parse(body)
141
- fields = body[1..-2].split(/\$,\$/)
142
-
137
+ fields = split(body)
138
+
143
139
  results = {
144
140
  :response_code => fields[RESPONSE_CODE].to_i,
145
141
  :response_reason_code => fields[RESPONSE_REASON_CODE],
@@ -230,7 +226,7 @@ module ActiveMerchant #:nodoc:
230
226
  return AVS_MESSAGES[results[:avs_result_code]] if AVS_ERRORS.include?(results[:avs_result_code])
231
227
  end
232
228
 
233
- return results[:response_reason_text][0..-2] # Forget the punctuation at the end
229
+ return results[:response_reason_text].nil? ? '' : results[:response_reason_text][0..-2]
234
230
  end
235
231
 
236
232
  def expdate(creditcard)
@@ -239,6 +235,10 @@ module ActiveMerchant #:nodoc:
239
235
 
240
236
  "#{month}#{year[-2..-1]}"
241
237
  end
238
+
239
+ def split(response)
240
+ response[1..-2].split(/\$,\$/)
241
+ end
242
242
  end
243
243
 
244
244
  AuthorizedNetGateway = AuthorizeNetGateway