activemerchant 1.1.0 → 1.2.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 (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