activemerchant 1.2.1 → 1.3.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 (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)