activemerchant 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +310 -294
  3. data/CONTRIBUTERS +13 -0
  4. data/README +55 -31
  5. data/Rakefile +21 -13
  6. data/lib/active_merchant.rb +7 -0
  7. data/lib/active_merchant/billing/avs_result.rb +95 -0
  8. data/lib/active_merchant/billing/base.rb +8 -3
  9. data/lib/active_merchant/billing/check.rb +61 -0
  10. data/lib/active_merchant/billing/credit_card.rb +104 -80
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +11 -8
  12. data/lib/active_merchant/billing/credit_card_methods.rb +76 -32
  13. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  14. data/lib/active_merchant/billing/expiry_date.rb +28 -0
  15. data/lib/active_merchant/billing/gateway.rb +47 -111
  16. data/lib/active_merchant/billing/gateways/authorize_net.rb +508 -121
  17. data/lib/active_merchant/billing/gateways/bogus.rb +26 -32
  18. data/lib/active_merchant/billing/gateways/brain_tree.rb +82 -70
  19. data/lib/active_merchant/billing/gateways/card_stream.rb +43 -15
  20. data/lib/active_merchant/billing/gateways/cyber_source.rb +9 -29
  21. data/lib/active_merchant/billing/gateways/data_cash.rb +18 -38
  22. data/lib/active_merchant/billing/gateways/efsnet.rb +23 -50
  23. data/lib/active_merchant/billing/gateways/eway.rb +8 -19
  24. data/lib/active_merchant/billing/gateways/exact.rb +17 -25
  25. data/lib/active_merchant/billing/gateways/linkpoint.rb +18 -25
  26. data/lib/active_merchant/billing/gateways/moneris.rb +9 -39
  27. data/lib/active_merchant/billing/gateways/net_registry.rb +113 -182
  28. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  29. data/lib/active_merchant/billing/gateways/pay_junction.rb +52 -73
  30. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  31. data/lib/active_merchant/billing/gateways/payflow.rb +13 -14
  32. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +55 -37
  33. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +4 -0
  34. data/lib/active_merchant/billing/gateways/payflow_express.rb +2 -4
  35. data/lib/active_merchant/billing/gateways/payment_express.rb +11 -30
  36. data/lib/active_merchant/billing/gateways/paypal.rb +3 -14
  37. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +36 -16
  38. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -2
  39. data/lib/active_merchant/billing/gateways/plugnpay.rb +7 -15
  40. data/lib/active_merchant/billing/gateways/protx.rb +24 -25
  41. data/lib/active_merchant/billing/gateways/psigate.rb +34 -71
  42. data/lib/active_merchant/billing/gateways/psl_card.rb +24 -19
  43. data/lib/active_merchant/billing/gateways/quickpay.rb +10 -24
  44. data/lib/active_merchant/billing/gateways/realex.rb +7 -19
  45. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  46. data/lib/active_merchant/billing/gateways/skip_jack.rb +437 -0
  47. data/lib/active_merchant/billing/gateways/trans_first.rb +5 -14
  48. data/lib/active_merchant/billing/gateways/trust_commerce.rb +100 -39
  49. data/lib/active_merchant/billing/gateways/usa_epay.rb +60 -55
  50. data/lib/active_merchant/billing/gateways/verifi.rb +32 -39
  51. data/lib/active_merchant/billing/gateways/viaklix.rb +31 -37
  52. data/lib/active_merchant/billing/integrations.rb +2 -0
  53. data/lib/active_merchant/billing/integrations/bogus.rb +5 -0
  54. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  55. data/lib/active_merchant/billing/integrations/chronopay.rb +5 -0
  56. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  57. data/lib/active_merchant/billing/integrations/gestpay.rb +5 -0
  58. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  59. data/lib/active_merchant/billing/integrations/hi_trust.rb +26 -0
  60. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  61. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +57 -0
  62. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  63. data/lib/active_merchant/billing/integrations/nochex.rb +5 -0
  64. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  65. data/lib/active_merchant/billing/integrations/paypal.rb +5 -0
  66. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  67. data/lib/active_merchant/billing/integrations/return.rb +35 -0
  68. data/lib/active_merchant/billing/integrations/two_checkout.rb +5 -0
  69. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  70. data/lib/active_merchant/billing/response.rb +12 -8
  71. data/lib/active_merchant/lib/posts_data.rb +39 -7
  72. data/lib/active_merchant/lib/requires_parameters.rb +2 -3
  73. data/lib/active_merchant/lib/utils.rb +18 -0
  74. data/lib/active_merchant/lib/validateable.rb +3 -3
  75. data/lib/support/gateway_support.rb +22 -9
  76. data/script/destroy +14 -0
  77. data/script/generate +7 -7
  78. data/test/fixtures.yml +25 -3
  79. data/test/remote/gateways/remote_authorize_net_test.rb +145 -0
  80. data/test/remote/gateways/remote_brain_tree_test.rb +118 -0
  81. data/test/{remote_tests → remote/gateways}/remote_card_stream_test.rb +56 -68
  82. data/test/{remote_tests → remote/gateways}/remote_cyber_source_test.rb +21 -32
  83. data/test/{remote_tests → remote/gateways}/remote_data_cash_test.rb +2 -2
  84. data/test/{remote_tests → remote/gateways}/remote_efsnet_test.rb +22 -34
  85. data/test/{remote_tests → remote/gateways}/remote_eway_test.rb +18 -15
  86. data/test/{remote_tests → remote/gateways}/remote_exact_test.rb +20 -19
  87. data/test/{remote_tests → remote/gateways}/remote_linkpoint_test.rb +31 -63
  88. data/test/remote/gateways/remote_moneris_test.rb +82 -0
  89. data/test/{remote_tests → remote/gateways}/remote_net_registry_test.rb +19 -54
  90. data/test/remote/gateways/remote_netbilling_test.rb +70 -0
  91. data/test/{remote_tests → remote/gateways}/remote_pay_junction_test.rb +41 -60
  92. data/test/remote/gateways/remote_pay_secure_test.rb +39 -0
  93. data/test/{remote_tests → remote/gateways}/remote_payflow_express_test.rb +2 -2
  94. data/test/{remote_tests → remote/gateways}/remote_payflow_test.rb +34 -38
  95. data/test/{remote_tests → remote/gateways}/remote_payflow_uk_test.rb +13 -12
  96. data/test/{remote_tests → remote/gateways}/remote_payment_express_test.rb +26 -36
  97. data/test/{remote_tests → remote/gateways}/remote_paypal_express_test.rb +3 -3
  98. data/test/{remote_tests → remote/gateways}/remote_paypal_test.rb +25 -21
  99. data/test/{remote_tests → remote/gateways}/remote_plugnpay_test.rb +18 -16
  100. data/test/{remote_tests → remote/gateways}/remote_protx_test.rb +33 -33
  101. data/test/remote/gateways/remote_psigate_test.rb +50 -0
  102. data/test/{remote_tests → remote/gateways}/remote_psl_card_test.rb +27 -26
  103. data/test/{remote_tests → remote/gateways}/remote_quickpay_test.rb +48 -48
  104. data/test/{remote_tests → remote/gateways}/remote_realex_test.rb +30 -33
  105. data/test/remote/gateways/remote_secure_pay_tech_test.rb +37 -0
  106. data/test/remote/gateways/remote_secure_pay_test.rb +28 -0
  107. data/test/remote/gateways/remote_skipjack_test.rb +105 -0
  108. data/test/{remote_tests → remote/gateways}/remote_trans_first_test.rb +7 -10
  109. data/test/remote/gateways/remote_trust_commerce_test.rb +152 -0
  110. data/test/{remote_tests → remote/gateways}/remote_usa_epay_test.rb +11 -22
  111. data/test/{remote_tests → remote/gateways}/remote_verifi_test.rb +27 -27
  112. data/test/{remote_tests → remote/gateways}/remote_viaklix_test.rb +8 -18
  113. data/test/{remote_tests → remote/integrations}/remote_gestpay_integration_test.rb +1 -1
  114. data/test/{remote_tests → remote/integrations}/remote_paypal_integration_test.rb +1 -1
  115. data/test/test_helper.rb +102 -61
  116. data/test/unit/avs_result_test.rb +59 -0
  117. data/test/unit/base_test.rb +33 -39
  118. data/test/unit/check_test.rb +76 -0
  119. data/test/unit/credit_card_formatting_test.rb +10 -15
  120. data/test/unit/credit_card_methods_test.rb +132 -17
  121. data/test/unit/credit_card_test.rb +157 -228
  122. data/test/unit/cvv_result_test.rb +33 -0
  123. data/test/unit/expiry_date_test.rb +21 -0
  124. data/test/unit/gateways/authorize_net_test.rb +180 -40
  125. data/test/unit/gateways/bogus_test.rb +2 -3
  126. data/test/unit/gateways/brain_tree_test.rb +63 -29
  127. data/test/unit/gateways/card_stream_test.rb +59 -6
  128. data/test/unit/gateways/cyber_source_test.rb +59 -40
  129. data/test/unit/gateways/data_cash_test.rb +82 -1
  130. data/test/unit/gateways/efsnet_test.rb +97 -44
  131. data/test/unit/gateways/eway_test.rb +55 -42
  132. data/test/unit/gateways/exact_test.rb +93 -55
  133. data/test/unit/gateways/gateway_test.rb +7 -0
  134. data/test/unit/gateways/linkpoint_test.rb +60 -58
  135. data/test/unit/gateways/moneris_test.rb +67 -76
  136. data/test/unit/gateways/net_registry_test.rb +351 -419
  137. data/test/unit/gateways/netbilling_test.rb +54 -0
  138. data/test/unit/gateways/pay_junction_test.rb +108 -46
  139. data/test/unit/gateways/pay_secure_test.rb +71 -0
  140. data/test/unit/gateways/payflow_express_test.rb +0 -8
  141. data/test/unit/gateways/payflow_test.rb +136 -65
  142. data/test/unit/gateways/payflow_uk_test.rb +0 -38
  143. data/test/unit/gateways/payment_express_test.rb +31 -51
  144. data/test/unit/gateways/paypal_express_test.rb +8 -2
  145. data/test/unit/gateways/paypal_test.rb +213 -54
  146. data/test/unit/gateways/plugnpay_test.rb +39 -32
  147. data/test/unit/gateways/protx_test.rb +45 -33
  148. data/test/unit/gateways/psigate_test.rb +146 -87
  149. data/test/unit/gateways/psl_card_test.rb +37 -24
  150. data/test/unit/gateways/quickpay_test.rb +33 -46
  151. data/test/unit/gateways/realex_test.rb +32 -31
  152. data/test/unit/gateways/secure_pay_tech_test.rb +44 -0
  153. data/test/unit/gateways/secure_pay_test.rb +35 -26
  154. data/test/unit/gateways/skip_jack_test.rb +125 -0
  155. data/test/unit/gateways/trans_first_test.rb +24 -37
  156. data/test/unit/gateways/trust_commerce_test.rb +47 -26
  157. data/test/unit/gateways/usa_epay_test.rb +52 -41
  158. data/test/unit/gateways/verifi_test.rb +41 -35
  159. data/test/unit/gateways/viaklix_test.rb +38 -32
  160. data/test/unit/generators/test_gateway_generator.rb +46 -0
  161. data/test/unit/generators/test_generator_helper.rb +20 -0
  162. data/test/unit/generators/test_integration_generator.rb +53 -0
  163. data/test/unit/integrations/action_view_helper_test.rb +7 -14
  164. data/test/unit/integrations/bogus_module_test.rb +4 -0
  165. data/test/unit/integrations/chronopay_module_test.rb +4 -0
  166. data/test/unit/integrations/gestpay_module_test.rb +4 -0
  167. data/test/unit/integrations/helpers/hi_trust_helper_test.rb +16 -0
  168. data/test/unit/integrations/hi_trust_module_test.rb +13 -0
  169. data/test/unit/integrations/nochex_module_test.rb +4 -0
  170. data/test/unit/integrations/notifications/hi_trust_notification_test.rb +38 -0
  171. data/test/unit/integrations/paypal_module_test.rb +4 -0
  172. data/test/unit/integrations/returns/chronopay_return_test.rb +11 -0
  173. data/test/unit/integrations/returns/gestpay_return_test.rb +10 -0
  174. data/test/unit/integrations/returns/hi_trust_return_test.rb +24 -0
  175. data/test/unit/integrations/returns/nochex_return_test.rb +10 -0
  176. data/test/unit/integrations/returns/paypal_return_test.rb +10 -0
  177. data/test/unit/integrations/returns/return_test.rb +11 -0
  178. data/test/unit/integrations/returns/two_checkout_return_test.rb +24 -0
  179. data/test/unit/integrations/two_checkout_module_test.rb +4 -0
  180. data/test/unit/posts_data_test.rb +86 -0
  181. data/test/unit/response_test.rb +15 -1
  182. data/test/unit/utils_test.rb +7 -0
  183. data/test/unit/validateable_test.rb +10 -6
  184. metadata +180 -142
  185. metadata.gz.sig +0 -0
  186. data/lib/active_merchant/billing/gateways/paypal/api_cert_chain.crt +0 -35
  187. data/script/generator/base.rb +0 -45
  188. data/script/generator/generator.rb +0 -24
  189. data/script/generator/generators/gateway/gateway_generator.rb +0 -14
  190. data/script/generator/generators/gateway/templates/gateway.rb +0 -73
  191. data/script/generator/generators/gateway/templates/gateway_test.rb +0 -41
  192. data/script/generator/generators/gateway/templates/remote_gateway_test.rb +0 -56
  193. data/script/generator/generators/integration/integration_generator.rb +0 -25
  194. data/script/generator/generators/integration/templates/helper.rb +0 -34
  195. data/script/generator/generators/integration/templates/helper_test.rb +0 -54
  196. data/script/generator/generators/integration/templates/integration.rb +0 -18
  197. data/script/generator/generators/integration/templates/module_test.rb +0 -9
  198. data/script/generator/generators/integration/templates/notification.rb +0 -100
  199. data/script/generator/generators/integration/templates/notification_test.rb +0 -41
  200. data/script/generator/manifest.rb +0 -20
  201. data/test/remote_tests/remote_authorize_net_test.rb +0 -113
  202. data/test/remote_tests/remote_brain_tree_test.rb +0 -78
  203. data/test/remote_tests/remote_moneris_test.rb +0 -110
  204. data/test/remote_tests/remote_psigate_test.rb +0 -87
  205. data/test/remote_tests/remote_secure_pay_test.rb +0 -36
  206. data/test/remote_tests/remote_trust_commerce_test.rb +0 -136
