activemerchant 1.121.0 → 1.125.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +217 -0
  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 +75 -27
  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 +6 -3
  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 +33 -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 +46 -8
  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 +2 -2
  43. data/lib/active_merchant/billing/gateways/paymentez.rb +14 -2
  44. data/lib/active_merchant/billing/gateways/paysafe.rb +412 -0
  45. data/lib/active_merchant/billing/gateways/payu_latam.rb +9 -4
  46. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  47. data/lib/active_merchant/billing/gateways/pin.rb +31 -4
  48. data/lib/active_merchant/billing/gateways/priority.rb +347 -0
  49. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  50. data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
  51. data/lib/active_merchant/billing/gateways/safe_charge.rb +8 -2
  52. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  53. data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
  54. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +115 -39
  55. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  56. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  57. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +21 -7
  58. data/lib/active_merchant/billing/gateways/vpos.rb +49 -6
  59. data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
  60. data/lib/active_merchant/billing/gateways/worldpay.rb +226 -62
  61. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  62. data/lib/active_merchant/billing/response.rb +4 -0
  63. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  64. data/lib/active_merchant/billing.rb +1 -0
  65. data/lib/active_merchant/version.rb +1 -1
  66. 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,19 +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
400
- post[:networkTxReference] = options[:network_transaction_id] if options[:network_transaction_id]
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
401
432
  end
402
433
 
403
- def add_original_reference(post, authorization, options = {})
404
- if authorization.start_with?('#')
405
- _, original_psp_reference, = authorization.split('#')
406
- else
407
- original_psp_reference, = authorization.split('#')
408
- end
409
- 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
410
437
  end
411
438
 
412
439
  def add_mpi_data_for_network_tokenization_card(post, payment)
@@ -417,10 +444,6 @@ module ActiveMerchant #:nodoc:
417
444
  post[:mpiData][:eci] = payment.eci || '07'
418
445
  end
419
446
 
420
- def single_reference(authorization)
421
- authorization if !authorization.include?('#')
422
- end
423
-
424
447
  def add_recurring_contract(post, options = {})
425
448
  return unless options[:recurring_contract_type]
426
449
 
@@ -431,6 +454,31 @@ module ActiveMerchant #:nodoc:
431
454
  post[:recurring] = recurring
432
455
  end
433
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
+
434
482
  def add_installments(post, options)
435
483
  post[:installments] = {
436
484
  value: options[:installments]
@@ -612,7 +660,7 @@ module ActiveMerchant #:nodoc:
612
660
  def init_post(options = {})
613
661
  post = {}
614
662
  add_merchant_account(post, options)
615
- post[:reference] = options[:order_id] if options[:order_id]
663
+ post[:reference] = options[:order_id][0..79] if options[:order_id]
616
664
  post
617
665
  end
618
666
 
@@ -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
@@ -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
@@ -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)
@@ -87,6 +87,8 @@ module ActiveMerchant #:nodoc:
87
87
  add_transaction_data(post, options)
88
88
  add_3ds(post, options)
89
89
  add_metadata(post, options)
90
+ add_processing_channel(post, options)
91
+ add_marketplace_data(post, options)
90
92
  end
91
93
 
92
94
  def add_invoice(post, money, options)
@@ -109,12 +111,17 @@ module ActiveMerchant #:nodoc:
109
111
 
110
112
  def add_payment_method(post, payment_method, options)
111
113
  post[:source] = {}
112
- 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
+
113
120
  post[:source][:type] = 'network_token'
114
121
  post[:source][:token] = payment_method.number
115
- post[:source][:token_type] = payment_method.brand == 'visa' ? 'vts' : 'mdes'
116
- post[:source][:cryptogram] = payment_method.payment_cryptogram
117
- 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
118
125
  else
119
126
  post[:source][:type] = 'card'
120
127
  post[:source][:name] = payment_method.name
@@ -186,6 +193,17 @@ module ActiveMerchant #:nodoc:
186
193
  end
187
194
  end
188
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
+
189
207
  def commit(action, post, authorization = nil)
190
208
  begin
191
209
  raw_response = (action == :verify_payment ? ssl_get("#{base_url}/payments/#{post}", headers) : ssl_post(url(post, action, authorization), post.to_json, headers))
@@ -306,6 +324,17 @@ module ActiveMerchant #:nodoc:
306
324
  STANDARD_ERROR_CODE_MAPPING[response['response_code']]
307
325
  end
308
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
309
338
  end
310
339
  end
311
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