activemerchant 1.62.0 → 1.79.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +420 -2
  3. data/README.md +1 -2
  4. data/lib/active_merchant/billing/credit_card.rb +13 -14
  5. data/lib/active_merchant/billing/credit_card_methods.rb +3 -1
  6. data/lib/active_merchant/billing/gateway.rb +25 -9
  7. data/lib/active_merchant/billing/gateways/adyen.rb +299 -0
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +168 -56
  9. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +4 -2
  10. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +65 -22
  11. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +87 -7
  12. data/lib/active_merchant/billing/gateways/beanstream.rb +2 -0
  13. data/lib/active_merchant/billing/gateways/blue_snap.rb +3 -8
  14. data/lib/active_merchant/billing/gateways/borgun.rb +10 -10
  15. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +1 -0
  16. data/lib/active_merchant/billing/gateways/braintree_blue.rb +49 -15
  17. data/lib/active_merchant/billing/gateways/card_connect.rb +286 -0
  18. data/lib/active_merchant/billing/gateways/card_stream.rb +97 -2
  19. data/lib/active_merchant/billing/gateways/cardprocess.rb +254 -0
  20. data/lib/active_merchant/billing/gateways/cashnet.rb +14 -2
  21. data/lib/active_merchant/billing/gateways/cenpos.rb +1 -1
  22. data/lib/active_merchant/billing/gateways/checkout.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/checkout_v2.rb +44 -14
  24. data/lib/active_merchant/billing/gateways/citrus_pay.rb +0 -1
  25. data/lib/active_merchant/billing/gateways/clearhaus.rb +0 -2
  26. data/lib/active_merchant/billing/gateways/conekta.rb +4 -4
  27. data/lib/active_merchant/billing/gateways/creditcall.rb +71 -9
  28. data/lib/active_merchant/billing/gateways/credorax.rb +117 -5
  29. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  30. data/lib/active_merchant/billing/gateways/cyber_source.rb +54 -15
  31. data/lib/active_merchant/billing/gateways/data_cash.rb +12 -0
  32. data/lib/active_merchant/billing/gateways/dibs.rb +0 -1
  33. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  34. data/lib/active_merchant/billing/gateways/ebanx.rb +296 -0
  35. data/lib/active_merchant/billing/gateways/elavon.rb +37 -95
  36. data/lib/active_merchant/billing/gateways/element.rb +11 -1
  37. data/lib/active_merchant/billing/gateways/fat_zebra.rb +3 -29
  38. data/lib/active_merchant/billing/gateways/first_pay.rb +12 -10
  39. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +37 -20
  40. data/lib/active_merchant/billing/gateways/forte.rb +0 -1
  41. data/lib/active_merchant/billing/gateways/global_collect.rb +55 -16
  42. data/lib/active_merchant/billing/gateways/global_transport.rb +16 -2
  43. data/lib/active_merchant/billing/gateways/hps.rb +12 -1
  44. data/lib/active_merchant/billing/gateways/iats_payments.rb +2 -2
  45. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  46. data/lib/active_merchant/billing/gateways/jetpay.rb +12 -9
  47. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +437 -0
  48. data/lib/active_merchant/billing/gateways/kushki.rb +227 -0
  49. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -2
  50. data/lib/active_merchant/billing/gateways/litle.rb +107 -30
  51. data/lib/active_merchant/billing/gateways/mercado_pago.rb +262 -0
  52. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +11 -0
  53. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +16 -4
  54. data/lib/active_merchant/billing/gateways/mercury.rb +14 -1
  55. data/lib/active_merchant/billing/gateways/migs.rb +28 -6
  56. data/lib/active_merchant/billing/gateways/moneris.rb +20 -12
  57. data/lib/active_merchant/billing/gateways/moneris_us.rb +11 -0
  58. data/lib/active_merchant/billing/gateways/mundipagg.rb +292 -0
  59. data/lib/active_merchant/billing/gateways/nab_transact.rb +4 -4
  60. data/lib/active_merchant/billing/gateways/netbanx.rb +60 -16
  61. data/lib/active_merchant/billing/gateways/netbilling.rb +0 -1
  62. data/lib/active_merchant/billing/gateways/nmi.rb +12 -1
  63. data/lib/active_merchant/billing/gateways/ogone.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/omise.rb +9 -5
  65. data/lib/active_merchant/billing/gateways/openpay.rb +13 -0
  66. data/lib/active_merchant/billing/gateways/opp.rb +124 -114
  67. data/lib/active_merchant/billing/gateways/optimal_payment.rb +14 -1
  68. data/lib/active_merchant/billing/gateways/orbital.rb +83 -14
  69. data/lib/active_merchant/billing/gateways/pay_hub.rb +2 -2
  70. data/lib/active_merchant/billing/gateways/payeezy.rb +152 -46
  71. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -2
  72. data/lib/active_merchant/billing/gateways/payflow.rb +24 -2
  73. data/lib/active_merchant/billing/gateways/payment_express.rb +3 -2
  74. data/lib/active_merchant/billing/gateways/paymentez.rb +276 -0
  75. data/lib/active_merchant/billing/gateways/paymill.rb +18 -10
  76. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +14 -0
  77. data/lib/active_merchant/billing/gateways/paypal.rb +0 -12
  78. data/lib/active_merchant/billing/gateways/paystation.rb +14 -1
  79. data/lib/active_merchant/billing/gateways/payu_latam.rb +102 -62
  80. data/lib/active_merchant/billing/gateways/pin.rb +5 -0
  81. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  82. data/lib/active_merchant/billing/gateways/psigate.rb +12 -1
  83. data/lib/active_merchant/billing/gateways/qbms.rb +11 -0
  84. data/lib/active_merchant/billing/gateways/quickbooks.rb +10 -0
  85. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +21 -17
  86. data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
  87. data/lib/active_merchant/billing/gateways/qvalent.rb +60 -3
  88. data/lib/active_merchant/billing/gateways/realex.rb +16 -6
  89. data/lib/active_merchant/billing/gateways/redsys.rb +8 -2
  90. data/lib/active_merchant/billing/gateways/safe_charge.rb +262 -0
  91. data/lib/active_merchant/billing/gateways/sage.rb +8 -3
  92. data/lib/active_merchant/billing/gateways/sage_pay.rb +29 -13
  93. data/lib/active_merchant/billing/gateways/secure_net.rb +11 -1
  94. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -0
  95. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  96. data/lib/active_merchant/billing/gateways/spreedly_core.rb +53 -7
  97. data/lib/active_merchant/billing/gateways/stripe.rb +84 -26
  98. data/lib/active_merchant/billing/gateways/tns.rb +0 -1
  99. data/lib/active_merchant/billing/gateways/trans_first.rb +3 -2
  100. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +61 -26
  101. data/lib/active_merchant/billing/gateways/trexle.rb +217 -0
  102. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
  103. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +45 -22
  104. data/lib/active_merchant/billing/gateways/vanco.rb +1 -1
  105. data/lib/active_merchant/billing/gateways/wepay.rb +79 -46
  106. data/lib/active_merchant/billing/gateways/wirecard.rb +5 -4
  107. data/lib/active_merchant/billing/gateways/worldpay.rb +85 -20
  108. data/lib/active_merchant/billing/gateways/worldpay_us.rb +27 -8
  109. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  110. data/lib/active_merchant/connection.rb +48 -12
  111. data/lib/active_merchant/net_http_ssl_connection.rb +9 -0
  112. data/lib/active_merchant/network_connection_retries.rb +6 -4
  113. data/lib/active_merchant/posts_data.rb +11 -1
  114. data/lib/active_merchant/version.rb +1 -1
  115. data/lib/active_merchant.rb +2 -5
  116. data/lib/certs/cacert.pem +85 -0
  117. data/lib/support/ssl_version.rb +87 -0
  118. metadata +25 -9
  119. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