@@ -2,6 +2,14 @@ module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  # Bogus Gateway
4
4
  class BogusGateway < Gateway
5
+ AUTHORIZATION = '53433'
6
+
7
+ SUCCESS_MESSAGE = "Bogus Gateway: Forced success"
8
+ FAILURE_MESSAGE = "Bogus Gateway: Forced failure"
9
+ ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error"
10
+ CREDIT_ERROR_MESSAGE = "Bogus Gateway: Use trans_id 1 for success, 2 for exception and anything else for error"
11
+ UNSTORE_ERROR_MESSAGE = "Bogus Gateway: Use trans_id 1 for success, 2 for exception and anything else for error"
12
+ CAPTURE_ERROR_MESSAGE = "Bogus Gateway: Use authorization number 1 for exception, 2 for error and anything else for success"
5
13
 
6
14
  self.supported_countries = ['US']
7
15
  self.supported_cardtypes = [:bogus]
@@ -11,82 +19,68 @@ module ActiveMerchant #:nodoc:
11
19
  def authorize(money, creditcard, options = {})
12
20
  case creditcard.number
13
21
  when '1'
14
- Response.new(true, "Bogus Gateway: Forced success", {:authorized_amount => money.to_s}, :test => true, :authorization => '53433' )
22
+ Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money.to_s}, :test => true, :authorization => AUTHORIZATION )
15
23
  when '2'
