activemerchant 1.95.0 → 1.96.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 (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