@@ -0,0 +1,254 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class CardprocessGateway < Gateway
4
+ self.test_url = 'https://test.vr-pay-ecommerce.de/v1/payments'
5
+ self.live_url = 'https://vr-pay-ecommerce.de/v1/payments'
6
+
7
+ self.supported_countries = %w[ BE BG CZ DK DE EE IE ES FR HR IT CY LV LT LU
8
+ MT HU NL AT PL PT RO SI SK FI SE GB IS LI NO
9
+ CH ME MK AL RS TR BA ]
10
+ self.default_currency = 'EUR'
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
12
+
13
+ self.homepage_url = 'https://vr-pay-ecommerce.docs.oppwa.com/'
14
+ self.display_name = 'CardProcess VR-Pay'
15
+ self.money_format = :dollars
16
+
17
+ STANDARD_ERROR_CODE_MAPPING = {}
18
+
19
+ # Creates a new CardProcess Gateway
20
+ #
21
+ # The gateway requires a valid login, password, and entity ID
22
+ # to be passed in the +options+ hash.
23
+ #
24
+ # === Options
25
+ #
26
+ # * <tt>:user_id</tt> -- The CardProcess user ID
27
+ # * <tt>:password</tt> -- The CardProcess password
28
+ # * <tt>:entity_id</tt> -- The CardProcess channel or entity ID for any transactions
29
+ def initialize(options={})
30
+ requires!(options, :user_id, :password, :entity_id)
31
+ super
32
+ # This variable exists purely to allow remote tests to force error codes;
33
+ # the lack of a setter despite its usage is intentional.
34
+ @test_options = {}
35
+ end
36
+
37
+ def purchase(money, payment, options = {})
38
+ post = {}
39
+ add_invoice(post, money, options)
40
+ add_payment(post, payment)
41
+ add_address(post, payment, options)
42
+ add_customer_data(post, options)
43
+
44
+ commit('DB', post)
45
+ end
46
+
47
+ def authorize(money, payment, options = {})
48
+ post = {}
49
+ add_invoice(post, money, options)
50
+ add_payment(post, payment)
51
+ add_address(post, payment, options)
52
+ add_customer_data(post, options)
53
+
54
+ commit('PA', post)
55
+ end
56
+
57
+ def capture(money, authorization, options = {})
58
+ post = {
59
+ id: authorization
60
+ }
61
+ add_invoice(post, money, options)
62
+ commit('CP', post)
63
+ end
64
+
65
+ def refund(money, authorization, options = {})
66
+ post = {
67
+ id: authorization
68
+ }
69
+ add_invoice(post, money, options)
70
+ commit('RF', post)
71
+ end
72
+
73
+ def credit(money, payment, options = {})
74
+ post = {}
75
+ add_invoice(post, money, options)
76
+ add_payment(post, payment)
77
+ add_address(post, payment, options)
78
+ add_customer_data(post, options)
79
+
80
+ commit('CD', post)
81
+ end
82
+
83
+ def void(authorization, _options = {})
84
+ post = {
85
+ id: authorization
86
+ }
87
+ commit('RV', post)
88
+ end
89
+
90
+ def verify(credit_card, options = {})
91
+ MultiResponse.run do |r|
92
+ r.process { authorize(100, credit_card, options) }
93
+ r.process { void(r.authorization, options) }
94
+ end
95
+ end
96
+
97
+ def supports_scrubbing?
98
+ true
99
+ end
100
+
101
+ def scrub(transcript)
102
+ transcript
103
+ .gsub(%r{(authentication\.[^=]+=)[^&]+}, '\1[FILTERED]')
104
+ .gsub(%r{(card\.number=)\d+}, '\1[FILTERED]')
105
+ .gsub(%r{(cvv=)\d{3,4}}, '\1[FILTERED]\2')
106
+ end
107
+
108
+ private
109
+
110
+ def add_customer_data(post, options)
111
+ post['customer.ip'] = options[:ip] if options[:ip]
112
+ end
113
+
114
+ def add_address(post, _card, options)
115
+ if (address = options[:billing_address] || options[:address])
116
+ post[:billing] = hashify_address(address)
117
+ end
118
+
119
+ if (shipping = options[:shipping_address])
120
+ post[:shipping] = hashify_address(shipping)
121
+ end
122
+ end
123
+
124
+ def add_invoice(post, money, options)
125
+ return if money.nil?
126
+ post[:amount] = amount(money)
127
+ post[:currency] = (options[:currency] || currency(money))
128
+ post[:merchantInvoiceId] = options[:merchant_invoice_id] if options[:merchant_invoice_id]
129
+ post[:merchantTransactionId] = options[:merchant_transaction_id] if options[:merchant_transaction_id]
130
+ post[:transactionCategory] = options[:transaction_category] if options[:transaction_category]
131
+ end
132
+
133
+ def add_payment(post, payment)
134
+ return if payment.is_a?(String)
135
+ post[:paymentBrand] = payment.brand.upcase if payment.brand
136
+ post[:card] ||= {}
137
+ post[:card][:number] = payment.number
138
+ post[:card][:holder] = payment.name
139
+ post[:card][:expiryMonth] = sprintf('%02d', payment.month)
140
+ post[:card][:expiryYear] = sprintf('%02d', payment.year)
141
+ post[:card][:cvv] = payment.verification_value
142
+ end
143
+
144
+ def parse(body)
145
+ JSON.parse(body)
146
+ end
147
+
148
+ def commit(action, parameters)
149
+ url = (test? ? test_url : live_url)
150
+ if (id = parameters.delete(:id))
151
+ url += "/#{id}"
152
+ end
153
+
154
+ begin
155
+ raw_response = ssl_post(url, post_data(action, parameters.merge(@test_options)))
156
+ rescue ResponseError => e
157
+ raw_response = e.response.body
158
+ end
159
+ response = parse(raw_response)
160
+
161
+ Response.new(
162
+ success_from(response),
163
+ message_from(response),
164
+ response,
165
+ authorization: authorization_from(response),
166
+ avs_result: AVSResult.new(code: response['result']['avsResponse']),
167
+ cvv_result: CVVResult.new(response['result']['cvvResponse']),
168
+ test: test?,
169
+ error_code: error_code_from(response)
170
+ )
171
+ end
172
+
173
+ def success_from(response)
174
+ !(response['result']['code'] =~ /^(000\.000\.|000\.100\.1|000\.[36])/).nil?
175
+ end
176
+
177
+ def message_from(response)
178
+ response['result']['description']
179
+ end
180
+
181
+ def authorization_from(response)
182
+ response['id']
183
+ end
184
+
185
+ def post_data(action, parameters = {})
186
+ post = parameters.clone
187
+ post[:authentication] ||= {}
188
+ post[:authentication][:userId] = @options[:user_id]
189
+ post[:authentication][:password] = @options[:password]
190
+ post[:authentication][:entityId] = @options[:entity_id]
191
+ post[:paymentType] = action
192
+ dot_flatten_hash(post).map {|key, value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&")
193
+ end
194
+
195
+ def error_code_from(response)
196
+ unless success_from(response)
197
+ case response['result']['code']
198
+ when '100.100.101'
199
+ STANDARD_ERROR_CODE[:incorrect_number]
200
+ when '100.100.303'
201
+ STANDARD_ERROR_CODE[:expired_card]
202
+ when /100\.100\.(201|301|305)/
203
+ STANDARD_ERROR_CODE[:invalid_expiry_date]
204
+ when /100.100.60[01]/
205
+ STANDARD_ERROR_CODE[:invalid_cvc]
206
+ when '800.100.151'
207
+ STANDARD_ERROR_CODE[:invalid_number]
208
+ when '800.100.153'
209
+ STANDARD_ERROR_CODE[:incorrect_cvc]
210
+ when /800.800.(102|302)/
211
+ STANDARD_ERROR_CODE[:incorrect_address]
212
+ when '800.800.202'
213
+ STANDARD_ERROR_CODE[:invalid_zip]
214
+ when '800.100.166'
215
+ STANDARD_ERROR_CODE[:incorrect_pin]
216
+ when '800.100.171'
217
+ STANDARD_ERROR_CODE[:pickup_card]
218
+ when /^(200|700)\./
219
+ STANDARD_ERROR_CODE[:config_error]
220
+ when /^(800\.[17]00|800\.800\.[123])/
221
+ STANDARD_ERROR_CODE[:card_declined]
222
+ when /^(900\.[1234]00)/
223
+ STANDARD_ERROR_CODE[:processing_error]
224
+ else
225
+ STANDARD_ERROR_CODE[:processing_error]
226
+ end
227
+ end
228
+ end
229
+
230
+ def hashify_address(address)
231
+ hash = {}
232
+ hash[:street1] = address[:address1] if address[:address1]
233
+ hash[:street2] = address[:address2] if address[:address2]
234
+ hash[:city] = address[:city] if address[:city]
235
+ hash[:state] = address[:state] if address[:state]
236
+ hash[:postcode] = address[:zip] if address[:zip]
237
+ hash[:country] = address[:country] if address[:country]
238
+ hash
239
+ end
240
+
241
+ def dot_flatten_hash(hash, prefix = '')
242
+ h = {}
243
+ hash.each_pair do |k, v|
244
+ if v.is_a?(Hash)
245
+ h.merge!(dot_flatten_hash(v, prefix + k.to_s + '.'))
246
+ else
247
+ h[prefix + k.to_s] = v
248
+ end
249
+ end
250
+ h
251
+ end
252
+ end
253
+ end
254
+ end
@@ -3,7 +3,8 @@ module ActiveMerchant #:nodoc:
3
3
  class CashnetGateway < Gateway
4
4
  include Empty
5
5
 
6
- self.live_url = "https://commerce.cashnet.com/"
6
+ self.live_url = "https://commerce.cashnet.com/"
7
+ self.test_url = "https://train.cashnet.com/"
7
8
 
8
9
  self.supported_countries = ["US"]
9
10
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
@@ -54,11 +55,22 @@ module ActiveMerchant #:nodoc:
54
55
  commit('REFUND', money, post)
55
56
  end
56
57
 
58
+ def supports_scrubbing?
59
+ true
60
+ end
61
+
62
+ def scrub(transcript)
63
+ transcript
64
+ .gsub(%r{(password=)[^&]+}, '\1[FILTERED]')
65
+ .gsub(%r{(cardno=)[^&]+}, '\1[FILTERED]')
66
+ .gsub(%r{(cid=)[^&]+}, '\1[FILTERED]')
67
+ end
68
+
57
69
  private
58
70
 
59
71
  def commit(action, money, fields)
60
72
  fields[:amount] = amount(money)
61
- url = live_url + CGI.escape(@options[:merchant_gateway_name])
73
+ url = (test? ? test_url : live_url) + CGI.escape(@options[:merchant_gateway_name])
62
74
  raw_response = ssl_post(url, post_data(action, fields))
63
75
  parsed_response = parse(raw_response)
64
76
 
@@ -180,7 +180,7 @@ module ActiveMerchant #:nodoc:
180
180
 
181
181
  def headers
182
182
  {
183
- "Accept-Encoding" => "gzip,deflate",
183
+ "Accept-Encoding" => "identity",
184
184
  "Content-Type" => "text/xml;charset=UTF-8",
185
185
  "SOAPAction" => "http://tempuri.org/Transactional/ProcessCreditCard"
186
186
  }
@@ -5,7 +5,7 @@ module ActiveMerchant #:nodoc:
5
5
  module Billing #:nodoc:
6
6
  class CheckoutGateway < Gateway
7
7
  self.default_currency = 'USD'
8
- self.money_format = :decimals
8
+ self.money_format = :cents
9
9
 
10
10
  self.supported_countries = ['AD', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FO', 'FI', 'FR', 'GB', 'GI', 'GL', 'GR', 'HR', 'HU', 'IE', 'IS', 'IL', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SM', 'SK', 'SJ', 'TR', 'VA']
11
11
  self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
@@ -4,9 +4,9 @@ module ActiveMerchant #:nodoc:
4
4
  self.display_name = "Checkout.com V2 Gateway"
5
5
  self.homepage_url = "https://www.checkout.com/"
6
6
  self.live_url = "https://api2.checkout.com/v2"
7
- self.test_url = "http://sandbox.checkout.com/api2/v2"
7
+ self.test_url = "https://sandbox.checkout.com/api2/v2"
8
8
 
9
- self.supported_countries = ['AD', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FO', 'FI', 'FR', 'GB', 'GI', 'GL', 'GR', 'HR', 'HU', 'IE', 'IS', 'IL', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SM', 'SK', 'SJ', 'TR', 'VA']
9
+ self.supported_countries = ['AD', 'AE', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FO', 'FI', 'FR', 'GB', 'GI', 'GL', 'GR', 'HR', 'HU', 'IE', 'IS', 'IL', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SM', 'SK', 'SJ', 'TR', 'VA']
10
10
  self.default_currency = "USD"
11
11
  self.money_format = :cents
12
12
  self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
@@ -17,10 +17,15 @@ module ActiveMerchant #:nodoc:
17
17
  end
18
18
 
19
19
  def purchase(amount, payment_method, options={})
20
- MultiResponse.run do |r|
20
+ multi = MultiResponse.run do |r|
21
21
  r.process { authorize(amount, payment_method, options) }
22
22
  r.process { capture(amount, r.authorization, options) }
23
23
  end
24
+
25
+ merged_params = multi.responses.map { |r| r.params }.reduce({}, :merge)
26
+ succeeded = success_from(merged_params)
27
+
28
+ response(:purchase, succeeded, merged_params)
24
29
  end
25
30
 
26
31
  def authorize(amount, payment_method, options={})
@@ -29,6 +34,7 @@ module ActiveMerchant #:nodoc:
29
34
  add_invoice(post, amount, options)
30
35
  add_payment_method(post, payment_method)
31
36
  add_customer_data(post, options)
37
+ add_transaction_data(post, options)
32
38
 
33
39
  commit(:authorize, post)
34
40
  end
@@ -75,7 +81,7 @@ module ActiveMerchant #:nodoc:
75
81
  private
76
82
 
77
83
  def add_invoice(post, money, options)
78
- post[:value] = amount(money)
84
+ post[:value] = localized_amount(money, options[:currency])
79
85
  post[:trackId] = options[:order_id]
80
86
  post[:currency] = options[:currency] || currency(money)
81
87
  post[:descriptor] = {}
@@ -94,11 +100,12 @@ module ActiveMerchant #:nodoc:
94
100
 
95
101
  def add_customer_data(post, options)
96
102
  post[:email] = options[:email] || "unspecified@example.com"
103
+ post[:customerIp] = options[:ip] if options[:ip]
97
104
  address = options[:billing_address]
98
105
  if(address && post[:card])
99
106
  post[:card][:billingDetails] = {}
100
- post[:card][:billingDetails][:address1] = address[:address1]
101
- post[:card][:billingDetails][:address2] = address[:address2]
107
+ post[:card][:billingDetails][:addressLine1] = address[:address1]
108
+ post[:card][:billingDetails][:addressLine2] = address[:address2]
102
109
  post[:card][:billingDetails][:city] = address[:city]
103
110
  post[:card][:billingDetails][:state] = address[:state]
104
111
  post[:card][:billingDetails][:country] = address[:country]
@@ -107,6 +114,12 @@ module ActiveMerchant #:nodoc:
107
114
  end
108
115
  end
109
116
 
117
+ def add_transaction_data(post, options={})
118
+ post[:cardOnFile] = true if options[:card_on_file] == true
119
+ post[:transactionIndicator] = options[:transaction_indicator] || 1
120
+ post[:previousChargeId] = options[:previous_charge_id] if options[:previous_charge_id]
121
+ end
122
+
110
123
  def commit(action, post, authorization = nil)
111
124
  begin
112
125
  raw_response = ssl_post(url(post, action, authorization), post.to_json, headers)
@@ -117,6 +130,15 @@ module ActiveMerchant #:nodoc:
117
130
  end
118
131
 
119
132
  succeeded = success_from(response)
133
+
134
+ response(action, succeeded, response)
135
+ end
136
+
137
+ def response(action, succeeded, response)
138
+ successful_response = succeeded && action == :purchase || action == :authorize
139
+ avs_result = successful_response ? avs_result(response) : nil
140
+ cvv_result = successful_response ? cvv_result(response) : nil
141
+
120
142
  Response.new(
121
143
  succeeded,
122
144
  message_from(succeeded, response),
@@ -124,8 +146,9 @@ module ActiveMerchant #:nodoc:
124
146
  authorization: authorization_from(response),
125
147
  error_code: error_code_from(succeeded, response),
126
148
  test: test?,
127
- avs_result: avs_result(action, response),
128
- cvv_result: cvv_result(action, response))
149
+ avs_result: avs_result,
150
+ cvv_result: cvv_result
151
+ )
129
152
  end