16
- Response.new(false, "Bogus Gateway: Forced failure", {:authorized_amount => money.to_s, :error => 'Bogus Gateway: Forced failure' }, :test => true)
24
+ Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money.to_s, :error => FAILURE_MESSAGE }, :test => true)
17
25
  else
18
- raise Error, 'Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error'
26
+ raise Error, ERROR_MESSAGE
19
27
  end
20
28
  end
21
29
 
22
30
  def purchase(money, creditcard, options = {})
23
31
  case creditcard.number
24
32
  when '1'
25
- Response.new(true, "Bogus Gateway: Forced success", {:paid_amount => money.to_s}, :test => true)
33
+ Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money.to_s}, :test => true)
26
34
  when '2'
27
- Response.new(false, "Bogus Gateway: Forced failure", {:paid_amount => money.to_s, :error => 'Bogus Gateway: Forced failure' },:test => true)
35
+ Response.new(false, FAILURE_MESSAGE, {:paid_amount => money.to_s, :error => FAILURE_MESSAGE },:test => true)
28
36
  else
29
- raise Error, 'Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error'
37
+ raise Error, ERROR_MESSAGE
30
38
  end
31
39
  end
32
40
 
33
41
  def credit(money, ident, options = {})
34
42
  case ident
35
43
  when '1'
36
- Response.new(true, "Bogus Gateway: Forced success", {:paid_amount => money.to_s}, :test => true)
44
+ raise Error, CREDIT_ERROR_MESSAGE
37
45
  when '2'
