activemerchant 1.56.0 → 1.66.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +331 -0
  3. data/README.md +9 -9
  4. data/lib/active_merchant/billing/check.rb +3 -0
  5. data/lib/active_merchant/billing/credit_card.rb +8 -3
  6. data/lib/active_merchant/billing/credit_card_methods.rb +41 -1
  7. data/lib/active_merchant/billing/gateway.rb +14 -6
  8. data/lib/active_merchant/billing/gateways/adyen.rb +228 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +157 -44
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +7 -4
  11. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +283 -0
  12. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +68 -2
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +2 -2
  14. data/lib/active_merchant/billing/gateways/blue_snap.rb +348 -0
  15. data/lib/active_merchant/billing/gateways/bpoint.rb +1 -1
  16. data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -20
  17. data/lib/active_merchant/billing/gateways/bridge_pay.rb +37 -8
  18. data/lib/active_merchant/billing/gateways/card_stream.rb +161 -40
  19. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -0
  20. data/lib/active_merchant/billing/gateways/checkout_v2.rb +5 -2
  21. data/lib/active_merchant/billing/gateways/citrus_pay.rb +24 -0
  22. data/lib/active_merchant/billing/gateways/clearhaus.rb +24 -40
  23. data/lib/active_merchant/billing/gateways/conekta.rb +6 -1
  24. data/lib/active_merchant/billing/gateways/creditcall.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/credorax.rb +310 -0
  26. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  27. data/lib/active_merchant/billing/gateways/cyber_source.rb +80 -64
  28. data/lib/active_merchant/billing/gateways/data_cash.rb +10 -304
  29. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  30. data/lib/active_merchant/billing/gateways/elavon.rb +40 -26
  31. data/lib/active_merchant/billing/gateways/element.rb +356 -0
  32. data/lib/active_merchant/billing/gateways/fat_zebra.rb +16 -2
  33. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -1
  34. data/lib/active_merchant/billing/gateways/forte.rb +10 -2
  35. data/lib/active_merchant/billing/gateways/global_collect.rb +311 -0
  36. data/lib/active_merchant/billing/gateways/global_transport.rb +1 -0
  37. data/lib/active_merchant/billing/gateways/iats_payments.rb +13 -0
  38. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  39. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  40. data/lib/active_merchant/billing/gateways/jetpay.rb +33 -19
  41. data/lib/active_merchant/billing/gateways/kushki.rb +217 -0
  42. data/lib/active_merchant/billing/gateways/latitude19.rb +416 -0
  43. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -0
  44. data/lib/active_merchant/billing/gateways/litle.rb +29 -13
  45. data/lib/active_merchant/billing/gateways/mastercard.rb +268 -0
  46. data/lib/active_merchant/billing/gateways/maxipago.rb +145 -122
  47. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +15 -1
  48. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +10 -7
  49. data/lib/active_merchant/billing/gateways/mercury.rb +13 -5
  50. data/lib/active_merchant/billing/gateways/metrics_global.rb +1 -1
  51. data/lib/active_merchant/billing/gateways/migs.rb +23 -1
  52. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  53. data/lib/active_merchant/billing/gateways/moneris.rb +21 -1
  54. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -0
  55. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
  56. data/lib/active_merchant/billing/gateways/netbanx.rb +245 -0
  57. data/lib/active_merchant/billing/gateways/nmi.rb +30 -9
  58. data/lib/active_merchant/billing/gateways/omise.rb +9 -5
  59. data/lib/active_merchant/billing/gateways/openpay.rb +10 -1
  60. data/lib/active_merchant/billing/gateways/opp.rb +362 -0
  61. data/lib/active_merchant/billing/gateways/orbital.rb +28 -7
  62. data/lib/active_merchant/billing/gateways/pagarme.rb +248 -0
  63. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
  64. data/lib/active_merchant/billing/gateways/payeezy.rb +61 -12
  65. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  66. data/lib/active_merchant/billing/gateways/payflow.rb +6 -0
  67. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  68. data/lib/active_merchant/billing/gateways/paymill.rb +29 -11
  69. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  70. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -6
  71. data/lib/active_merchant/billing/gateways/payu_in.rb +3 -2
  72. data/lib/active_merchant/billing/gateways/payu_latam.rb +402 -0
  73. data/lib/active_merchant/billing/gateways/pin.rb +6 -3
  74. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  75. data/lib/active_merchant/billing/gateways/psl_card.rb +3 -3
  76. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +1 -1
  77. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +0 -2
  78. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -1
  79. data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
  80. data/lib/active_merchant/billing/gateways/qvalent.rb +44 -1
  81. data/lib/active_merchant/billing/gateways/redsys.rb +3 -0
  82. data/lib/active_merchant/billing/gateways/s5.rb +8 -5
  83. data/lib/active_merchant/billing/gateways/safe_charge.rb +220 -0
  84. data/lib/active_merchant/billing/gateways/sage.rb +397 -128
  85. data/lib/active_merchant/billing/gateways/sage_pay.rb +45 -20
  86. data/lib/active_merchant/billing/gateways/secure_net.rb +0 -5
  87. data/lib/active_merchant/billing/gateways/secure_pay.rb +1 -1
  88. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -0
  89. data/lib/active_merchant/billing/gateways/securion_pay.rb +46 -17
  90. data/lib/active_merchant/billing/gateways/stripe.rb +125 -29
  91. data/lib/active_merchant/billing/gateways/telr.rb +275 -0
  92. data/lib/active_merchant/billing/gateways/tns.rb +13 -222
  93. data/lib/active_merchant/billing/gateways/trans_first.rb +40 -16
  94. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +606 -0
  95. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
  96. data/lib/active_merchant/billing/gateways/vanco.rb +14 -10
  97. data/lib/active_merchant/billing/gateways/visanet_peru.rb +209 -0
  98. data/lib/active_merchant/billing/gateways/wepay.rb +73 -38
  99. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -0
  100. data/lib/active_merchant/billing/gateways/world_net.rb +344 -0
  101. data/lib/active_merchant/billing/gateways/worldpay.rb +48 -16
  102. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -0
  103. data/lib/active_merchant/country.rb +6 -4
  104. data/lib/active_merchant/posts_data.rb +1 -1
  105. data/lib/active_merchant/version.rb +1 -1
  106. metadata +32 -13
  107. data/lib/active_merchant/billing/gateways/app55.rb +0 -176
  108. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
  109. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -278
  110. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -89
  111. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -115
  112. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +0 -149
  113. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -97