130
153
 
131
154
  def headers
@@ -147,12 +170,12 @@ module ActiveMerchant #:nodoc:
147
170
  test? ? test_url : live_url
148
171
  end
149
172
 
150
- def avs_result(action, response)
151
- action == :purchase ? AVSResult.new(code: response["card"]["avsCheck"]) : nil
173
+ def avs_result(response)
174
+ response['card'] && response['card']['avsCheck'] ? AVSResult.new(code: response['card']['avsCheck']) : nil
152
175
  end
153
176
 
154
- def cvv_result(action, response)
155
- action == :purchase ? CVVResult.new(response["card"]["cvvCheck"]) : nil
177
+ def cvv_result(response)
178
+ response['card'] && response['card']['cvvCheck'] ? CVVResult.new(response['card']['cvvCheck']) : nil
156
179
  end
157
180
 
158
181
  def parse(body)
@@ -165,7 +188,7 @@ module ActiveMerchant #:nodoc:
165
188
  end
166
189
 
167
190
  def success_from(response)
168
- response["responseCode"] == ("10000" || "10100")
191
+ (response["responseCode"] == "10000" && !response["responseMessage"].start_with?("40")) || response["responseCode"] == "10100"
169
192
  end
170
193
 
171
194
  def message_from(succeeded, response)
