activemerchant 1.120.0 → 1.125.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +227 -1
  3. data/README.md +1 -1
  4. data/lib/active_merchant/billing/check.rb +13 -19
  5. data/lib/active_merchant/billing/credit_card.rb +13 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +24 -12
  8. data/lib/active_merchant/billing/gateway.rb +1 -1
  9. data/lib/active_merchant/billing/gateways/adyen.rb +81 -26
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +9 -5
  14. data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
  15. data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
  16. data/lib/active_merchant/billing/gateways/checkout_v2.rb +43 -4
  17. data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
  18. data/lib/active_merchant/billing/gateways/cyber_source.rb +41 -6
  19. data/lib/active_merchant/billing/gateways/d_local.rb +12 -6
  20. data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
  21. data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
  22. data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
  23. data/lib/active_merchant/billing/gateways/elavon.rb +65 -30
  24. data/lib/active_merchant/billing/gateways/element.rb +22 -2
  25. data/lib/active_merchant/billing/gateways/global_collect.rb +130 -26
  26. data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
  27. data/lib/active_merchant/billing/gateways/kushki.rb +30 -0
  28. data/lib/active_merchant/billing/gateways/mercado_pago.rb +6 -3
  29. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  30. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  31. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  32. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  33. data/lib/active_merchant/billing/gateways/mundipagg.rb +22 -11
  34. data/lib/active_merchant/billing/gateways/nmi.rb +29 -10
  35. data/lib/active_merchant/billing/gateways/orbital.rb +55 -9
  36. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  37. data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
  38. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  39. data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
  40. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  41. data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
  42. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  43. data/lib/active_merchant/billing/gateways/paymentez.rb +14 -2
  44. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  45. data/lib/active_merchant/billing/gateways/paysafe.rb +412 -0
  46. data/lib/active_merchant/billing/gateways/payu_latam.rb +9 -4
  47. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  48. data/lib/active_merchant/billing/gateways/pin.rb +31 -4
  49. data/lib/active_merchant/billing/gateways/priority.rb +347 -0
  50. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  51. data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
  52. data/lib/active_merchant/billing/gateways/safe_charge.rb +8 -2
  53. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  54. data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
  55. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +115 -39
  56. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  57. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  58. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +21 -7
  59. data/lib/active_merchant/billing/gateways/vpos.rb +58 -10
  60. data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
  61. data/lib/active_merchant/billing/gateways/worldpay.rb +226 -62
  62. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  63. data/lib/active_merchant/billing/response.rb +4 -0
  64. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  65. data/lib/active_merchant/billing.rb +1 -0
  66. data/lib/active_merchant/version.rb +1 -1
  67. metadata +13 -3
@@ -16,8 +16,8 @@ module ActiveMerchant #:nodoc:
16
16
  self.homepage_url = 'https://www.adyen.com/'
17
17
  self.display_name = 'Adyen'
18
18
 
19
- PAYMENT_API_VERSION = 'v40'
20
- RECURRING_API_VERSION = 'v30'
19
+ PAYMENT_API_VERSION = 'v64'
20
+ RECURRING_API_VERSION = 'v49'
21
21
 
