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
@@ -0,0 +1,168 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class NetbillingGateway < Gateway
4
+ URL = 'https://secure.netbilling.com:1402/gw/sas/direct3.1'
5
+
6
+ TRANSACTIONS = {
7
+ :authorization => 'A',
8
+ :purchase => 'S',
9
+ :referenced_credit => 'R',
10
+ :unreferenced_credit => 'C',
11
+ :capture => 'D'
12
+ }
13
+
14
+ SUCCESS_CODES = [ '1', 'T' ]
15
+ SUCCESS_MESSAGE = 'The transaction was approved'
16
+ FAILURE_MESSAGE = 'The transaction failed'
17
+ TEST_LOGIN = '104901072025'
18
+
19
+ self.display_name = 'NETbilling'
20
+ self.homepage_url = 'http://www.netbilling.com'
21
+ self.supported_countries = ['US']
22
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
23
+
24
+ def initialize(options = {})
25
+ requires!(options, :login)
26
+ @options = options
27
+ super
28
+ end
29
+
30
+ def authorize(money, credit_card, options = {})
31
+ post = {}
32
+ add_amount(post, money)
33
+ add_invoice(post, options)
34
+ add_credit_card(post, credit_card)
35
+ add_address(post, credit_card, options)
36
+ add_customer_data(post, options)
37
+
38
+ commit(:authorization, money, post)
39
+ end
40
+
41
+ def purchase(money, credit_card, options = {})
42
+ post = {}
43
+ add_amount(post, money)
44
+ add_invoice(post, options)
45
+ add_credit_card(post, credit_card)
46
+ add_address(post, credit_card, options)
47
+ add_customer_data(post, options)
48
+
49
+ commit(:purchase, money, post)
50
+ end
51
+
52
+ def capture(money, authorization, options = {})
53
+ post = {}
54
+ add_reference(post, authorization)
55
+ commit(:capture, money, post)
56
+ end
57
+
58
+ def test?
59
+ @options[:login] == TEST_LOGIN || super
60
+ end
61
+
62
+ private
63
+ def add_amount(post, money)
64
+ post[:amount] = amount(money)
65
+ end
66
+
67
+ def add_reference(post, reference)
68
+ post[:orig_id] = reference
69
+ end
70
+
71
+ def add_customer_data(post, options)
72
+ post[:cust_email] = options[:email]
73
+ post[:cust_ip] = options[:ip]
74
+ end
75
+
76
+ def add_address(post, credit_card, options)
77
+ if billing_address = options[:billing_address] || options[:address]
78
+ post[:bill_street] = billing_address[:address1]
79
+ post[:cust_phone] = billing_address[:phone]
80
+ post[:bill_zip] = billing_address[:zip]
81
+ post[:bill_city] = billing_address[:city]
82
+ post[:bill_country] = billing_address[:country]
83
+ post[:bill_state] = billing_address[:state]
84
+ end
85
+
86
+ if shipping_address = options[:shipping_address]
87
+ first_name, last_name = parse_first_and_last_name(shipping_address[:name])
88
+
89
+ post[:ship_name1] = first_name
90
+ post[:ship_name2] = last_name
91
+ post[:ship_street] = shipping_address[:address1]
92
+ post[:ship_zip] = shipping_address[:zip]
93
+ post[:ship_city] = shipping_address[:city]
94
+ post[:ship_country] = shipping_address[:country]
95
+ post[:ship_state] = shipping_address[:state]
96
+ end
97
+ end
98
+
99
+ def add_invoice(post, options)
100
+ post[:description] = options[:description]
101
+ end
102
+
103
+ def add_credit_card(post, credit_card)
104
+ post[:bill_name1] = credit_card.first_name
105
+ post[:bill_name2] = credit_card.last_name
106
+ post[:card_number] = credit_card.number
107
+ post[:card_expire] = expdate(credit_card)
108
+ post[:card_cvv2] = credit_card.verification_value
109
+ end
110
+
111
+ def parse(body)
112
+ results = {}
113
+ body.split(/&/).each do |pair|
114
+ key,val = pair.split(/=/)
115
+ results[key.to_sym] = CGI.unescape(val)
116
+ end
117
+ results
118
+ end
119
+
120
+ def commit(action, money, parameters)
121
+ response = parse(ssl_post(URL, post_data(action, parameters)))
122
+
123
+ Response.new(success?(response), message_from(response), response,
124
+ :test => test_response?(response),
125
+ :authorization => response[:trans_id],
126
+ :avs_result => { :code => response[:avs_code]},
127
+ :cvv_result => response[:cvv2_code]
128
+ )
129
+ end
130
+
131
+ def test_response?(response)
132
+ !!(test? || response[:auth_msg] =~ /TEST/)
133
+ end
134
+
135
+ def success?(response)
136
+ SUCCESS_CODES.include?(response[:status_code])
137
+ end
138
+
139
+ def message_from(response)
140
+ success?(response) ? SUCCESS_MESSAGE : (response[:auth_msg] || FAILURE_MESSAGE)
141
+ end
142
+
143
+ def expdate(credit_card)
144
+ year = sprintf("%.4i", credit_card.year)
145
+ month = sprintf("%.2i", credit_card.month)
146
+
147
+ "#{month}#{year[-2..-1]}"
148
+ end
149
+
150
+ def post_data(action, parameters = {})
151
+ parameters[:account_id] = @options[:login]
152
+ parameters[:pay_type] = 'C'
153
+ parameters[:tran_type] = TRANSACTIONS[action]
154
+
155
+ parameters.reject{|k,v| v.blank?}.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
156
+ end
157
+
158
+ def parse_first_and_last_name(value)
159
+ name = value.to_s.split(' ')
160
+
161
+ last_name = name.pop || ''
162
+ first_name = name.join(' ')
163
+ [ first_name, last_name ]
164
+ end
165
+ end
166
+ end
167
+ end
168
+
@@ -1,6 +1,5 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
-
4
3
  # PayJunction Gateway