@@ -196,7 +219,14 @@ module ActiveMerchant #:nodoc:
196
219
  end
197
220
 
198
221
  def error_code_from(succeeded, response)
199
- succeeded ? nil : STANDARD_ERROR_CODE_MAPPING[response["responseCode"]]
222
+ return if succeeded
223
+ if response["errorCode"] && response["errorMessageCodes"]
224
+ "#{response["errorCode"]}: #{response["errorMessageCodes"].join(", ")}"
225
+ elsif response["errorCode"]
226
+ response["errorCode"]
227
+ else
228
+ STANDARD_ERROR_CODE_MAPPING[response["responseCode"]]
229
+ end
200
230
  end
201
231
  end
202
232
  end
@@ -16,7 +16,6 @@ module ActiveMerchant
16
16
  self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
17
17
  self.default_currency = 'USD'
18
18
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :laser]
19
- self.ssl_version = :TLSv1
20
19
 
21
20
  end
22
21
  end
@@ -1,5 +1,3 @@
1
- require 'openssl'
2
-
3
1
  module ActiveMerchant #:nodoc:
4
2
  module Billing #:nodoc:
5
3
  class ClearhausGateway < Gateway
@@ -77,21 +77,21 @@ module ActiveMerchant #:nodoc:
77
77
  post[:description] = options[:description] || "Active Merchant Purchase"