38
- Response.new(false, "Bogus Gateway: Forced failure", {:paid_amount => money.to_s, :error => 'Bogus Gateway: Forced failure' },:test => true)
46
+ Response.new(false, FAILURE_MESSAGE, {:paid_amount => money.to_s, :error => FAILURE_MESSAGE }, :test => true)
39
47
  else
40
- raise Error, 'Bogus Gateway: Use trans_id 1 for success, 2 for exception and anything else for error'
48
+ Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money.to_s}, :test => true)
41
49
  end
42
50
  end
43
51
 
44
52
  def capture(money, ident, options = {})
45
53
  case ident
46
54
  when '1'
47
- raise Error, 'Bogus Gateway: Use authorization number 1 for exception, 2 for error and anything else for success'
55
+ raise Error, CAPTURE_ERROR_MESSAGE
48
56
  when '2'
49
- Response.new(false, "Bogus Gateway: Forced failure", {:paid_amount => money.to_s, :error => 'Bogus Gateway: Forced failure' }, :test => true)
57
+ Response.new(false, FAILURE_MESSAGE, {:paid_amount => money.to_s, :error => FAILURE_MESSAGE }, :test => true)
50
58
  else
51
- Response.new(true, "Bogus Gateway: Forced success", {:paid_amount => money.to_s}, :test => true)
59
+ Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money.to_s}, :test => true)
52
60
  end