@@ -0,0 +1,348 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant
4
+ module Billing
5
+ class BlueSnapGateway < Gateway
6
+ self.test_url = "https://sandbox.bluesnap.com/services/2"
7
+ self.live_url = "https://ws.bluesnap.com/services/2"
8
+ self.supported_countries = %w(US CA GB AT BE BG HR CY CZ DK EE FI FR DE GR HU IE IT LV LT LU MT NL PL PT RO SK SI ES SE)
9
+
10
+ self.default_currency = 'USD'
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
12
+
13
+ self.homepage_url = 'https://home.bluesnap.com/'
14
+ self.display_name = 'BlueSnap'
15
+
16
+ TRANSACTIONS = {
17
+ purchase: "AUTH_CAPTURE",
18
+ authorize: "AUTH_ONLY",
19
+ capture: "CAPTURE",
20
+ void: "AUTH_REVERSAL",
21
+ refund: "REFUND"
22
+ }
23
+
24
+ CVC_CODE_TRANSLATOR = {
25
+ 'MA' => 'M',
26
+ 'NC' => 'U',
27
+ 'ND' => 'P',
28
+ 'NM' => 'N',
29
+ 'NP' => 'S'
30
+ }
31
+
32
+ AVS_CODE_TRANSLATOR = {
33
+ 'line1: U, zip: U, name: U' => 'I',
34
+ 'line1: U, zip: U, name: M' => 'I',
35
+ 'line1: U, zip: U, name: N' => 'I',
36
+ 'line1: U, zip: M, name: U' => 'P',
37
+ 'line1: U, zip: M, name: M' => 'P',
38
+ 'line1: U, zip: M, name: N' => 'F',
39
+ 'line1: U, zip: N, name: U' => 'O',
40
+ 'line1: U, zip: N, name: M' => 'O',
41
+ 'line1: U, zip: N, name: N' => 'O',
42
+ 'line1: M, zip: U, name: U' => 'B',
43
+ 'line1: M, zip: U, name: M' => 'B',
44
+ 'line1: M, zip: U, name: N' => 'T',
45
+ 'line1: M, zip: M, name: U' => 'M',
46
+ 'line1: M, zip: M, name: M' => 'V',
47
+ 'line1: M, zip: M, name: N' => 'H',
48
+ 'line1: M, zip: N, name: U' => 'A',
49
+ 'line1: M, zip: N, name: M' => 'O',
50
+ 'line1: M, zip: N, name: N' => 'A',
51
+ 'line1: N, zip: U, name: U' => 'C',
52
+ 'line1: N, zip: U, name: M' => 'C',
53
+ 'line1: N, zip: U, name: N' => 'C',
54
+ 'line1: N, zip: M, name: U' => 'W',
55
+ 'line1: N, zip: M, name: M' => 'L',
56
+ 'line1: N, zip: M, name: N' => 'W',
57
+ 'line1: N, zip: N, name: U' => 'N',
58
+ 'line1: N, zip: N, name: M' => 'K',
59
+ 'line1: N, zip: N, name: N' => 'N',
60
+ }
61
+
62
+ def initialize(options={})
63
+ requires!(options, :api_username, :api_password)
64
+ super
65
+ end
66
+
67
+ def purchase(money, payment_method, options={})
68
+ commit(:purchase) do |doc|
69
+ add_auth_purchase(doc, money, payment_method, options)
70
+ end
71
+ end
72
+
73
+ def authorize(money, payment_method, options={})
74
+ commit(:authorize) do |doc|
75
+ add_auth_purchase(doc, money, payment_method, options)
76
+ end
77
+ end
78
+
79
+ def capture(money, authorization, options={})
80
+ commit(:capture, :put) do |doc|
81
+ add_authorization(doc, authorization)
82
+ add_order(doc, options)
83
+ end
84
+ end
85
+
86
+ def refund(money, authorization, options={})
87
+ commit(:refund, :put) do |doc|
88
+ add_authorization(doc, authorization)
89
+ add_amount(doc, money)
90
+ add_order(doc, options)
91
+ end
92
+ end
93
+
94
+ def void(authorization, options={})
95
+ commit(:void, :put) do |doc|
96
+ add_authorization(doc, authorization)
97
+ add_order(doc, options)
98
+ end
99
+ end
100
+
101
+ def verify(payment_method, options={})
102
+ authorize(0, payment_method, options)
103
+ end
104
+
105
+ def store(credit_card, options = {})
106
+ commit(:store) do |doc|
107
+ add_personal_info(doc, credit_card, options)
108
+ doc.send("payment-sources") do
109
+ doc.send("credit-card-info") do
110
+ add_credit_card(doc, credit_card)
111
+ end
112
+ end
113
+ add_order(doc, options)
114
+ end
115
+ end
116
+
117
+ def verify_credentials
118
+ begin
119
+ ssl_get("#{url}/nonexistent", headers)
120
+ rescue ResponseError => e
121
+ return false if e.response.code.to_i == 401
122
+ end
123
+
124
+ true
125
+ end
126
+
127
+ def supports_scrubbing?
128
+ true
129
+ end
130
+
131
+ def scrub(transcript)
132
+ transcript.
133
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
134
+ gsub(%r((<card-number>).+(</card-number>)), '\1[FILTERED]\2').
135
+ gsub(%r((<security-code>).+(</security-code>)), '\1[FILTERED]\2')
136
+ end
137
+
138
+ private
139
+
140
+ def add_auth_purchase(doc, money, payment_method, options)
141
+ doc.send("recurring-transaction", options[:recurring] ? "RECURRING" : "ECOMMERCE")
142
+ add_order(doc, options)
143
+ add_amount(doc, money)
144
+ doc.send("transaction-fraud-info") do
145
+ doc.send("shopper-ip-address", options[:ip]) if options[:ip]
146
+ end
147
+
148
+ if payment_method.is_a?(String)
149
+ doc.send("vaulted-shopper-id", payment_method)
150
+ else
151
+ doc.send("card-holder-info") do
152
+ add_personal_info(doc, payment_method, options)
153
+ end
154
+ add_credit_card(doc, payment_method)
155
+ end
156
+ end
157
+
158
+ def add_amount(doc, money)
159
+ doc.amount(amount(money))
160
+ doc.currency(options[:currency] || currency(money))
161
+ end
162
+
163
+ def add_personal_info(doc, credit_card, options)
164
+ doc.send("first-name", credit_card.first_name)
165
+ doc.send("last-name", credit_card.last_name)
166
+ doc.email(options[:email]) if options[:email]
167
+ add_address(doc, options)
168
+ end
169
+
170
+ def add_credit_card(doc, card)
171
+ doc.send("credit-card") do
172
+ doc.send("card-number", card.number)
173
+ doc.send("security-code", card.verification_value)
174
+ doc.send("expiration-month", card.month)
175
+ doc.send("expiration-year", card.year)
176
+ end
177
+ end
178
+
179
+ def add_description(doc, description)
180
+ doc.send("transaction-meta-data") do
181
+ doc.send("meta-data") do
182
+ doc.send("meta-key", "description")
183
+ doc.send("meta-value", truncate(description, 500))
184
+ doc.send("meta-description", "Description")
185
+ end
186
+ end
187
+ end
188
+
189
+ def add_order(doc, options)
190
+ doc.send("merchant-transaction-id", truncate(options[:order_id], 50)) if options[:order_id]
191
+ doc.send("soft-descriptor", options[:soft_descriptor]) if options[:soft_descriptor]
192
+ add_description(doc, options[:description]) if options[:description]
193
+ end
194
+
195
+ def add_address(doc, options)
196
+ address = options[:billing_address]
197
+ return unless address
198
+
199
+ doc.country(address[:country]) if address[:country]
200
+ doc.state(address[:state]) if address[:state]
201
+ doc.address(address[:address]) if address[:address]
202
+ doc.city(address[:city]) if address[:city]
203
+ doc.zip(address[:zip]) if address[:zip]
204
+ end
205
+
206
+ def add_invoice(post, money, options)
207
+ post[:amount] = amount(money)
208
+ post[:currency] = (options[:currency] || currency(money))
209
+ end
210
+
211
+ def add_authorization(doc, authorization)
212
+ doc.send("transaction-id", authorization)
213
+ end
214
+
215
+ def parse(response)
216
+ return bad_authentication_response if response.code.to_i == 401
217
+
218
+ parsed = {}
219
+ doc = Nokogiri::XML(response.body)
220
+ doc.root.xpath('*').each do |node|
221
+ if (node.elements.empty?)
222
+ parsed[node.name.downcase] = node.text
223
+ else
224
+ node.elements.each do |childnode|
225
+ parse_element(parsed, childnode)
226
+ end
227
+ end
228
+ end
229
+
230
+ parsed["content-location-header"] = response['content-location']
231
+ parsed
232
+ end
233
+
234
+ def parse_element(parsed, node)
235
+ if !node.elements.empty?
236
+ node.elements.each {|e| parse_element(parsed, e) }
237
+ else
238
+ parsed[node.name.downcase] = node.text
239
+ end
240
+ end
241
+
242
+ def api_request(action, request, verb)
243
+ begin
244
+ ssl_request(verb, url(action), request, headers)
245
+ rescue ResponseError => e
246
+ e.response
247
+ end
248
+ end
249
+
250
+ def commit(action, verb = :post)
251
+ request = build_xml_request(action) { |doc| yield(doc) }
252
+ response = api_request(action, request, verb)
253
+ parsed = parse(response)
254
+
255
+ succeeded = success_from(action, response)
256
+ Response.new(
257
+ succeeded,
258
+ message_from(succeeded, parsed),
259
+ parsed,
260
+ authorization: authorization_from(action, parsed),
261
+ avs_result: avs_result(parsed),
262
+ cvv_result: cvv_result(parsed),
263
+ error_code: error_code_from(parsed),
264
+ test: test?,
265
+ )
266
+ end
267
+
268
+ def url(action = nil)
269
+ base = test? ? test_url : live_url
270
+ resource = (action == :store) ? "vaulted-shoppers" : "transactions"
271
+ "#{base}/#{resource}"
272
+ end
273
+
274
+ def cvv_result(parsed)
275
+ CVVResult.new(CVC_CODE_TRANSLATOR[parsed["cvv-response-code"]])
276
+ end
277
+
278
+ def avs_result(parsed)
279
+ AVSResult.new(code: AVS_CODE_TRANSLATOR[avs_lookup_key(parsed)])
280
+ end
281
+
282
+ def avs_lookup_key(p)
283
+ "line1: #{p['avs-response-code-address']}, zip: #{p['avs-response-code-zip']}, name: #{p['avs-response-code-name']}"
284
+ end
285
+
286
+ def success_from(action, response)
287
+ (200...300).include?(response.code.to_i)
288
+ end
289
+
290
+ def message_from(succeeded, parsed_response)
291
+ return "Success" if succeeded
292
+ parsed_response["description"]
293
+ end
294
+
295
+ def authorization_from(action, parsed_response)
296
+ (action == :store) ? vaulted_shopper_id(parsed_response) : parsed_response["transaction-id"]
297
+ end
298
+
299
+ def vaulted_shopper_id(parsed_response)
300
+ return nil unless parsed_response["content-location-header"]
301
+ parsed_response["content-location-header"].split("/").last
302
+ end
303
+
304
+ def error_code_from(parsed_response)
305
+ parsed_response["code"]
306
+ end
307
+
308
+ def root_attributes
309
+ {
310
+ xmlns: "http://ws.plimus.com"
311
+ }
312
+ end
313
+
314
+ def root_element(action)
315
+ (action == :store) ? "vaulted-shopper" : "card-transaction"
316
+ end
317
+
318
+ def headers
319
+ {
320
+ 'Content-Type' => 'application/xml',
321
+ 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:api_username]}:#{@options[:api_password]}").strip),
322
+ }
323
+ end
324
+
325
+ def build_xml_request(action)
326
+ builder = Nokogiri::XML::Builder.new
327
+ builder.__send__(root_element(action), root_attributes) do |doc|
328
+ doc.send("card-transaction-type", TRANSACTIONS[action]) if TRANSACTIONS[action]
329
+ yield(doc)
330
+ end
331
+ builder.doc.root.to_xml
332
+ end
333
+
334
+ def handle_response(response)
335
+ case response.code.to_i
336
+ when 200...300
337
+ response
338
+ else
339
+ raise ResponseError.new(response)
340
+ end
341
+ end
342
+
343
+ def bad_authentication_response
344
+ { "description" => "Unable to authenticate. Please check your credentials." }
345
+ end
346
+ end
347
+ end
348
+ end
@@ -252,7 +252,7 @@ module ActiveMerchant #:nodoc:
252
252
  end