78
78
  post[:reference_id] = options[:order_id] if options[:order_id]
79
79
  post[:currency] = (options[:currency] || currency(money)).downcase
80
+ post[:monthly_installments] = options[:monthly_installments] if options[:monthly_installments]
80
81
  post[:amount] = amount(money)
81
82
  end
82
83
 
83
84
  def add_details_data(post, options)
84
85
  details = {}
85
- details[:name] = options[:customer] if options[:customer]
86
+ details[:name] = options[:customer] || (options[:billing_address][:name] if options[:billing_address])
87
+ details[:phone] = options[:phone] || (options[:billing_address][:phone] if options[:billing_address])
86
88
  details[:email] = options[:email] if options[:email]
87
- details[:phone] = options[:phone] if options[:phone]
88
- post[:device_fingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
89
89
  details[:ip] = options[:ip] if options[:ip]
90
90
  add_billing_address(details, options)
91
91
  add_line_items(details, options)
92
92
  add_shipment(details, options)
93
-
94
93
  post[:details] = details
94
+ post[:device_fingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
95
95
  end
96
96
 
97
97
  def add_shipment(post, options)
@@ -14,6 +14,32 @@ module ActiveMerchant #:nodoc:
14
14
 
15
15
  self.homepage_url = 'https://www.creditcall.com'
16
16
  self.display_name = 'Creditcall'
17
+
18
+ CVV_CODE = {
19
+ "matched" => "M",
20
+ "notmatched" => "N",
21
+ "notchecked" => "P",
22
+ "partialmatch" => "N"
23
+ }
24
+
25
+ AVS_CODE = {
26
+ "matched;matched" => "D",
27
+ "matched;notchecked" =>"B",
28
+ "matched;notmatched" => "A",
29
+ "matched;partialmatch" => "A",
30
+ "notchecked;matched" => "P",
31
+ "notchecked;notchecked" =>"I",
32
+ "notchecked;notmatched" => "I",
33
+ "notchecked;partialmatch" => "I",
34
+ "notmatched;matched" => "W",
35
+ "notmatched;notchecked" =>"C",
36
+ "notmatched;notmatched" => "C",
37
+ "notmatched;partialmatch" => "C",
38
+ "partialmatched;matched" => "W",
39
+ "partialmatched;notchecked" =>"C",
40
+ "partialmatched;notmatched" => "C",
41
+ "partialmatched;partialmatch" => "C"
42
+ }
17
43
 
18
44
  def initialize(options={})
19
45
  requires!(options, :terminal_id, :transaction_key)
@@ -26,11 +52,16 @@ module ActiveMerchant #:nodoc:
26
52
  r.process { capture(money, r.authorization, options) }
27
53
  end
28
54
 
55
+ merged_params = multi_response.responses.map { |r| r.params }.reduce({}, :merge)
56
+
29
57
  Response.new(
30
58
  multi_response.primary_response.success?,
31
59
  multi_response.primary_response.message,
32
- multi_response.primary_response.params,
60
+ merged_params,
33
61
  authorization: multi_response.responses.first.authorization,
62
+ avs_result: AVSResult.new(code: avs_result_code_from(merged_params)),
63
+ cvv_result: CVVResult.new(cvv_result_code_from(merged_params)),
64
+ error_code: error_result_code_from(merged_params),
34
65
  test: test?
35
66
  )
36
67
  end
@@ -92,6 +123,18 @@ module ActiveMerchant #:nodoc:
92
123
 
93
124
  private
94
125
 
126
+ def avs_result_code_from(params)
127
+ AVS_CODE["#{params['Address']};#{params['Zip']}"]
128
+ end
129
+
130
+ def cvv_result_code_from(params)
131
+ CVV_CODE[params["CSC"]]
132
+ end
133
+
134
+ def error_result_code_from(params)
135
+ params["ErrorCode"]
136
+ end
137
+
95
138
  def build_xml_request
96
139
  builder = Nokogiri::XML::Builder.new do |xml|
97
140
  xml.Request(type: "CardEaseXML", version: "1.0.0") do
@@ -120,17 +163,22 @@ module ActiveMerchant #:nodoc:
120
163
 
121
164
  def add_card_details(xml, payment_method, options={})
122
165
  xml.CardDetails do
123
- xml.Manual(type: "ecommerce") do
166
+ xml.Manual(type: manual_type(options)) do
124
167
  xml.PAN payment_method.number
125
168
  xml.ExpiryDate exp_date(payment_method)
126
169
  xml.CSC payment_method.verification_value unless empty?(payment_method.verification_value)
127
170
  end
128
171
 
129
- if address = options[:billing_address]
130
- xml.AdditionalVerification do
131
- xml.Address address[:address1]
132
- xml.Zip address[:zip]
133
- end
172
+ add_additional_verification(xml, options)
173
+ end
174
+ end
175
+
176
+ def add_additional_verification(xml, options)
177
+ return unless (options[:verify_zip].to_s == 'true') || (options[:verify_address].to_s == 'true')
178
+ if address = options[:billing_address]
179
+ xml.AdditionalVerification do
180
+ xml.Zip address[:zip] if options[:verify_zip].to_s == 'true'
181
+ xml.Address address[:address1] if options[:verify_address].to_s == 'true'
134
182
  end
135
183
  end
136
184
  end
@@ -157,6 +205,16 @@ module ActiveMerchant #:nodoc:
157
205
  end
158
206
  end
159
207
 
208
+ node = xml.xpath("//Response/CardDetails")
209
+ node.children.each do |childnode|
210
+ if childnode.elements.empty?
211
+ response[childnode.name] = childnode.text
212
+ else
213
+ childnode_to_response(response, childnode)
214
+ end
215
+ end
216
+
217
+
160
218
  response
161
219
  end
162
220
 
@@ -179,8 +237,9 @@ module ActiveMerchant #:nodoc:
179
237
  message_from(response),
180
238
  response,
181
239
  authorization: authorization_from(response),
182
- avs_result: AVSResult.new(code: response["some_avs_response_key"]),
183
- cvv_result: CVVResult.new(response["some_cvv_response_key"]),
240
+ avs_result: AVSResult.new(code: avs_result_code_from(response)),
241
+ cvv_result: CVVResult.new(cvv_result_code_from(response)),
242
+ error_code: error_result_code_from(response),
184
243
  test: test?
185
244
  )
186
245
  end
@@ -205,6 +264,9 @@ module ActiveMerchant #:nodoc:
205
264
  response["CardEaseReference"]
206
265
  end
207
266
 
267
+ def manual_type(options)
268
+ options[:manual_type] ? options[:manual_type] : "ecommerce"
269
+ end
208
270
  end
209
271
  end
210
272
  end