5
4
  #
6
5
  # This gateway accepts the following arguments:
@@ -11,7 +10,8 @@ module ActiveMerchant #:nodoc:
11
10
  #
12
11
  # gateway = ActiveMerchant::Billing::Base.gateway(:pay_junction).new(
13
12
  # :login => "my_account",
14
- # :password => "my_pass" )
13
+ # :password => "my_pass"
14
+ # )
15
15
  #
16
16
  # # set up credit card obj as in main ActiveMerchant example
17
17
  # creditcard = ActiveMerchant::Billing::CreditCard.new(
@@ -25,7 +25,7 @@ module ActiveMerchant #:nodoc:
25
25
  #
26
26
  # # optionally specify address if using AVS
27
27
  # address = { :address1 => '101 Test Ave', :city => 'Test', :state => 'TS',
28
- # :zipcode => '10101', :country => 'US' }
28
+ # :zip => '10101', :country => 'US' }
29
29
  #
30
30
  # # run request
31
31
  # response = gateway.purchase(1000, creditcard, :address => address) # charge 10 dollars
@@ -52,8 +52,7 @@ module ActiveMerchant #:nodoc:
52
52
  #
53
53
  # See the source for initialize() for test account information. Note that
54
54
  # PayJunction does not allow test transactions on your account, so if the
55
- # gateway is running in :test mode or the :test_request option has been
56
- # been specified and is true, your transaction will be run against
55
+ # gateway is running in :test mode your transaction will be run against
57
56
  # PayJunction's global test account and will not show up in your account.
58
57
  #
59
58
  # Transactions ran on this account go through a test processor, so there is no
@@ -93,18 +92,21 @@ module ActiveMerchant #:nodoc:
93
92
  # "instant" transactions.
94
93
  #
95
94
  # dc_invoice :order_id in options for transaction method
96
- # dc_notes :notes in options for transaction method
95
+ # dc_notes :description in options for transaction method
97
96
  #
98
97
  # See example use above for address AVS fields
99
98
  # See #recurring for periodic transaction fields
100
- #
101
-
102
-
103
99
  class PayJunctionGateway < Gateway
104
100
  API_VERSION = '1.2'