253
253
 
254
254
  def message
255
- params[:ProcessPaymentResult_AuthorisationResult]
255
+ params[:ProcessPaymentResult_AuthorisationResult] || params[:response_ResponseMessage]
256
256
  end
257
257
  end
258
258
 
@@ -6,7 +6,9 @@ rescue LoadError
6
6
  raise "Could not load the braintree gem. Use `gem install braintree` to install it."
7
7
  end
8
8
 
9
- raise "Need braintree gem 2.x.y. Run `gem install braintree --version '~>2.0'` to get the correct version." unless Braintree::Version::Major == 2
9
+ unless Braintree::Version::Major == 2 && Braintree::Version::Minor >= 4
10
+ raise "Need braintree gem >= 2.4.0. Run `gem install braintree --version '~>2.4'` to get the correct version."
11
+ end
10
12
 
11
13
  module ActiveMerchant #:nodoc:
12
14
  module Billing #:nodoc:
@@ -40,6 +42,10 @@ module ActiveMerchant #:nodoc:
40
42
 
41
43
  self.display_name = 'Braintree (Blue Platform)'
42
44
 
45
+ ERROR_CODES = {
46
+ cannot_refund_if_unsettled: 91506
47
+ }
48
+
43
49
  def initialize(options = {})
44
50
  requires!(options, :merchant_id, :public_key, :private_key)