53
61
  end
54
62
 
55
63
  def store(creditcard, options = {})
56
64
  case creditcard.number
57
65
  when '1'
58
- Response.new(true, "Bogus Gateway: Forced success", {:billingid => '1'}, :test => true, :authorization => '53433' )
66
+ Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION )
59
67
  when '2'
60
- Response.new(false, "Bogus Gateway: Forced failure", {:billingid => nil, :error => 'Bogus Gateway: Forced failure' }, :test => true)
68
+ Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true)
61
69
  else
62
- raise Error, 'Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error'
70
+ raise Error, ERROR_MESSAGE
63
71
  end
64
72
  end
65
73
 
66
74
  def unstore(identification, options = {})
67
75
  case identification
68
76
  when '1'
69
- Response.new(true, "Bogus Gateway: Forced success", {}, :test => true)
77
+ Response.new(true, SUCCESS_MESSAGE, {}, :test => true)
70
78
  when '2'
71
- Response.new(false, "Bogus Gateway: Forced failure", {:error => 'Bogus Gateway: Forced failure' },:test => true)
79
+ Response.new(false, FAILURE_MESSAGE, {:error => FAILURE_MESSAGE },:test => true)
72
80
  else
73
- raise Error, 'Bogus Gateway: Use trans_id 1 for success, 2 for exception and anything else for error'
81
+ raise Error, UNSTORE_ERROR_MESSAGE
74
82
  end
75
83
  end
76
-
77
- private
78
-
79
- def deal_with_cc(creditcard)
80
- case creditcard.number
81
- when '1'
82
- Response.new(true, "Bogus Gateway: Forced success", {}, :test => true)
83
- when '2'
84
- Response.new(false, "Bogus Gateway: Forced failure", @response, :test => true)
85
- else
86
- raise Error, 'Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error'
87
- end
88
- end
89
-
90
84
  end
91
85
  end
92
86
  end
@@ -1,54 +1,27 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'check.rb')
2
+
1
3
  module ActiveMerchant #:nodoc:
2
4
  module Billing #:nodoc:
3
5
  class BrainTreeGateway < Gateway
4
6
  URL = 'https://secure.braintreepaymentgateway.com/api/transact.php'
5
- attr_reader :url
6
- attr_reader :response
7
- attr_reader :options
8
-
7
+
9
8
  self.supported_countries = ['US']
10
9
  self.supported_cardtypes = [:visa, :master, :american_express]
11
10
  self.homepage_url = 'http://www.braintreepaymentsolutions.com'
12
11
  self.display_name = 'Braintree'
13
12
 
14
- AVS_MESSAGES = {
15
- "X" => "Exact match, 9-character numeric ZIP",
16
- "Y" => "Exact match, 5-character numeric ZIP",
17
- "D" => "Exact match, 5-character numeric ZIP",
18
- "M" => "Exact match, 5-character numeric ZIP",
19
- "A" => "Address match only",
20
- "B" => "Address match only",
21
- "W" => "9-character numeric ZIP match only",
22
- "Z" => "5-character Zip match only",
23
- "P" => "5-character Zip match only",
24
- "L" => "5-character Zip match only",
25
- "N" => "No address or ZIP match",
26
- "C" => "No address or ZIP match",
27
- "U" => "Address unavailable",
28
- "G" => "Non-U.S. Issuer does not participate",
29
- "I" => "Non-U.S. Issuer does not participate",
30
- "R" => "Issuer system unavailable",
31
- "E" => "Not a mail/phone order",
32
- "S" => "Service not supported",
33
- "0" => "AVS Not Available",
34
- "O" => "AVS Not Available",
35
- "B" => "AVS Not Available"
36
- }
37
-
38
- CARD_CODE_MESSAGES = {
39
- "M" => "CVV2/CVC2 Match",
40
- "N" => "CVV2/CVC2 No Match",
41
- "P" => "Not Processed",
42
- "S" => "Merchant has indicated that CVV2/CVC2 is not present on card",
43
- "U" => "Issuer is not certified and/or has not provided Visa encryption keys"
44
- }
45
-
46
13
  def initialize(options = {})