105
- LIVE_URL = 'https://payjunction.com/quick_link' # also handles test requests
101
+ URL = 'https://payjunction.com/quick_link' # also handles test requests
102
+
103
+ TEST_LOGIN = 'pj-ql-01'
104
+ TEST_PASSWORD = 'pj-ql-01p'
106
105
 
107
106
  SUCCESS_CODES = ["00", "85"]
107
+ SUCCESS_MESSAGE = 'The transaction was approved.'
108
+
109
+ FAILURE_MESSAGE = 'The transaction was declined.'
108
110
 
109
111
  DECLINE_CODES = {
110
112
  "AE" => 'Address verification failed because address did not match.',
@@ -137,15 +139,8 @@ module ActiveMerchant #:nodoc:
137
139
  '15' => 'Declined because there is no such issuer.',
138
140
  '96' => 'Declined because of a system error.',
139
141
  'N7' => 'Declined because of a CVV2/CVC2 mismatch.',
140
- 'M4' => 'Declined.'
141
-
142
- }
143
-
144
- BADDATA_CODES = {
145
- "FE" => "There was a format error with your Trinity Gateway Service (API) request."
146
- }
147
-
148
- ERROR_CODES = {
142
+ 'M4' => 'Declined.',
143
+ "FE" => "There was a format error with your Trinity Gateway Service (API) request.",
149
144
  "LE" => "Could not log you in (problem with dc_logon and/or dc_password).",
150
145
  'NL' => 'Aborted because of a system error, please try again later. ',
151
146
  'AB' => 'Aborted because of an upstream system error, please try again later.'
@@ -153,11 +148,8 @@ module ActiveMerchant #:nodoc:
153
148
 
154
149
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
155
150
  self.supported_countries = ['US']
156
-
157
151
  self.homepage_url = 'http://www.payjunction.com/'
158
152
  self.display_name = 'PayJunction'
159
-
160
- attr_reader :url, :response, :options
161
153
 
162
154
  def initialize(options = {})
163
155
  requires!(options, :login, :password)
@@ -168,12 +160,12 @@ module ActiveMerchant #:nodoc:
168
160
  # The first half of the preauth(authorize)/postauth(capture) model.
169
161
  # Checks to make sure funds are available for a transaction, and returns a
170
162
  # transaction_id that can be used later to postauthorize (capture) the funds.
171
- def authorize(money, creditcard_or_billing_id, options = {})
163
+ def authorize(money, payment_source, options = {})
172
164
  parameters = {
173
165
  :transaction_amount => amount(money),
174
166
  }
175
167
 
176
- add_payment_source(parameters, creditcard_or_billing_id)
168
+ add_payment_source(parameters, payment_source)
177
169
  add_address(parameters, options)
178
170
  add_optional_fields(parameters, options)
179
171
  commit('AUTHORIZATION', parameters)
@@ -181,12 +173,12 @@ module ActiveMerchant #:nodoc:
181
173
 
182
174
  # A simple sale, capturing funds immediately.
183
175
  # Execute authorization and capture in a single step.
184
- def purchase(money, creditcard_or_billing_id, options = {})
176
+ def purchase(money, payment_source, options = {})
185
177
  parameters = {
186
178
  :transaction_amount => amount(money),
187
179
  }
188
180
 
189
- add_payment_source(parameters, creditcard_or_billing_id)
181
+ add_payment_source(parameters, payment_source)
190
182
  add_address(parameters, options)
191
183
  add_optional_fields(parameters, options)
192
184
  commit('AUTHORIZATION_CAPTURE', parameters)
@@ -238,7 +230,7 @@ module ActiveMerchant #:nodoc:
238
230
  # The optional parameter :starting_at takes a date or time argument or a string in
239
231
  # YYYYMMDD format and can be used to specify when the first charge will be made.
240
232
  # If omitted the first charge will be immediate.
241
- def recurring(money, creditcard_or_billing_id, options = {})
233
+ def recurring(money, payment_source, options = {})
242
234
  requires!(options, [:periodicity, :monthly, :weekly, :daily], :payments)
243
235
 
244
236
  periodic_type = case options[:periodicity]
@@ -268,18 +260,22 @@ module ActiveMerchant #:nodoc:
268
260
  :schedule_start => start_date
269
261
  }