45
51
  @merchant_account_id = options[:merchant_account_id]
@@ -88,11 +94,15 @@ module ActiveMerchant #:nodoc:
88
94
  def refund(*args)
89
95
  # legacy signature: #refund(transaction_id, options = {})
90
96
  # new signature: #refund(money, transaction_id, options = {})
91
- money, transaction_id, _ = extract_refund_args(args)
97
+ money, transaction_id, options = extract_refund_args(args)
92
98
  money = amount(money).to_s if money
93
99
 
94
100
  commit do
95
- response_from_result(@braintree_gateway.transaction.refund(transaction_id, money))
101
+ response = response_from_result(@braintree_gateway.transaction.refund(transaction_id, money))
102
+ return response if response.success?
103
+ return response unless options[:force_full_refund_if_unsettled]
104
+
105
+ void(transaction_id) if response.message =~ /#{ERROR_CODES[:cannot_refund_if_unsettled]}/
96
106
  end
97
107
  end
98
108
 
@@ -173,6 +183,18 @@ module ActiveMerchant #:nodoc:
173
183
  true
174
184
  end
175
185
 
186
+ def verify_credentials
187
+ begin
188
+ @braintree_gateway.transaction.find("non_existent_token")
189
+ rescue Braintree::AuthenticationError
190
+ return false
191
+ rescue Braintree::NotFoundError
192
+ return true
193
+ end
194
+
195
+ true
196
+ end
197
+
176
198
  private