47
14
  requires!(options, :login, :password)
48
15
  @options = options
49
16
  super
50
17
  end
51
18
 
19
+ # Pass :store => true in the options to store the
20
+ # payment info at BrainTree and get a generated
21
+ # customer_vault_id in the response.
22
+ # Pass :store => some_number_or_string to specify the
23
+ # customer_vault_id BrainTree should use (make sure it's
24
+ # unique).
52
25
  def authorize(money, creditcard, options = {})
53
26
  post = {}
54
27
  add_invoice(post, options)
@@ -59,11 +32,11 @@ module ActiveMerchant #:nodoc:
59
32
  commit('auth', money, post)
60
33
  end
61
34
 
62
- def purchase(money, creditcard, options = {})
35
+ def purchase(money, payment_source, options = {})
63
36
  post = {}
64
37
  add_invoice(post, options)
65
- add_payment_source(post, creditcard,options)
66
- add_address(post, creditcard, options)
38
+ add_payment_source(post, payment_source, options)
39
+ add_address(post, payment_source, options)
67
40
  add_customer_data(post, options)
68
41
 
69
42
  commit('sale', money, post)
@@ -74,6 +47,33 @@ module ActiveMerchant #:nodoc:
74
47
  post[:transactionid] = authorization
75
48
  commit('capture', money, post)
76
49
  end
50
+
51
+ def void(authorization, options = {})
52
+ post ={}
53
+ post[:transactionid] = authorization
54
+ commit('void', nil, post)
55
+ end
56
+
57
+ # Update the values (such as CC expiration) stored at
58
+ # BrainTree. The CC number must be supplied in the
59
+ # CreditCard object.
60
+ def update(vault_id, creditcard, options = {})
61
+ post = {}
62
+ post[:customer_vault] = "update_customer"
63
+ add_customer_vault_id(post, vault_id)
64
+ add_creditcard(post, creditcard, options)
65
+ add_address(post, creditcard, options)
66
+ add_customer_data(post, options)
67
+
68
+ commit(nil, nil, post)
69
+ end
70
+
71
+ def delete(vault_id)
72
+ post = {}
73
+ post[:customer_vault] = "delete_customer"
74
+ add_customer_vault_id(post, vault_id)
75
+ commit(nil, nil, post)
76
+ end
77
77
 
78
78
  private
79
79
  def add_customer_data(post, options)
@@ -103,11 +103,11 @@ module ActiveMerchant #:nodoc:
103
103
  post[:orderid] = options[:order_id].to_s.gsub(/[^\w.]/, '')
104
104
  end
105
105
 
106
- def add_payment_source(params, source,options)
107
- if source.is_a?(String)
108
- add_customer_vault_id(params, source)
109
- else
110
- add_creditcard(params, source,options)
106
+ def add_payment_source(params, source, options={})
107
+ case determine_funding_source(source)
108
+ when :vault then add_customer_vault_id(params, source)
109
+ when :credit_card then add_creditcard(params, source, options)
110
+ when :check then add_check(params, source)
111
111
  end
112
112
  end
113
113
 
@@ -115,9 +115,11 @@ module ActiveMerchant #:nodoc:
115
115
  params[:customer_vault_id] = vault_id
116
116
  end
117
117
 
118
- def add_creditcard(post, creditcard,options)
119
- post[:customer_vault] = "add_customer" if options[:store]
120
-
118
+ def add_creditcard(post, creditcard,options)
119
+ if options[:store]
120
+ post[:customer_vault] = "add_customer"
121
+ post[:customer_vault_id] = options[:store] unless options[:store] == true
122
+ end
121
123
  post[:ccnumber] = creditcard.number
122
124
  post[:cvv] = creditcard.verification_value if creditcard.verification_value?
123
125
  post[:ccexp] = expdate(creditcard)
@@ -125,32 +127,35 @@ module ActiveMerchant #:nodoc:
125
127
  post[:lastname] = creditcard.last_name
126
128
  end
127
129
 
130
+ def add_check(post, check)
131
+ post[:payment] = 'check' # Set transaction to ACH
132
+ post[:checkname] = check.name # The name on the customer's Checking Account
133
+ post[:checkaba] = check.routing_number # The customer's bank routing number
134
+ post[:checkaccount] = check.account_number # The customer's account number
135
+ post[:account_holder_type] = check.account_holder_type # The customer's type of ACH account
136
+ post[:account_type] = check.account_type # The customer's type of ACH account
137
+ end
138
+
128
139
  def parse(body)
129
140
  results = {}
130
141
  body.split(/&/).each do |pair|
131
142
  key,val = pair.split(/=/)
