activemerchant 1.95.0 → 1.96.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +45 -0
  3. data/README.md +3 -0
  4. data/lib/active_merchant/billing/avs_result.rb +4 -5
  5. data/lib/active_merchant/billing/credit_card.rb +2 -0
  6. data/lib/active_merchant/billing/credit_card_methods.rb +14 -0
  7. data/lib/active_merchant/billing/gateway.rb +10 -0
  8. data/lib/active_merchant/billing/gateways/adyen.rb +19 -6
  9. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +39 -10
  10. data/lib/active_merchant/billing/gateways/blue_snap.rb +4 -1
  11. data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
  12. data/lib/active_merchant/billing/gateways/braintree_blue.rb +11 -1
  13. data/lib/active_merchant/billing/gateways/card_connect.rb +1 -0
  14. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
  15. data/lib/active_merchant/billing/gateways/checkout_v2.rb +24 -24
  16. data/lib/active_merchant/billing/gateways/credorax.rb +29 -3
  17. data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -2
  18. data/lib/active_merchant/billing/gateways/decidir.rb +232 -0
  19. data/lib/active_merchant/billing/gateways/global_collect.rb +2 -6
  20. data/lib/active_merchant/billing/gateways/hps.rb +46 -1
  21. data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
  22. data/lib/active_merchant/billing/gateways/migs.rb +8 -0
  23. data/lib/active_merchant/billing/gateways/mundipagg.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/nmi.rb +39 -1
  26. data/lib/active_merchant/billing/gateways/opp.rb +20 -1
  27. data/lib/active_merchant/billing/gateways/payflow.rb +40 -2
  28. data/lib/active_merchant/billing/gateways/paypal.rb +14 -1
  29. data/lib/active_merchant/billing/gateways/realex.rb +11 -5
  30. data/lib/active_merchant/billing/gateways/spreedly_core.rb +43 -29
  31. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -2
  32. data/lib/active_merchant/billing/gateways/trust_commerce.rb +24 -5
  33. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -5
  34. data/lib/active_merchant/billing/gateways/worldpay.rb +157 -37
  35. data/lib/active_merchant/country.rb +1 -0
  36. data/lib/active_merchant/version.rb +1 -1
  37. metadata +3 -2
@@ -33,9 +33,9 @@ module ActiveMerchant #:nodoc:
33
33
  '10110' => STANDARD_ERROR_CODE[:incorrect_address],
34
34
  '10111' => STANDARD_ERROR_CODE[:incorrect_address],
35
35
  '10127' => STANDARD_ERROR_CODE[:card_declined],
36
- '10128' => STANDARD_ERROR_CODE[:processing_error],
37
- '10132' => STANDARD_ERROR_CODE[:processing_error],
38
- '00043' => STANDARD_ERROR_CODE[:call_issuer]
36
+ '00043' => STANDARD_ERROR_CODE[:call_issuer],
37
+ '10205' => STANDARD_ERROR_CODE[:card_declined],
38
+ '10204' => STANDARD_ERROR_CODE[:pickup_card]
39
39
  }
40
40
 
41
41
  def initialize(options = {})
@@ -318,12 +318,15 @@ module ActiveMerchant #:nodoc:
318
318
  def commit(action, parameters)
319
319
  url = (test? ? self.test_url : self.live_url)
320
320
  response = parse(ssl_post(url, post_data(action, parameters)))