177
199
 
178
200
  def check_customer_exists(customer_vault_id)
@@ -311,17 +333,19 @@ module ActiveMerchant #:nodoc:
311
333
  def message_from_result(result)
312
334
  if result.success?
313
335
  "OK"
314
- elsif result.errors.size == 0 && result.credit_card_verification
336
+ elsif result.errors.any?
337
+ result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
338
+ elsif result.credit_card_verification
315
339
  "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
316
340
  else
317
- result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
341
+ result.message.to_s
318
342
  end
319
343
  end
320
344
 
321
345
  def response_from_result(result)
322
346
  Response.new(result.success?, message_from_result(result),
323
347
  { braintree_transaction: transaction_hash(result) },
324
- { authorization: (result.transaction.id if result.success?) }
348
+ { authorization: (result.transaction.id if result.transaction) }
325
349
  )
326
350
  end
327
351
 
@@ -334,10 +358,8 @@ module ActiveMerchant #:nodoc:
334
358
 
335
359
  def response_options(result)
336
360
  options = {}
337
- if result.success?
338
- options[:authorization] = result.transaction.id
339
- end
340
361
  if result.transaction
362
+ options[:authorization] = result.transaction.id
341
363
  options[:avs_result] = { code: avs_code_from(result.transaction) }
342
364
  options[:cvv_result] = result.transaction.cvv_response_code