22
22
  STANDARD_ERROR_CODE_MAPPING = {
23
23
  '101' => STANDARD_ERROR_CODE[:incorrect_number],
@@ -59,6 +59,8 @@ module ActiveMerchant #:nodoc:
59
59
  add_3ds_authenticated_data(post, options)
60
60
  add_splits(post, options)
61
61
  add_recurring_contract(post, options)
62
+ add_network_transaction_reference(post, options)
63
+ add_application_info(post, options)
62
64
  commit('authorise', post, options)
63
65
  end
64
66
 
@@ -67,29 +69,34 @@ module ActiveMerchant #:nodoc:
67
69
  add_invoice_for_modification(post, money, options)
68
70
  add_reference(post, authorization, options)
69
71
  add_splits(post, options)
72
+ add_network_transaction_reference(post, options)
70
73
  commit('capture', post, options)
71
74
  end
72
75
 
73
76
  def refund(money, authorization, options = {})
74
77
  post = init_post(options)
75
78
  add_invoice_for_modification(post, money, options)
76
- add_original_reference(post, authorization, options)
79
+ add_reference(post, authorization, options)
77
80
  add_splits(post, options)
81
+ add_network_transaction_reference(post, options)
78
82
  commit('refund', post, options)
79
83
  end
80
84
 
81
85
  def credit(money, payment, options = {})
86
+ action = 'refundWithData'
82
87
  post = init_post(options)
83
88
  add_invoice(post, money, options)
84
- add_payment(post, payment, options)
89
+ add_payment(post, payment, options, action)
85
90
  add_shopper_reference(post, options)
86
- commit('refundWithData', post, options)
91
+ add_network_transaction_reference(post, options)
92
+ commit(action, post, options)
87
93
  end
88
94
 
89
95
  def void(authorization, options = {})
90
96
  post = init_post(options)
91
97
  endpoint = options[:cancel_or_refund] ? 'cancelOrRefund' : 'cancel'
92
98
  add_reference(post, authorization, options)
99
+ add_network_transaction_reference(post, options)
93
100
  commit(endpoint, post, options)
94
101
  end
95
102
 
@@ -147,12 +154,19 @@ module ActiveMerchant #:nodoc:
147
154
  true
148
155
  end
149
156
 
157
+ def supports_network_tokenization?
158
+ true
159
+ end
160
+
150
161
  def scrub(transcript)
151
162
  transcript.
152
163
  gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
153
- gsub(%r(("number\\?":\\?")[^"]*)i, '\1[FILTERED]').
154
- gsub(%r(("cvc\\?":\\?")[^"]*)i, '\1[FILTERED]').
155
- gsub(%r(("cavv\\?":\\?")[^"]*)i, '\1[FILTERED]')
164
+ gsub(%r(("number\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
165
+ gsub(%r(("cvc\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
166
+ gsub(%r(("cavv\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
167
+ gsub(%r(("bankLocationId\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
168
+ gsub(%r(("iban\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
169
+ gsub(%r(("bankAccountNumber\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]')
156
170
  end
157
171
 
158
172
  private
@@ -204,7 +218,7 @@ module ActiveMerchant #:nodoc:
204
218
  }
205
219
 
206
220
  def add_extra_data(post, payment, options)
207
- post[:telephoneNumber] = options[:billing_address][:phone] if options.dig(:billing_address, :phone)
221
+ post[:telephoneNumber] = (options[:billing_address][:phone_number] if options.dig(:billing_address, :phone_number)) || (options[:billing_address][:phone] if options.dig(:billing_address, :phone)) || ''
208
222
  post[:fraudOffset] = options[:fraud_offset] if options[:fraud_offset]
209
223
  post[:selectedBrand] = options[:selected_brand] if options[:selected_brand]
210
224
  post[:selectedBrand] ||= NETWORK_TOKENIZATION_CARD_SOURCE[payment.source.to_s] if payment.is_a?(NetworkTokenizationCreditCard)
@@ -327,7 +341,7 @@ module ActiveMerchant #:nodoc:
327
341
  post[:deliveryAddress][:stateOrProvince] = get_state(address)
328
342
  post[:deliveryAddress][:country] = address[:country] if address[:country]
329
343
  end
330
- return unless post[:card]&.kind_of?(Hash)
344
+ return unless post[:bankAccount]&.kind_of?(Hash) || post[:card]&.kind_of?(Hash)
331
345
 
332
346
  if (address = options[:billing_address] || options[:address]) && address[:country]
333
347
  post[:billingAddress] = {}
@@ -350,6 +364,7 @@ module ActiveMerchant #:nodoc:
350
364
  value: localized_amount(money, currency),
351
365
  currency: currency
352
366
  }
367
+
353
368
  post[:amount] = amount
354
369
  end
355
370
 
@@ -362,17 +377,32 @@ module ActiveMerchant #:nodoc:
362
377
  post[:modificationAmount] = amount
363
378
  end
364
379
 
365
- def add_payment(post, payment, options)
380
+ def add_payment(post, payment, options, action = nil)
366
381
  if payment.is_a?(String)
367
382
  _, _, recurring_detail_reference = payment.split('#')
368
383
  post[:selectedRecurringDetailReference] = recurring_detail_reference
369
384
  options[:recurring_contract_type] ||= 'RECURRING'
385
+ elsif payment.is_a?(Check)
386
+ add_bank_account(post, payment, options, action)
370
387
  else
371
388
  add_mpi_data_for_network_tokenization_card(post, payment) if payment.is_a?(NetworkTokenizationCreditCard)
372
389
  add_card(post, payment)
373
390
  end
374
391
  end
375
392
 
393
+ def add_bank_account(post, bank_account, options, action)
394
+ bank = {
395
+ bankAccountNumber: bank_account.account_number,
396
+ ownerName: bank_account.name,
397
+ countryCode: options[:billing_address][:country]
398
+ }
399
+
400
+ action == 'refundWithData' ? bank[:iban] = bank_account.routing_number : bank[:bankLocationId] = bank_account.routing_number
401
+
402
+ requires!(bank, :bankAccountNumber, :ownerName, :countryCode)
403
+ post[:bankAccount] = bank
404
+ end
405
+
376
406
  def add_card(post, credit_card)
377
407
  card = {
378
408
  expiryMonth: credit_card.month,
@@ -394,18 +424,16 @@ module ActiveMerchant #:nodoc:
394
424
  options
395
425
  end
396
426
 
397
- def add_reference(post, authorization, options = {})
398
- _, psp_reference, = authorization.split('#')
399
- post[:originalReference] = single_reference(authorization) || psp_reference
427
+ def add_network_transaction_reference(post, options)
428
+ return unless ntid = options[:network_transaction_id] || options.dig(:stored_credential, :network_transaction_id)
429
+
430
+ post[:additionalData] = {} unless post[:additionalData]
431
+ post[:additionalData][:networkTxReference] = ntid
400
432
  end
401
433
 
402
- def add_original_reference(post, authorization, options = {})
403
- if authorization.start_with?('#')
404
- _, original_psp_reference, = authorization.split('#')
405
- else
406
- original_psp_reference, = authorization.split('#')
407
- end
408
- post[:originalReference] = single_reference(authorization) || original_psp_reference
434
+ def add_reference(post, authorization, options = {})
435
+ original_reference = authorization.split('#').reject(&:empty?).first
436
+ post[:originalReference] = original_reference
409
437
  end
410
438
 
411
439
  def add_mpi_data_for_network_tokenization_card(post, payment)
@@ -416,10 +444,6 @@ module ActiveMerchant #:nodoc:
416
444
  post[:mpiData][:eci] = payment.eci || '07'
417
445
  end
418
446
 
419
- def single_reference(authorization)
420
- authorization if !authorization.include?('#')
421
- end
422
-
423
447
  def add_recurring_contract(post, options = {})
424
448
  return unless options[:recurring_contract_type]
425
449
 
@@ -430,6 +454,31 @@ module ActiveMerchant #:nodoc:
430
454
  post[:recurring] = recurring
431
455
  end
432
456
 
457
+ def add_application_info(post, options)
458
+ post[:applicationInfo] ||= {}
459
+ add_external_platform(post, options)
460
+ add_merchant_application(post, options)
461
+ end
462
+
463
+ def add_external_platform(post, options)
464
+ return unless options[:externalPlatform]
465
+
466
+ post[:applicationInfo][:externalPlatform] = {
467
+ name: options[:externalPlatform][:name],
468
+ version: options[:externalPlatform][:version],
469
+ integrator: options[:externalPlatform][:integrator]
470
+ }
471
+ end
472
+
473
+ def add_merchant_application(post, options)
474
+ return unless options[:merchantApplication]
475
+
476
+ post[:applicationInfo][:merchantApplication] = {
477
+ name: options[:merchantApplication][:name],
478
+ version: options[:merchantApplication][:version]
479
+ }
480
+ end
481
+
433
482
  def add_installments(post, options)
434
483
  post[:installments] = {
435
484
  value: options[:installments]
@@ -511,6 +560,7 @@ module ActiveMerchant #:nodoc:
511
560
  raw_response = e.response.body
512
561
  response = parse(raw_response)
513
562
  end
563
+
514
564
  success = success_from(action, response, options)
515
565
  Response.new(
516
566
  success,
@@ -519,6 +569,7 @@ module ActiveMerchant #:nodoc:
519
569
  authorization: authorization_from(action, parameters, response),
520
570
  test: test?,
521
571
  error_code: success ? nil : error_code_from(response),
572
+ network_transaction_id: network_transaction_id_from(response),
522
573
  avs_result: AVSResult.new(code: avs_code_from(response)),
523
574
  cvv_result: CVVResult.new(cvv_result_from(response))
524
575
  )
@@ -609,7 +660,7 @@ module ActiveMerchant #:nodoc:
609
660
  def init_post(options = {})
610
661
  post = {}
611
662
  add_merchant_account(post, options)
612
- post[:reference] = options[:order_id] if options[:order_id]
663
+ post[:reference] = options[:order_id][0..79] if options[:order_id]
613
664
  post
614
665
  end
615
666
 
@@ -621,6 +672,10 @@ module ActiveMerchant #:nodoc:
621
672
  STANDARD_ERROR_CODE_MAPPING[response['errorCode']]
622
673
  end
623
674
 
675
+ def network_transaction_id_from(response)
676
+ response.dig('additionalData', 'networkTxReference')
677
+ end
678
+
624
679
  def add_browser_info(browser_info, post)
625
680
  return unless browser_info
626
681
 
@@ -567,14 +567,16 @@ module ActiveMerchant
567
567
 
568
568
  xml.customerIP(options[:ip]) unless empty?(options[:ip])
569
569
 
570
- xml.cardholderAuthentication do
571
- three_d_secure = options.fetch(:three_d_secure, {})
572
- xml.authenticationIndicator(
573
- options[:authentication_indicator] || three_d_secure[:eci]
574
- )
575
- xml.cardholderAuthenticationValue(
576
- options[:cardholder_authentication_value] || three_d_secure[:cavv]
577
- )
570
+ if !empty?(options.fetch(:three_d_secure, {})) || options[:authentication_indicator] || options[:cardholder_authentication_value]
571
+ xml.cardholderAuthentication do
572
+ three_d_secure = options.fetch(:three_d_secure, {})
573
+ xml.authenticationIndicator(
574
+ options[:authentication_indicator] || three_d_secure[:eci]
575
+ )
576
+ xml.cardholderAuthenticationValue(
577
+ options[:cardholder_authentication_value] || three_d_secure[:cavv]
578
+ )
579
+ end
578
580
  end
579
581
  end
580
582
 
@@ -84,6 +84,7 @@ module ActiveMerchant #:nodoc:
84
84
  add_customer_data(post, options)
85
85
  add_rebill(post, options) if options[:rebill]
86
86
  add_duplicate_override(post, options)
87
+ add_stored_credential(post, options)
87
88
  post[:TRANS_TYPE] = 'AUTH'
88
89
  commit('AUTH_ONLY', money, post, options)
89
90
  end
@@ -107,6 +108,7 @@ module ActiveMerchant #:nodoc:
107
108
  add_customer_data(post, options)
108
109
  add_rebill(post, options) if options[:rebill]
109
110
  add_duplicate_override(post, options)
111
+ add_stored_credential(post, options)
110
112
  post[:TRANS_TYPE] = 'SALE'
111
113
  commit('AUTH_CAPTURE', money, post, options)
112
114
  end
@@ -461,6 +463,33 @@ module ActiveMerchant #:nodoc:
461
463
  post[:REB_CYCLES] = options[:rebill_cycles]
462
464
  end
463
465
 
466
+ def add_stored_credential(post, options)
467
+ post[:cof] = initiator(options)
468
+ post[:cofscheduled] = scheduled(options)
469
+ end
470
+
471
+ def initiator(options)
472
+ return unless initiator = options.dig(:stored_credential, :initiator)
473
+
474
+ case initiator
475
+ when 'merchant'
476
+ 'M'
477
+ when 'cardholder'
478
+ 'C'
479
+ end
480
+ end
481
+
482
+ def scheduled(options)
483
+ return unless reason_type = options.dig(:stored_credential, :reason_type)
484
+
485
+ case reason_type
486
+ when 'recurring' || 'installment'
487
+ 'Y'
488
+ when 'unscheduled'
489
+ 'N'
490
+ end
491
+ end
492
+
464
493
  def post_data(action, parameters = {})
465
494
  post = {}
466
495
  post[:version] = '1'
@@ -386,7 +386,7 @@ module ActiveMerchant
386
386
 
387
387
  def parse(response)
388
388
  return bad_authentication_response if response.code.to_i == 401
389
- return forbidden_response(response.body) if response.code.to_i == 403
389
+ return generic_error_response(response.body) if [403, 429].include?(response.code.to_i)
390
390
 
391
391
  parsed = {}
392
392
  doc = Nokogiri::XML(response.body)
@@ -564,7 +564,7 @@ module ActiveMerchant
564
564
  { 'description' => 'Unable to authenticate. Please check your credentials.' }
565
565
  end
566
566
 
567
- def forbidden_response(body)
567
+ def generic_error_response(body)
568
568
  { 'description' => body }
569
569
  end
570
570
  end
@@ -7,7 +7,7 @@ rescue LoadError
7
7
  raise 'Could not load the braintree gem. Use `gem install braintree` to install it.'
8
8
  end
9
9
 
10
- raise "Need braintree gem >= 3.0.0. Run `gem install braintree --version '~>3.0.0'` to get the correct version." unless Braintree::Version::Major == 3 && Braintree::Version::Minor == 0
10
+ raise 'Need braintree gem >= 2.0.0.' unless Braintree::Version::Major >= 2 && Braintree::Version::Minor >= 0
11
11
 
12
12
  module ActiveMerchant #:nodoc:
13
13
  module Billing #:nodoc:
@@ -135,8 +135,8 @@ module ActiveMerchant #:nodoc:
135
135
  result = @braintree_gateway.verification.create(payload)
136
136
  response = Response.new(result.success?, message_from_transaction_result(result), response_options(result))
137
137
  response.cvv_result['message'] = ''
138
- response.cvv_result['code'] = response.params['cvv_result']
139
- response.avs_result['code'] = response.params['avs_result'][:code]
138
+ response.cvv_result['code'] = response.params['cvv_result'] if response.params['cvv_result']
139
+ response.avs_result['code'] = response.params['avs_result'][:code] if response.params.dig('avs_result', :code)
140
140
  response
141
141
  end
142
142
 
@@ -588,7 +588,8 @@ module ActiveMerchant #:nodoc:
588
588
  'merchant_account_id' => transaction.merchant_account_id,
589
589
  'risk_data' => risk_data,
590
590
  'network_transaction_id' => transaction.network_transaction_id || nil,
591
- 'processor_response_code' => response_code_from_result(result)
591
+ 'processor_response_code' => response_code_from_result(result),
592
+ 'recurring' => transaction.recurring
592
593
  }
593
594
  end
594
595
 
@@ -770,6 +771,8 @@ module ActiveMerchant #:nodoc:
770
771
  else
771
772
  parameters[:transaction_source] = stored_credential[:reason_type]
772
773
  end
774
+ elsif %w(recurring_first moto).include?(stored_credential[:reason_type])
775
+ parameters[:transaction_source] = stored_credential[:reason_type]
773
776
  else
774
777
  parameters[:transaction_source] = ''
775
778
  end
@@ -801,7 +804,8 @@ module ActiveMerchant #:nodoc:
801
804
  eci_indicator: credit_card_or_vault_id.eci
802
805
  }
803
806
  elsif credit_card_or_vault_id.source == :android_pay || credit_card_or_vault_id.source == :google_pay
804
- parameters[:google_pay_card] = {
807
+ Braintree::Version::Major < 3 ? pay_card = :android_pay_card : pay_card = :google_pay_card
808
+ parameters[pay_card] = {
805
809
  number: credit_card_or_vault_id.number,
806
810
  cryptogram: credit_card_or_vault_id.payment_cryptogram,
807
811
  expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
@@ -150,23 +150,13 @@ module ActiveMerchant #:nodoc:
150
150
 
151
151
  def authorize(money, credit_card_or_reference, options = {})
152
152
  post = {}
153
- add_pair(post, :captureDelay, -1)
154
- add_amount(post, money, options)
155
- add_invoice(post, credit_card_or_reference, money, options)
156
- add_credit_card_or_reference(post, credit_card_or_reference)
157
- add_customer_data(post, options)
158
- add_remote_address(post, options)
153
+ add_auth_purchase(post, -1, money, credit_card_or_reference, options)
159
154
  commit('SALE', post)
160
155
  end
161
156
 
162
157
  def purchase(money, credit_card_or_reference, options = {})
163
158
  post = {}
164
- add_pair(post, :captureDelay, 0)
165
- add_amount(post, money, options)
166
- add_invoice(post, credit_card_or_reference, money, options)
167
- add_credit_card_or_reference(post, credit_card_or_reference)
168
- add_customer_data(post, options)
169
- add_remote_address(post, options)
159
+ add_auth_purchase(post, 0, money, credit_card_or_reference, options)
170
160
  commit('SALE', post)
171
161
  end
172
162
 
@@ -184,6 +174,7 @@ module ActiveMerchant #:nodoc:
184
174
  add_pair(post, :xref, authorization)
185
175
  add_amount(post, money, options)
186
176
  add_remote_address(post, options)
177
+ add_country_code(post, options)
187
178
  response = commit('REFUND_SALE', post)
188
179
 
189
180
  return response if response.success?
@@ -223,6 +214,16 @@ module ActiveMerchant #:nodoc:
223
214
 
224
215
  private
225
216
 
217
+ def add_auth_purchase(post, pair_value, money, credit_card_or_reference, options)
218
+ add_pair(post, :captureDelay, pair_value)
219
+ add_amount(post, money, options)
220
+ add_invoice(post, credit_card_or_reference, money, options)
221
+ add_credit_card_or_reference(post, credit_card_or_reference)
222
+ add_customer_data(post, options)
223
+ add_remote_address(post, options)
224
+ add_country_code(post, options)
225
+ end
226
+
226
227
  def add_amount(post, money, options)
227
228
  currency = options[:currency] || currency(money)
228
229
  add_pair(post, :amount, localized_amount(money, currency), required: true)
@@ -286,6 +287,10 @@ module ActiveMerchant #:nodoc:
286
287
  add_pair(post, :remoteAddress, options[:ip] || '1.1.1.1')
287
288
  end
288
289
 
290
+ def add_country_code(post, options)
291
+ post[:countryCode] = options[:country_code] || self.supported_countries[0]
292
+ end
293
+
289
294
  def normalize_line_endings(str)
290
295
  str.gsub(/%0D%0A|%0A%0D|%0D/, '%0A')
291
296
  end
@@ -309,7 +314,6 @@ module ActiveMerchant #:nodoc:
309
314
  end
310
315
 
311
316
  def commit(action, parameters)
312
- parameters.update(countryCode: self.supported_countries[0]) unless %w[CAPTURE CANCEL].include?(action)
313
317
  parameters.update(
314
318
  merchantID: @options[:login],
315
319
  action: action
@@ -41,7 +41,7 @@ module ActiveMerchant #:nodoc:
41
41
  def purchase(money, payment_object, options = {})
42
42
  post = {}
43
43
  add_creditcard(post, payment_object)
44
- add_invoice(post, options)
44
+ add_invoice(post, money, options)
45
45
  add_address(post, options)
46
46
  add_customer_data(post, options)
47
47
  commit('SALE', money, post)
@@ -50,7 +50,7 @@ module ActiveMerchant #:nodoc:
50
50
  def refund(money, identification, options = {})
51
51
  post = {}
52
52
  post[:origtx] = identification
53
- add_invoice(post, options)
53
+ add_invoice(post, money, options)
54
54
  add_customer_data(post, options)
55
55
  commit('REFUND', money, post)
56
56
  end
@@ -69,7 +69,6 @@ module ActiveMerchant #:nodoc:
69
69
  private
70
70
 
71
71
  def commit(action, money, fields)
72
- fields[:amount] = amount(money)
73
72
  url = (test? ? test_url : live_url) + CGI.escape(@options[:merchant_gateway_name])
74
73
  raw_response = ssl_post(url, post_data(action, fields))
75
74
  parsed_response = parse(raw_response)
@@ -92,6 +91,7 @@ module ActiveMerchant #:nodoc:
92
91
 
93
92
  def post_data(action, parameters = {})
94
93
  post = {}
94
+
95
95
  post[:command] = action
96
96
  post[:merchant] = @options[:merchant]
97
97
  post[:operator] = @options[:operator]
@@ -110,9 +110,19 @@ module ActiveMerchant #:nodoc:
110
110
  post[:lname] = creditcard.last_name
111
111
  end
112
112
 
113
- def add_invoice(post, options)
113
+ def add_invoice(post, money, options)
114
114
  post[:order_number] = options[:order_id] if options[:order_id].present?
115
- post[:itemcode] = (options[:item_code] || @options[:default_item_code])
115
+
116
+ if options[:item_codes].present?
117
+ codes_and_amounts = options[:item_codes].transform_keys { |key| key.to_s.delete('_') }
118
+ codes_and_amounts.each do |key, value|
119
+ post[key] = value if key.start_with?('itemcode')
120
+ post[key] = amount(value.to_i) if key.start_with?('amount')
121
+ end
122
+ else
123
+ post[:itemcode] = (options[:item_code] || @options[:default_item_code])
124
+ post[:amount] = amount(money.to_i)
125
+ end
116
126
  end
117
127
 
118
128
  def add_address(post, options)
@@ -37,12 +37,15 @@ module ActiveMerchant #:nodoc:
37
37
  post = {}
38
38
  add_invoice(post, amount, options)
39
39
  add_customer_data(post, options)
40
+ add_metadata(post, options)
40
41
 
41
42
  commit(:capture, post, authorization)
42
43
  end
43
44
 
44
45
  def void(authorization, _options = {})
45
46
  post = {}
47
+ add_metadata(post, options)
48
+
46
49
  commit(:void, post, authorization)
47
50
  end
48
51
 
@@ -50,6 +53,7 @@ module ActiveMerchant #:nodoc:
50
53
  post = {}
51
54
  add_invoice(post, amount, options)
52
55
  add_customer_data(post, options)
56
+ add_metadata(post, options)
53
57
 
54
58
  commit(:refund, post, authorization)
55
59
  end
@@ -82,6 +86,9 @@ module ActiveMerchant #:nodoc:
82
86
  add_stored_credential_options(post, options)
83
87
  add_transaction_data(post, options)
84
88
  add_3ds(post, options)
89
+ add_metadata(post, options)
90
+ add_processing_channel(post, options)
91
+ add_marketplace_data(post, options)
85
92
  end
86
93
 
87
94
  def add_invoice(post, money, options)
@@ -97,14 +104,24 @@ module ActiveMerchant #:nodoc:
97
104
  post[:metadata][:udf5] = application_id || 'ActiveMerchant'
98
105
  end
99
106
 
107
+ def add_metadata(post, options)
108
+ post[:metadata] = {} unless post[:metadata]
109
+ post[:metadata].merge!(options[:metadata]) if options[:metadata]
110
+ end
111
+
100
112
  def add_payment_method(post, payment_method, options)
101
113
  post[:source] = {}
102
- if payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :network_token
114
+ if payment_method.is_a?(NetworkTokenizationCreditCard)
115
+ token_type = token_type_from(payment_method)
116
+ cryptogram = payment_method.payment_cryptogram
117
+ eci = payment_method.eci || options[:eci]
118
+ eci ||= '05' if token_type == 'vts'
119
+
103
120
  post[:source][:type] = 'network_token'
104
121
  post[:source][:token] = payment_method.number
105
- post[:source][:token_type] = payment_method.brand == 'visa' ? 'vts' : 'mdes'
106
- post[:source][:cryptogram] = payment_method.payment_cryptogram
107
- post[:source][:eci] = options[:eci] || '05'
122
+ post[:source][:token_type] = token_type
123
+ post[:source][:cryptogram] = cryptogram if cryptogram
124
+ post[:source][:eci] = eci if eci
108
125
  else
109
126
  post[:source][:type] = 'card'
110
127
  post[:source][:name] = payment_method.name
@@ -176,6 +193,17 @@ module ActiveMerchant #:nodoc:
176
193
  end
177
194
  end
178
195
 
196
+ def add_processing_channel(post, options)
197
+ post[:processing_channel_id] = options[:processing_channel_id] if options[:processing_channel_id]
198
+ end
199
+
200
+ def add_marketplace_data(post, options)
201
+ if options[:marketplace]
202
+ post[:marketplace] = {}
203
+ post[:marketplace][:sub_entity_id] = options[:marketplace][:sub_entity_id] if options[:marketplace][:sub_entity_id]
204
+ end
205
+ end
206
+
179
207
  def commit(action, post, authorization = nil)
180
208
  begin
181
209
  raw_response = (action == :verify_payment ? ssl_get("#{base_url}/payments/#{post}", headers) : ssl_post(url(post, action, authorization), post.to_json, headers))
@@ -296,6 +324,17 @@ module ActiveMerchant #:nodoc:
296
324
  STANDARD_ERROR_CODE_MAPPING[response['response_code']]
297
325
  end
298
326
  end
327
+
328
+ def token_type_from(payment_method)
329
+ case payment_method.source
330
+ when :network_token
331
+ payment_method.brand == 'visa' ? 'vts' : 'mdes'
332
+ when :google_pay, :android_pay
333
+ 'googlepay'
334
+ when :apple_pay
335
+ 'applepay'
336
+ end
337
+ end
299
338
  end
300
339
  end
301
340
  end
@@ -20,8 +20,9 @@ module ActiveMerchant #:nodoc:
20
20
  self.live_url = 'https://assigned-subdomain.credorax.net/crax_gate/service/gateway'
21
21
 
22
22
  self.supported_countries = %w(AD AT BE BG HR CY CZ DK EE FR DE GI GR GG HU IS IE IM IT JE LV LI LT LU MT MC NO PL PT RO SM SK ES SE CH GB)
23
+
23
24
  self.default_currency = 'EUR'
24
- self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
25
+ self.currencies_without_fractions = %w(BIF CLP DJF GNF ISK JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
25
26
  self.currencies_with_three_decimal_places = %w(BHD IQD JOD KWD LYD OMR TND)
26
27
 
27
28
  self.money_format = :cents