132
143
  results[key] = val
133
144
  end
134
- results[:card_code_message] = CARD_CODE_MESSAGES[results[:cvvresponse]] if results[:cvvresponse]
135
- results[:avs_message] = AVS_MESSAGES[results["avsresponse"]] if results["avsresponse"]
136
- results
137
145
 
146
+ results
138
147
  end
139
148
 
140
149
  def commit(action, money, parameters)
141
150
  parameters[:amount] = amount(money) if money
142
151
 
143
- if result = test_result_from_cc_number(parameters[:ccnumber])
144
- return result
145
- end
146
-
147
- data = ssl_post URL, post_data(action,parameters)
148
-
149
- @response = parse(data)
152
+ response = parse( ssl_post(URL, post_data(action,parameters)) )
150
153
 
151
- Response.new(@response["response"]=="1", message_from(@response), @response,
152
- :authorization => @response["transactionid"],
153
- :test => test?
154
+ Response.new(response["response"] == "1", message_from(response), response,
155
+ :authorization => response["transactionid"],
156
+ :test => test?,
157
+ :cvv_result => response["cvvresponse"],
158
+ :avs_result => { :code => response["avsresponse"] }
154
159
  )
155
160
 
156
161
  end
@@ -164,27 +169,34 @@ module ActiveMerchant #:nodoc:
164
169
 
165
170
 
166
171
  def message_from(response)
167
- r=response["responsetext"]
168
- case r
169
- when "SUCCESS","Approved"
170
- "This transaction has been approved"
171
- when "DECLINE"
172
- "This transaction has been declined"
173
- else
174
- r
175
- end
172
+ case response["responsetext"]
173
+ when "SUCCESS","Approved"
174
+ "This transaction has been approved"
175
+ when "DECLINE"
176
+ "This transaction has been declined"
177
+ else
178
+ response["responsetext"]
179
+ end
176
180
  end
177
181
 
178
182
  def post_data(action, parameters = {})
179
183
  post = {}
180
184
  post[:username] = @options[:login]
181
185
  post[:password] = @options[:password]
182
- post[:type] = action
186
+ post[:type] = action if action
183
187
 
184
188
  request = post.merge(parameters).map {|key,value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&")
185
189
  request
186
190
  end
187
191
 
192
+ def determine_funding_source(source)
193
+ case
194
+ when source.is_a?(String) then :vault
195
+ when CreditCard.card_companies.keys.include?(source.type) then :credit_card
196
+ when source.type == 'check' then :check
197
+ else raise ArgumentError, "Unsupported funding source provided"
198
+ end
199
+ end
188
200
  end
189
201
  end
190
202
  end
@@ -24,7 +24,7 @@ module ActiveMerchant #:nodoc:
24
24
  self.money_format = :cents
25
25
  self.default_currency = 'GBP'
26
26
  self.supported_countries = ['GB']
27
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :solo, :switch]
27
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover, :jcb, :maestro, :solo, :switch]
28
28
  self.homepage_url = 'http://www.cardstream.com/'
29
29
  self.display_name = 'CardStream'
30
30
 
@@ -53,12 +53,39 @@ module ActiveMerchant #:nodoc:
53
53
  :authorization => 'ESALE_KEYED'
54
54
  }
55
55
 
56
- POST_HEADERS = { 'Content-Type' => 'application/x-www-form-urlencoded' }
57
-
58
- attr_reader :url
59
- attr_reader :response
60
- attr_reader :options
61
-
56
+ CVV_CODE = {
57
+ '0' => 'U',
58
+ '1' => 'P',
59
+ '2' => 'M',
60
+ '4' => 'N'
61
+ }
62
+
63
+ # 0 - No additional information available.
64
+ # 1 - Postcode not checked.
65
+ # 2 - Postcode matched.
66
+ # 4 - Postcode not matched.
67
+ # 8 - Postcode partially matched.
68
+ AVS_POSTAL_MATCH = {
69
+ "0" => nil,
70
+ "1" => nil,
71
+ "2" => "Y",
72
+ "4" => "N",
73
+ "8" => "N"
74
+ }
75
+
76
+ # 0 - No additional information available.
77
+ # 1 - Address numeric not checked.
78
+ # 2 - Address numeric matched.
79
+ # 4 - Address numeric not matched.
80
+ # 8 - Address numeric partially matched.
81
+ AVS_STREET_MATCH = {
82
+ "0" => nil,
83
+ "1" => nil,
84
+ "2" => "Y",
85
+ "4" => "N",
86
+ "8" => "N"
87
+ }
88
+
62
89
  def initialize(options = {})
63
90
  requires!(options, :login, :password)