321
- Response.new(response[:status] == 'Approved', message_from(response), response,
321
+ approved = response[:status] == 'Approved'
322
+ error_code = nil
323
+ error_code = (STANDARD_ERROR_CODE_MAPPING[response[:error_code]] || STANDARD_ERROR_CODE[:processing_error]) unless approved
324
+ Response.new(approved, message_from(response), response,
322
325
  :test => test?,
323
326
  :authorization => response[:ref_num],
324
327
  :cvv_result => response[:cvv2_result_code],
325
328
  :avs_result => { :code => response[:avs_result_code] },
326
- :error_code => STANDARD_ERROR_CODE_MAPPING[response[:error_code]]
329
+ :error_code => error_code
327
330
  )
328
331
  end
329
332
 
@@ -59,10 +59,12 @@ module ActiveMerchant #:nodoc:
59
59
 
60
60
  def authorize(money, payment_method, options = {})
61
61
  requires!(options, :order_id)
62
- authorize_request(money, payment_method, options)
62
+ payment_details = payment_details_from(payment_method)
63
+ authorize_request(money, payment_method, payment_details.merge(options))
63
64
  end
64
65
 
65
66
  def capture(money, authorization, options = {})
67
+ authorization = order_id_from_authorization(authorization.to_s)
66
68
  MultiResponse.run do |r|
67
69
  r.process { inquire_request(authorization, options, 'AUTHORISED') } unless options[:authorization_validated]
68
70
  if r.params
@@ -74,6 +76,7 @@ module ActiveMerchant #:nodoc:
74
76
  end
75
77
 
76
78
  def void(authorization, options = {})
79
+ authorization = order_id_from_authorization(authorization.to_s)
77
80
  MultiResponse.run do |r|
78
81
  r.process { inquire_request(authorization, options, 'AUTHORISED') } unless options[:authorization_validated]
79
82
  r.process { cancel_request(authorization, options) }
@@ -81,6 +84,7 @@ module ActiveMerchant #:nodoc:
81
84
  end
82
85
 
83
86
  def refund(money, authorization, options = {})
87
+ authorization = order_id_from_authorization(authorization.to_s)
84
88
  response = MultiResponse.run do |r|
85
89
  r.process { inquire_request(authorization, options, 'CAPTURED', 'SETTLED', 'SETTLED_BY_MERCHANT') }
86
90
  r.process { refund_request(money, authorization, options) }
@@ -97,16 +101,22 @@ module ActiveMerchant #:nodoc:
97
101
  # and other transactions should be performed on a normal eCom-flagged
98
102
  # merchant ID.
99
103
  def credit(money, payment_method, options = {})
100
- credit_request(money, payment_method, options.merge(:credit => true))
104
+ payment_details = payment_details_from(payment_method)
105
+ credit_request(money, payment_method, payment_details.merge(:credit => true, **options))
101
106
  end
102
107
 
103
- def verify(credit_card, options={})
108
+ def verify(payment_method, options={})
104
109
  MultiResponse.run(:use_first_response) do |r|
105
- r.process { authorize(100, credit_card, options) }
110
+ r.process { authorize(100, payment_method, options) }
106
111
  r.process(:ignore_result) { void(r.authorization, options.merge(:authorization_validated => true)) }
107
112
  end
108
113
  end
109
114
 
115
+ def store(credit_card, options={})
116
+ requires!(options, :customer)
117
+ store_request(credit_card, options)
118
+ end
119
+
110
120
  def supports_scrubbing
111
121
  true
112
122
  end
@@ -144,6 +154,10 @@ module ActiveMerchant #:nodoc:
144
154
  commit('credit', build_authorization_request(money, payment_method, options), :ok, 'SENT_FOR_REFUND', options)
145
155
  end
146
156
 
157
+ def store_request(credit_card, options)
158
+ commit('store', build_store_request(credit_card, options), options)
159
+ end
160
+
147
161
  def build_request
148
162
  xml = Builder::XmlMarkup.new :indent => 2
149
163
  xml.instruct! :xml, :encoding => 'UTF-8'
@@ -184,7 +198,7 @@ module ActiveMerchant #:nodoc:
184
198
  end
185
199
  end
186
200
  add_payment_method(xml, money, payment_method, options)
187
- add_email(xml, options)
201
+ add_shopper(xml, options)
188
202
  if options[:hcg_additional_data]
189
203
  add_hcg_additional_data(xml, options)
190
204
  end
@@ -224,6 +238,22 @@ module ActiveMerchant #:nodoc:
224
238
  end
225
239
  end
226
240
 
241
+ def build_store_request(credit_card, options)
242
+ build_request do |xml|
243
+ xml.tag! 'submit' do
244
+ xml.tag! 'paymentTokenCreate' do
245
+ add_authenticated_shopper_id(xml, options)
246
+ xml.tag! 'createToken'
247
+ xml.tag! 'paymentInstrument' do
248
+ xml.tag! 'cardDetails' do
249
+ add_card(xml, credit_card, options)
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
256
+
227
257
  def add_amount(xml, money, options)
228
258
  currency = options[:currency] || currency(money)
229
259
 
@@ -241,7 +271,7 @@ module ActiveMerchant #:nodoc:
241
271
  end
242
272
 
243
273
  def add_payment_method(xml, amount, payment_method, options)
244
- if payment_method.is_a?(String)
274
+ if options[:payment_type] == :pay_as_order
245
275
  if options[:merchant_code]
246
276
  xml.tag! 'payAsOrder', 'orderCode' => payment_method, 'merchantCode' => options[:merchant_code] do
247
277
  add_amount(xml, amount, options)
@@ -253,16 +283,14 @@ module ActiveMerchant #:nodoc:
253
283
  end
254
284
  else
255
285
  xml.tag! 'paymentDetails', credit_fund_transfer_attribute(options) do
256
- xml.tag! card_code_for(payment_method) do
257
- xml.tag! 'cardNumber', payment_method.number
258
- xml.tag! 'expiryDate' do
259
- xml.tag! 'date', 'month' => format(payment_method.month, :two_digits), 'year' => format(payment_method.year, :four_digits)
286
+ if options[:payment_type] == :token
287
+ xml.tag! 'TOKEN-SSL', 'tokenScope' => options[:token_scope] do
288
+ xml.tag! 'paymentTokenID', options[:token_id]
289
+ end
290
+ else
291
+ xml.tag! card_code_for(payment_method) do
292
+ add_card(xml, payment_method, options)
260
293
  end
261
-
262
- xml.tag! 'cardHolderName', options[:execute_threed] ? '3D' : payment_method.name
263
- xml.tag! 'cvc', payment_method.verification_value
264
-
265
- add_address(xml, (options[:billing_address] || options[:address]))
266
294
  end
267
295
  add_stored_credential_options(xml, options)
268
296
  if options[:ip] && options[:session_id]
@@ -273,18 +301,37 @@ module ActiveMerchant #:nodoc:
273
301
  end
274
302
 
275
303
  if three_d_secure = options[:three_d_secure]
276
- xml.tag! 'info3DSecure' do
277
- xml.tag! 'threeDSVersion', three_d_secure[:version]
278
- xid_tag = three_d_secure[:version] =~ /^2/ ? 'dsTransactionId' : 'xid'
279
- xml.tag! xid_tag, three_d_secure[:xid]
280
- xml.tag! 'cavv', three_d_secure[:cavv]
281
- xml.tag! 'eci', three_d_secure[:eci]
282
- end
304
+ add_three_d_secure(three_d_secure, xml)
283
305
  end
284
306
  end
285
307
  end
286
308
  end
287
309
 
310
+ def add_three_d_secure(three_d_secure, xml)
311
+ xml.tag! 'info3DSecure' do
312
+ xml.tag! 'threeDSVersion', three_d_secure[:version]
313
+ if three_d_secure[:version] =~ /^2/
314
+ xml.tag! 'dsTransactionId', three_d_secure[:ds_transaction_id]
315
+ else
316
+ xml.tag! 'xid', three_d_secure[:xid]
317
+ end
318
+ xml.tag! 'cavv', three_d_secure[:cavv]
319
+ xml.tag! 'eci', three_d_secure[:eci]
320
+ end
321
+ end
322
+
323
+ def add_card(xml, payment_method, options)
324
+ xml.tag! 'cardNumber', payment_method.number
325
+ xml.tag! 'expiryDate' do
326
+ xml.tag! 'date', 'month' => format(payment_method.month, :two_digits), 'year' => format(payment_method.year, :four_digits)
327
+ end
328
+
329
+ xml.tag! 'cardHolderName', options[:execute_threed] ? '3D' : payment_method.name
330
+ xml.tag! 'cvc', payment_method.verification_value
331
+
332
+ add_address(xml, (options[:billing_address] || options[:address]))
333
+ end
334
+
288
335
  def add_stored_credential_options(xml, options={})
289
336
  if options[:stored_credential]
290
337
  add_stored_credential_using_normalized_fields(xml, options)
@@ -321,10 +368,11 @@ module ActiveMerchant #:nodoc:
321
368
  end
322
369
  end
323
370
 
324
- def add_email(xml, options)
325
- return unless options[:execute_threed] || options[:email]
371
+ def add_shopper(xml, options)
372
+ return unless options[:execute_threed] || options[:email] || options[:customer]
326
373
  xml.tag! 'shopper' do
327
374
  xml.tag! 'shopperEmailAddress', options[:email] if options[:email]
375
+ add_authenticated_shopper_id(xml, options)
328
376
  xml.tag! 'browser' do
329
377
  xml.tag! 'acceptHeader', options[:accept_header]
330
378
  xml.tag! 'userAgentHeader', options[:user_agent]
@@ -332,6 +380,10 @@ module ActiveMerchant #:nodoc:
332
380
  end
333
381
  end
334
382
 
383
+ def add_authenticated_shopper_id(xml, options)
384
+ xml.tag!('authenticatedShopperID', options[:customer]) if options[:customer]
385
+ end
386
+
335
387
  def add_address(xml, address)
336
388
  return unless address
337
389
 
@@ -390,14 +442,17 @@ module ActiveMerchant #:nodoc:
390
442
  end
391
443
 
392
444
  def parse_element(raw, node)
445
+ node_name = node.name.underscore
393
446
  node.attributes.each do |k, v|
394
- raw["#{node.name.underscore}_#{k.underscore}".to_sym] = v
447
+ raw["#{node_name}_#{k.underscore}".to_sym] = v
395
448
  end
396
449
  if node.has_elements?
397
- raw[node.name.underscore.to_sym] = true unless node.name.blank?
450
+ raw[node_name.to_sym] = true unless node.name.blank?
398
451
  node.elements.each { |e| parse_element(raw, e) }
452
+ elsif node.children.count > 1
453
+ raw[node_name.to_sym] = node.children.join(' ').strip
399
454
  else
400
- raw[node.name.underscore.to_sym] = node.text unless node.text.nil?
455
+ raw[node_name.to_sym] = node.text unless node.text.nil?
401
456
  end
402
457
  raw
403
458
  end
@@ -420,13 +475,14 @@ module ActiveMerchant #:nodoc:
420
475
  raw[:cookie] = @cookie
421
476
  raw[:session_id] = options[:session_id]
422
477
  end
423
- success, message = success_and_message_from(raw, success_criteria)
478
+ success = success_from(action, raw, success_criteria)
479
+ message = message_from(success, raw, success_criteria)
424
480
 
425
481
  Response.new(
426
482
  success,
427
483
  message,
428
484
  raw,
429
- :authorization => authorization_from(raw),
485
+ :authorization => authorization_from(action, raw, options),
430
486
  :error_code => error_code_from(success, raw),
431
487
  :test => test?,
432
488
  :avs_result => AVSResult.new(code: AVS_CODE_MAP[raw[:avs_result_code_description]]),
@@ -456,19 +512,30 @@ module ActiveMerchant #:nodoc:
456
512
  end
457
513
  end
458
514
 
515
+ def success_from(action, raw, success_criteria)
516
+ success_criteria_success?(raw, success_criteria) || action_success?(action, raw)
517
+ end
518
+
519
+ def message_from(success, raw, success_criteria)
520
+ return 'SUCCESS' if success
521
+ raw[:iso8583_return_code_description] || raw[:error] || required_status_message(raw, success_criteria)
522
+ end
523
+
459
524
  # success_criteria can be:
460
525
  # - a string or an array of strings (if one of many responses)
461
526
  # - An array of strings if one of many responses could be considered a
462
527
  # success.
463
- def success_and_message_from(raw, success_criteria)
464
- success = (success_criteria.include?(raw[:last_event]) || raw[:ok].present?)
465
- if success
466
- message = 'SUCCESS'
528
+ def success_criteria_success?(raw, success_criteria)
529
+ success_criteria.include?(raw[:last_event]) || raw[:ok].present?
530
+ end
531
+
532
+ def action_success?(action, raw)
533
+ case action
534
+ when 'store'
535
+ raw[:token].present?
467
536
  else
468
- message = (raw[:iso8583_return_code_description] || raw[:error] || required_status_message(raw, success_criteria))
537
+ false
469
538
  end
470
-
471
- [ success, message ]
472
539
  end
473
540
 
474
541
  def error_code_from(success, raw)
@@ -483,11 +550,64 @@ module ActiveMerchant #:nodoc:
483
550
  end
484
551
  end
485
552
 
486
- def authorization_from(raw)
553
+ def authorization_from(action, raw, options)
554
+ order_id = order_id_from(raw)
555
+
556
+ case action
557
+ when 'store'
558
+ authorization_from_token_details(
559
+ order_id: order_id,
560
+ token_id: raw[:payment_token_id],
561
+ token_scope: 'shopper',
562
+ customer: options[:customer]
563
+ )
564
+ else
565
+ order_id
566
+ end
567
+ end
568
+
569
+ def order_id_from(raw)
487
570
  pair = raw.detect { |k, v| k.to_s =~ /_order_code$/ }
488
571
  (pair ? pair.last : nil)
489
572
  end
490
573
 
574
+ def authorization_from_token_details(options={})
575
+ [options[:order_id], options[:token_id], options[:token_scope], options[:customer]].join('|')
576
+ end
577
+
578
+ def order_id_from_authorization(authorization)
579
+ token_details_from_authorization(authorization)[:order_id]
580
+ end
581
+
582
+ def token_details_from_authorization(authorization)
583
+ order_id, token_id, token_scope, customer = authorization.split('|')
584
+
585
+ token_details = {}
586
+ token_details[:order_id] = order_id if order_id.present?
587
+ token_details[:token_id] = token_id if token_id.present?
588
+ token_details[:token_scope] = token_scope if token_scope.present?
589
+ token_details[:customer] = customer if customer.present?
590
+
591
+ token_details
592
+ end
593
+
594
+ def payment_details_from(payment_method)
595
+ payment_details = {}
596
+ if payment_method.respond_to?(:number)
597
+ payment_details[:payment_type] = :credit
598
+ else
599
+ token_details = token_details_from_authorization(payment_method)
600
+ payment_details.merge!(token_details)
601
+ if token_details.has_key?(:token_id)
602
+ payment_details[:payment_type] = :token
603
+ else
604
+ payment_details[:payment_type] = :pay_as_order
605
+ end
606
+ end
607
+
608
+ payment_details
609
+ end
610
+
491
611
  def credit_fund_transfer_attribute(options)
492
612
  return unless options[:credit]
493
613
  {'action' => 'REFUND'}
@@ -183,6 +183,7 @@ module ActiveMerchant #:nodoc:
183
183
  { alpha2: 'KI', name: 'Kiribati', alpha3: 'KIR', numeric: '296' },
184
184
  { alpha2: 'KP', name: 'Korea, Democratic People\'s Republic of', alpha3: 'PRK', numeric: '408' },
185
185
  { alpha2: 'KR', name: 'Korea, Republic of', alpha3: 'KOR', numeric: '410' },
186
+ { alpha2: 'XK', name: 'Kosovo', alpha3: 'XKX', numeric: '900' },
186
187
  { alpha2: 'KW', name: 'Kuwait', alpha3: 'KWT', numeric: '414' },
187
188
  { alpha2: 'KG', name: 'Kyrgyzstan', alpha3: 'KGZ', numeric: '417' },
188
189
  { alpha2: 'LA', name: 'Lao People\'s Democratic Republic', alpha3: 'LAO', numeric: '418' },
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.95.0'
2
+ VERSION = '1.96.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemerchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.95.0
4
+ version: 1.96.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-23 00:00:00.000000000 Z
11
+ date: 2019-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -204,6 +204,7 @@ files:
204
204
  - lib/active_merchant/billing/gateways/cyber_source.rb
205
205
  - lib/active_merchant/billing/gateways/d_local.rb
206
206
  - lib/active_merchant/billing/gateways/data_cash.rb
207
+ - lib/active_merchant/billing/gateways/decidir.rb
207
208
  - lib/active_merchant/billing/gateways/dibs.rb
208
209
  - lib/active_merchant/billing/gateways/digitzs.rb
209
210
  - lib/active_merchant/billing/gateways/ebanx.rb