343
365
  end
@@ -554,30 +576,46 @@ module ActiveMerchant #:nodoc:
554
576
  :last_name => credit_card_or_vault_id.last_name
555
577
  )
556
578
  if credit_card_or_vault_id.is_a?(NetworkTokenizationCreditCard)
557
- parameters[:apple_pay_card] = {
558
- :number => credit_card_or_vault_id.number,
559
- :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
560
- :expiration_year => credit_card_or_vault_id.year.to_s,
561
- :cardholder_name => "#{credit_card_or_vault_id.first_name} #{credit_card_or_vault_id.last_name}",
562
- :cryptogram => credit_card_or_vault_id.payment_cryptogram
563
- }
579
+ if credit_card_or_vault_id.source == :apple_pay
580
+ parameters[:apple_pay_card] = {
581
+ :number => credit_card_or_vault_id.number,
582
+ :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
583
+ :expiration_year => credit_card_or_vault_id.year.to_s,
584
+ :cardholder_name => credit_card_or_vault_id.name,
585
+ :cryptogram => credit_card_or_vault_id.payment_cryptogram
586
+ }
587
+ elsif credit_card_or_vault_id.source == :android_pay
588
+ parameters[:android_pay_card] = {
589
+ :number => credit_card_or_vault_id.number,
590
+ :cryptogram => credit_card_or_vault_id.payment_cryptogram,
591
+ :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
592
+ :expiration_year => credit_card_or_vault_id.year.to_s,
593
+ :google_transaction_id => credit_card_or_vault_id.transaction_id,
594
+ :source_card_type => credit_card_or_vault_id.brand,
595
+ :source_card_last_four => credit_card_or_vault_id.last_digits
596
+ }
597
+ end
564
598
  else
565
599
  parameters[:credit_card] = {
566
600
  :number => credit_card_or_vault_id.number,
567
601
  :cvv => credit_card_or_vault_id.verification_value,
568
602
  :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
569
- :expiration_year => credit_card_or_vault_id.year.to_s
603
+ :expiration_year => credit_card_or_vault_id.year.to_s,
604
+ :cardholder_name => credit_card_or_vault_id.name
570
605
  }
571
606
  end
572
607
  end
573
608
  parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
574
609
  parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
575
- parameters[:channel] = application_id if application_id.present? && application_id != "ActiveMerchant"
576
610
 
577
- if options[:descriptor_name] || options[:descriptor_phone]
611
+ channel = @options[:channel] || application_id
612
+ parameters[:channel] = channel if channel
613
+
614
+ if options[:descriptor_name] || options[:descriptor_phone] || options[:descriptor_url]
578
615
  parameters[:descriptor] = {
579
616
  name: options[:descriptor_name],
580
- phone: options[:descriptor_phone]
617
+ phone: options[:descriptor_phone],
618
+ url: options[:descriptor_url]
581
619
  }