64
91
  @options = options
@@ -109,7 +136,7 @@ module ActiveMerchant #:nodoc:
109
136
 
110
137
  if [ 'american_express', 'diners_club' ].include?(credit_card.type.to_s)
111
138
  add_pair(post, :AEIT1Quantity, 1)
112
- add_pair(post, :AEIT1Description, options[:description] || options[:order_id])
139
+ add_pair(post, :AEIT1Description, (options[:description] || options[:order_id]).slice(0, 15))
113
140
  add_pair(post, :AEIT1GrossValue, amount(money))
114
141
  end
115
142
  end
@@ -136,15 +163,16 @@ module ActiveMerchant #:nodoc:
136
163
  end
137
164
 
138
165
  def commit(action, parameters)
139
- data = ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters), POST_HEADERS)
140
- @response = parse(data)
141
-
142
- success = @response[:response_code] == APPROVED
143
- message = message_from(@response)
166
+ response = parse( ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters)) )
144
167
 
145
- Response.new(success, message, @response,
168
+ Response.new(response[:response_code] == APPROVED, message_from(response), response,
146
169
  :test => test?,
147
- :authorization => @response[:cross_reference]
170
+ :authorization => response[:cross_reference],
171
+ :cvv_result => CVV_CODE[ response[:avscv2_response_code].to_s[0, 1] ],
172
+ :avs_result => {
173
+ :street_match => AVS_STREET_MATCH[ response[:avscv2_response_code].to_s[2, 1] ],
174
+ :postal_match => AVS_POSTAL_MATCH[ response[:avscv2_response_code].to_s[1, 1] ]
175
+ }
148
176
  )
149
177
  end
150
178
 
@@ -15,11 +15,6 @@ module ActiveMerchant #:nodoc:
15
15
  # * productCode is a value in the line_items hash that is used to tell CyberSource what kind of item you are selling. It is used when calculating tax/VAT.
16
16
  # * All transactions use dollar values.
17
17
  class CyberSourceGateway < Gateway
18
-
19
- attr_reader :url
20
- attr_reader :response
21
- attr_accessor :options
22
-
23
18
  TEST_URL = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor'
24
19
  LIVE_URL = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor'
25
20
 
@@ -167,7 +162,7 @@ module ActiveMerchant #:nodoc:
167
162
  # Create all address hash key value pairs so that we still function if we were only provided with one or two of them
168
163
  def setup_address_hash(options)
169
164
  options[:billing_address] = options[:billing_address] || options[:address] || {}
170
- options[:shipping_address] = options[:shipping_address] || options[:billing_address]
165
+ options[:shipping_address] = options[:shipping_address] || {}
171
166
  end
172
167
 
173
168
  def build_auth_request(money, creditcard, options)
@@ -334,35 +329,20 @@ module ActiveMerchant #:nodoc:
334
329
 
335
330
  # Contact CyberSource, make the SOAP request, and parse the reply into a Response object
336
331
  def commit(request, options)
337
- request_body = build_request(request, options)
338
-
339
- if test?
340
- card_number = parse_credit_card_number(request_body)
341
- if result = test? && test_result_from_cc_number(card_number)
342
- return result
343
- end
344
- end
345
-
346
- url = test? ? TEST_URL : LIVE_URL
347
- data = ssl_post(url, request_body)
348
- reply = parse(data)
332
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, build_request(request, options)))
349
333
 
350
- success = reply[:decision] == "ACCEPT"
351
- message = @@response_codes[('r' + reply[:reasonCode]).to_sym] rescue reply[:message]
352
- authorization = success ? [ options[:order_id], reply[:requestID], reply[:requestToken] ].compact.join(";") : nil
334
+ success = response[:decision] == "ACCEPT"
335
+ message = @@response_codes[('r' + response[:reasonCode]).to_sym] rescue response[:message]
336
+ authorization = success ? [ options[:order_id], response[:requestID], response[:requestToken] ].compact.join(";") : nil
353
337
 
354
- Response.new(success, message, reply,
338
+ Response.new(success, message, response,
355
339
  :test => test?,
356
- :authorization => authorization
340
+ :authorization => authorization,
341
+ :avs_result => { :code => response[:avsCode] },
342
+ :cvv_result => response[:cvCode]
357
343
  )
358
344
  end
359
345
 
360
- def parse_credit_card_number(xml)
361
- doc = REXML::Document.new(xml)
362
- node = REXML::XPath.first(doc, '//card/accountNumber')
363
- node && node.text
364
- end
365
-
366
346
  # Parse the SOAP response
367
347
  # Technique inspired by the Paypal Gateway
368
348
  def parse(xml)