270
262
 
271
- add_payment_source(parameters, creditcard_or_billing_id)
263
+ add_payment_source(parameters, payment_source)
272
264
  add_optional_fields(parameters, options)
273
265
  add_address(parameters, options)
274
266
  commit('AUTHORIZATION_CAPTURE', parameters)
275
267
  end
276
268
 
277
269
  def test?
278
- @options[:test] || super
270
+ test_login? || @options[:test] || super
279
271
  end
280
272
 
281
273
  private
282
274
 
275
+ def test_login?
276
+ @options[:login] == TEST_LOGIN && @options[:password] == TEST_PASSWORD
277
+ end
278
+
283
279
  # add fields depending on payment source selected (cc or transaction id)
284
280
  def add_payment_source(params, source)
285
281
  if source.is_a?(String)
@@ -321,57 +317,40 @@ module ActiveMerchant #:nodoc:
321
317
  params[:invoice] = options[:order_id].to_s.gsub(/[^-\/\w.,']/, '') unless options[:order_id].blank?
322
318
  end
323
319
 
324
- def clean_and_stringify_params(parameters)
325
- # PayJunction uses an HTTPS POST request to submit key-pairs. Here we're going
326
- # to convert all symbols in the params to strings and remove any pairs that
327
- # have a nil value to keep the gateway happy.
328
- to_submit = {}
329
- parameters.keys.reverse.each do |key|
330
- if parameters[key]
331
- to_submit[key.to_s] = parameters[key]
332
- end
320
+ def commit(action, parameters)
321
+ response = parse( ssl_post(URL, post_data(action, parameters)) )
322
+
323
+ Response.new(successful?(response), message_from(response), response,
324
+ :test => test?,
325
+ :authorization => response[:transaction_id] || parameters[:transaction_id]
326
+ )
327
+ end
328
+
329
+ def successful?(response)
330
+ SUCCESS_CODES.include?(response[:response_code]) || response[:query_status] == true
331
+ end
332
+
333
+ def message_from(response)
334
+ if successful?(response)
335
+ SUCCESS_MESSAGE
336
+ else
337
+ DECLINE_CODES[response[:response_code]] || FAILURE_MESSAGE
333
338
  end
334
- to_submit
335
339
  end
336
-
337
- def commit(action, parameters)
340
+
341
+ def post_data(action, params)
338
342
  if test?
339
343
  # test requests must use global test account
340
- parameters[:logon] = 'pj-ql-01'
341
- parameters[:password] = 'pj-ql-01p'
344
+ params[:logon] = TEST_LOGIN
345
+ params[:password] = TEST_PASSWORD
342
346
  else
343
- parameters[:logon] = @options[:login]
344
- parameters[:password] = @options[:password]
347
+ params[:logon] = @options[:login]
348
+ params[:password] = @options[:password]
345
349
  end
346
- parameters[:version] = API_VERSION
347
- parameters[:transaction_type] = action
350
+ params[:version] = API_VERSION
351
+ params[:transaction_type] = action
348
352
 
349
- submission = clean_and_stringify_params(parameters)
350
-
351
- if result = test_result_from_cc_number(parameters[:number])
352
- return result
353
- end
354
-
355
- post_args = submission.collect { |key, value| "dc_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
356
- headers = {'Content-type' => 'application/x-www-form-urlencoded '}
357
-
358
- data = ssl_post(LIVE_URL, post_args, headers) # execute transaction
359
- @response = parse(data)
360
-
361
- unless action == 'update'
362
- success = SUCCESS_CODES.include?(@response[:response_code])
363
- message = @response[:response_message]
364
- authorization = @response[:transaction_id]
365
- else
366
- success = @response[:query_status] == true
367
- message = 'Transaction update request.' # no message returned with this trans. type
368
- authorization = parameters[:transaction_id] # maintain trans ID since it isn't returned
369
- end
370
-
371
- Response.new(success, message, @response,
372
- :test => test?,
373
- :authorization => authorization
374
- )
353
+ params.reject{|k,v| v.blank?}.collect{ |k, v| "dc_#{k.to_s}=#{CGI.escape(v.to_s)}" }.join("&")
375
354
  end
376
355
 
377
356
  def parse(body)
@@ -0,0 +1,120 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaySecureGateway < Gateway
4
+ URL = 'https://clearance.commsecure.com.au/cgi-bin/PSDirect'
5
+
6
+ self.money_format = :cents
7
+
8
+ # Currently Authorization and Capture is not implemented because
9
+ # capturing requires the original credit card information
10
+ TRANSACTIONS = {
11
+ :purchase => 'PURCHASE',
12
+ :authorization => 'AUTHORISE',
13
+ :capture => 'ADVICE',
14
+ :credit => 'REFUND'
15
+ }
16
+
17
+ SUCCESS = 'Accepted'
18
+ SUCCESS_MESSAGE = 'The transaction was approved'
19
+
20
+ self.supported_countries = ['AU']
21
+ self.homepage_url = 'http://www.commsecure.com.au/paysecure.shtml'
22
+ self.display_name = 'PaySecure'
23
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
24
+
25
+ def initialize(options = {})
26
+ requires!(options, :login, :password)
27
+ @options = options
28
+ super
29
+ end
30
+
31
+ def purchase(money, credit_card, options = {})
32
+ requires!(options, :order_id)
33
+
34
+ post = {}
35
+ add_amount(post, money)
36
+ add_invoice(post, options)
37
+ add_credit_card(post, credit_card)
38
+
39
+ commit(:purchase, money, post)
40
+ end
41
+
42
+ private
43
+ # Used for capturing, which is currently not supported.
44
+ def add_reference(post, identification)
45
+ auth, trans_id = identification.split(";")
46
+ post[:authnum] = auth
47
+ post[:transid] = trans_id
48
+ end
49
+
50
+ def add_amount(post, money)
51
+ post[:amount] = amount(money)
52
+ end
53
+
54
+ def add_invoice(post, options)
55
+ post[:merchant_transid] = options[:order_id].to_s.slice(0,21)
56
+ post[:memnum] = options[:invoice]
57
+ post[:custnum] = options[:customer]
58
+ post[:clientdata] = options[:description]
59
+ end
60
+
61
+ def add_credit_card(post, credit_card)
62
+ post[:cardnum] = credit_card.number
63
+ post[:cardname] = credit_card.name
64
+ post[:expiry] = expdate(credit_card)
65
+ post[:cvv2] = credit_card.verification_value
66
+ end
67
+
68
+ def expdate(credit_card)
69
+ year = sprintf("%.4i", credit_card.year)
70
+ month = sprintf("%.2i", credit_card.month)
71
+
72
+ "#{month}#{year[-2..-1]}"
73
+ end
74
+
75
+ def commit(action, money, parameters)
76
+ response = parse( ssl_post(URL, post_data(action, parameters)) )
77
+
78
+ Response.new(successful?(response), message_from(response), response,
79
+ :test => test_response?(response),
80
+ :authorization => authorization_from(response)
81
+ )
82
+
83
+ end
84
+
85
+ def successful?(response)
86
+ response[:status] == SUCCESS
87
+ end
88
+
89
+ def authorization_from(response)
90
+ [ response[:authnum], response[:transid] ].compact.join(";")
91
+ end
92
+
93
+ def test_response?(response)
94
+ !!(response[:transid] =~ /SimProxy/)
95
+ end
96
+
97
+ def message_from(response)
98
+ successful?(response) ? SUCCESS_MESSAGE : response[:errorstring]
99
+ end
100
+
101
+ def parse(body)
102
+ response = {}
103
+ body.collect do |l|
104
+ key, value = l.split(":", 2)
105
+ response[key.to_s.downcase.to_sym] = value.strip
106
+ end
107
+ response
108
+ end
109
+
110
+ def post_data(action, parameters = {})
111
+ parameters[:request_type] = TRANSACTIONS[action]
112
+ parameters[:merchant_id] = @options[:login]
113
+ parameters[:password] = @options[:password]
114
+
115
+ parameters.reject{|k,v| v.blank?}.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&")
116
+ end
117
+ end
118
+ end
119
+ end
120
+