582
620
  end
583
621
 
@@ -6,8 +6,8 @@ module ActiveMerchant #:nodoc:
6
6
  self.display_name = "BridgePay"
7
7
  self.homepage_url = "http://www.bridgepaynetwork.com/"
8
8
 
9
- self.test_url = "https://gatewaystage.itstgate.com/SmartPayments/transact.asmx"
10
- self.live_url = "https://gateway.itstgate.com/SmartPayments/transact.asmx"
9
+ self.test_url = "https://gatewaystage.itstgate.com/SmartPayments/transact3.asmx"
10
+ self.live_url = "https://gateway.itstgate.com/SmartPayments/transact3.asmx"
11
11
 
12
12
  self.supported_countries = ["CA", "US"]
13
13
  self.default_currency = "USD"
@@ -75,6 +75,17 @@ module ActiveMerchant #:nodoc:
75
75
  end
76
76
  end
77
77
 
78
+ def store(creditcard, options={})
79
+ post = initialize_required_fields('')
80
+ post[:transaction] = 'Create'
81
+ post[:CardNumber] = creditcard.number
82
+ post[:CustomerPaymentInfoKey] = ''
83
+ post[:token] = ''
84
+ add_payment_method(post, creditcard)
85
+
86
+ commit(post)
87
+ end
88
+
78
89
  def supports_scrubbing?
79
90
  true
80
91
  end
@@ -96,6 +107,8 @@ module ActiveMerchant #:nodoc:
96
107
  post[:ExpDate] = expdate(payment_method)
97
108
  post[:CardNum] = payment_method.number
98
109
  post[:CVNum] = payment_method.verification_value
110
+ elsif payment_method.is_a?(String)
111
+ add_token(post, payment_method)
99
112
  else
100
113
  post[:CheckNum] = payment_method.number
101
114
  post[:TransitNum] = payment_method.routing_number
@@ -105,6 +118,11 @@ module ActiveMerchant #:nodoc:
105
118
  end
106
119
  end
107
120
 
121
+ def add_token(post, payment_method)
122
+ payment_method = payment_method.split("|")
123
+ post[:ExtData] = "<Force>T</Force><CardVault><Transaction>Read</Transaction><CustomerPaymentInfoKey>#{payment_method[1]}</CustomerPaymentInfoKey><Token>#{payment_method[0]}</Token><ExpDate>#{payment_method[2]}</ExpDate></CardVault>"
124
+ end
125
+
108
126
  def initialize_required_fields(transaction_type)
109
127
  post = {}
110
128
  post[:TransType] = transaction_type
@@ -164,9 +182,8 @@ module ActiveMerchant #:nodoc:
164
182
  end
165
183
 
166
184
  def commit(parameters)
167
- url = url(parameters[:TransitNum] ? 'ProcessCheck' : 'ProcessCreditCard')
168
185
  data = post_data(parameters)
169
- raw = parse(ssl_post(url, data))
186
+ raw = parse(ssl_post(url(parameters), data))
170
187
 
171
188
  Response.new(
172
189
  success_from(raw),
@@ -177,9 +194,17 @@ module ActiveMerchant #:nodoc:
177
194
  )
178
195
  end
179
196
 
180
- def url(action)
181
- base = test? ? test_url : live_url
182
- "#{base}/#{action}"
197
+ def url(params)
198
+ if params[:transaction]
199
+ "#{base_url}/ManageCardVault"
200
+ else
201
+ action = params[:TransitNum] ? 'ProcessCheck' : 'ProcessCreditCard'
202
+ "#{base_url}/#{action}"
203
+ end
204
+ end
205
+
206
+ def base_url
207
+ test? ? test_url : live_url
183
208
  end
184
209
 
185
210
  def success_from(response)
@@ -191,7 +216,11 @@ module ActiveMerchant #:nodoc:
191
216
  end
192
217
 
193
218
  def authorization_from(response)
194
- [response[:authcode], response[:pnref]].join("|")
219
+ if response[:token]
220
+ [response[:token], response[:customerpaymentinfokey], response[:expdate]].join("|")
221
+ else
222
+ [response[:authcode], response[:pnref]].join("|")
223
+ end
195
224
  end
196
225
 
197
226
  def split_authorization(authorization)