activemerchant 1.126.0 → 1.131.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +269 -0
  3. data/lib/active_merchant/billing/check.rb +40 -8
  4. data/lib/active_merchant/billing/credit_card.rb +28 -1
  5. data/lib/active_merchant/billing/credit_card_methods.rb +80 -24
  6. data/lib/active_merchant/billing/gateways/adyen.rb +69 -10
  7. data/lib/active_merchant/billing/gateways/airwallex.rb +40 -11
  8. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +24 -6
  10. data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
  11. data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -1
  12. data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
  13. data/lib/active_merchant/billing/gateways/borgun.rb +57 -16
  14. data/lib/active_merchant/billing/gateways/braintree_blue.rb +72 -24
  15. data/lib/active_merchant/billing/gateways/card_connect.rb +27 -9
  16. data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
  17. data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -57
  18. data/lib/active_merchant/billing/gateways/commerce_hub.rb +366 -0
  19. data/lib/active_merchant/billing/gateways/credorax.rb +47 -27
  20. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  21. data/lib/active_merchant/billing/gateways/cyber_source.rb +119 -33
  22. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +454 -0
  23. data/lib/active_merchant/billing/gateways/d_local.rb +45 -5
  24. data/lib/active_merchant/billing/gateways/decidir.rb +15 -4
  25. data/lib/active_merchant/billing/gateways/ebanx.rb +36 -24
  26. data/lib/active_merchant/billing/gateways/element.rb +21 -1
  27. data/lib/active_merchant/billing/gateways/global_collect.rb +113 -40
  28. data/lib/active_merchant/billing/gateways/ipg.rb +13 -8
  29. data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
  30. data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
  31. data/lib/active_merchant/billing/gateways/litle.rb +25 -5
  32. data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
  33. data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
  34. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
  35. data/lib/active_merchant/billing/gateways/monei.rb +2 -0
  36. data/lib/active_merchant/billing/gateways/moneris.rb +20 -5
  37. data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
  38. data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
  39. data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
  40. data/lib/active_merchant/billing/gateways/orbital.rb +43 -22
  41. data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
  42. data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
  43. data/lib/active_merchant/billing/gateways/paymentez.rb +18 -6
  44. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  45. data/lib/active_merchant/billing/gateways/paypal_express.rb +2 -0
  46. data/lib/active_merchant/billing/gateways/paysafe.rb +22 -14
  47. data/lib/active_merchant/billing/gateways/payu_latam.rb +4 -1
  48. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  49. data/lib/active_merchant/billing/gateways/priority.rb +29 -6
  50. data/lib/active_merchant/billing/gateways/rapyd.rb +110 -49
  51. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  52. data/lib/active_merchant/billing/gateways/redsys.rb +11 -6
  53. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
  54. data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
  55. data/lib/active_merchant/billing/gateways/shift4.rb +345 -0
  56. data/lib/active_merchant/billing/gateways/simetrik.rb +28 -22
  57. data/lib/active_merchant/billing/gateways/stripe.rb +30 -6
  58. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +62 -22
  59. data/lib/active_merchant/billing/gateways/tns.rb +2 -5
  60. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  61. data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
  62. data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
  63. data/lib/active_merchant/billing/gateways/visanet_peru.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
  65. data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
  66. data/lib/active_merchant/billing/gateways/worldpay.rb +128 -13
  67. data/lib/active_merchant/billing/response.rb +15 -1
  68. data/lib/active_merchant/connection.rb +0 -2
  69. data/lib/active_merchant/country.rb +1 -0
  70. data/lib/active_merchant/errors.rb +4 -1
  71. data/lib/active_merchant/version.rb +1 -1
  72. metadata +24 -3
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
30
30
  class OrbitalGateway < Gateway
31
31
  include Empty
32
32
 
33
- API_VERSION = '8.1'
33
+ API_VERSION = '9.0'
34
34
 
35
35
  POST_HEADERS = {
36
36
  'MIME-Version' => '1.1',
@@ -98,6 +98,7 @@ module ActiveMerchant #:nodoc:
98
98
  'NZD' => '554',
99
99
  'NOK' => '578',
100
100
  'SGD' => '702',
101
+ 'ZAR' => '710',
101
102
  'SEK' => '752',
102
103
  'CHF' => '756',
103
104
  'GBP' => '826',
@@ -119,6 +120,7 @@ module ActiveMerchant #:nodoc:
119
120
  'NZD' => '2',
120
121
  'NOK' => '2',
121
122
  'SGD' => '2',
123
+ 'ZAR' => '2',
122
124
  'SEK' => '2',
123
125
  'CHF' => '2',
124
126
  'GBP' => '2',
@@ -196,6 +198,7 @@ module ActiveMerchant #:nodoc:
196
198
  requires!(options, :login, :password) unless options[:ip_authentication]
197
199
  super
198
200
  @options[:merchant_id] = @options[:merchant_id].to_s
201
+ @use_secondary_url = false
199
202
  end
200
203
 
201
204
  # A – Authorization request
@@ -235,11 +238,7 @@ module ActiveMerchant #:nodoc:
235
238
  def refund(money, authorization, options = {})
236
239
  payment_method = options[:payment_method]
237
240
  order = build_new_order_xml(REFUND, money, payment_method, options.merge(authorization: authorization)) do |xml|
238
- if payment_method.is_a?(Check)
239
- add_echeck(xml, payment_method, options)
240
- else
241
- add_refund_payment_source(xml, options[:currency])
242
- end
241
+ add_payment_source(xml, payment_method, options)
243
242
  xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn]
244
243
  end
245
244
 
@@ -398,6 +397,12 @@ module ActiveMerchant #:nodoc:
398
397
  add_soft_descriptors_from_hash(xml, descriptors) if descriptors.is_a?(Hash)
399
398
  end
400
399
 
400
+ def add_payment_action_ind(xml, payment_action_ind)
401
+ return unless payment_action_ind
402
+
403
+ xml.tag! :PaymentActionInd, payment_action_ind
404
+ end
405
+
401
406
  def add_soft_descriptors_from_specialized_class(xml, soft_desc)
402
407
  xml.tag! :SDMerchantName, soft_desc.merchant_name if soft_desc.merchant_name
403
408
  xml.tag! :SDProductDescription, soft_desc.product_description if soft_desc.product_description
@@ -564,7 +569,7 @@ module ActiveMerchant #:nodoc:
564
569
  add_currency_fields(xml, options[:currency])
565
570
  xml.tag! :BCRtNum, check.routing_number
566
571
  xml.tag! :CheckDDA, check.account_number if check.account_number
567
- xml.tag! :BankAccountType, ACCOUNT_TYPE[check.account_type] if ACCOUNT_TYPE[check.account_type]
572
+ add_bank_account_type(xml, check)
568
573
  xml.tag! :ECPAuthMethod, options[:auth_method] if options[:auth_method]
569
574
  xml.tag! :BankPmtDelv, options[:payment_delivery] || 'B'
570
575
  xml.tag! :AVSname, (check&.name ? check.name[0..29] : nil) if get_address(options).blank?
@@ -577,12 +582,6 @@ module ActiveMerchant #:nodoc:
577
582
  add_verification_value(xml, credit_card) if credit_card
578
583
  end
579
584
 
580
- def add_refund_payment_source(xml, currency = nil)
581
- xml.tag! :AccountNum, nil
582
-
583
- add_currency_fields(xml, currency)
584
- end
585
-
586
585
  def add_verification_value(xml, credit_card)
587
586
  return unless credit_card&.verification_value?
588
587
 
@@ -595,7 +594,7 @@ module ActiveMerchant #:nodoc:
595
594
  # Null-fill this attribute OR
596
595
  # Do not submit the attribute at all.
597
596
  # - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
598
- xml.tag! :CardSecValInd, '1' if %w(visa master discover).include?(credit_card.brand)
597
+ xml.tag! :CardSecValInd, '1' if %w(visa discover diners_club).include?(credit_card.brand)
599
598
  xml.tag! :CardSecVal, credit_card.verification_value
600
599
  end
601
600
 
@@ -604,6 +603,17 @@ module ActiveMerchant #:nodoc:
604
603
  xml.tag! :CurrencyExponent, currency_exponents(currency)
605
604
  end
606
605
 
606
+ def add_bank_account_type(xml, check)
607
+ bank_account_type =
608
+ if check.account_holder_type == 'business'
609
+ 'X'
610
+ else
611
+ ACCOUNT_TYPE[check.account_type]
612
+ end
613
+
614
+ xml.tag! :BankAccountType, bank_account_type if bank_account_type
615
+ end
616
+
607
617
  def add_card_indicators(xml, options)
608
618
  xml.tag! :CardIndicators, options[:card_indicators] if options[:card_indicators]
609
619
  end
@@ -752,16 +762,23 @@ module ActiveMerchant #:nodoc:
752
762
  xml.tag!(:AuthenticationECIInd, eci) if eci
753
763
  end
754
764
 
755
- def add_dpanind(xml, credit_card)
765
+ def add_dpanind(xml, credit_card, industry_type = nil)
756
766
  return unless credit_card.is_a?(NetworkTokenizationCreditCard)
757
767
 
758
- xml.tag! :DPANInd, 'Y'
768
+ xml.tag! :DPANInd, 'Y' unless industry_type == 'RC'
759
769
  end
760
770
 
761
- def add_digital_token_cryptogram(xml, credit_card)
762
- return unless credit_card.is_a?(NetworkTokenizationCreditCard)
771
+ def add_digital_token_cryptogram(xml, credit_card, three_d_secure)
772
+ return unless credit_card.is_a?(NetworkTokenizationCreditCard) || three_d_secure && credit_card.brand == 'discover'
763
773
 
764
- xml.tag! :DigitalTokenCryptogram, credit_card.payment_cryptogram
774
+ cryptogram =
775
+ if three_d_secure && credit_card.brand == 'discover'
776
+ three_d_secure[:cavv]
777
+ else
778
+ credit_card.payment_cryptogram
779
+ end
780
+
781
+ xml.tag!(:DigitalTokenCryptogram, cryptogram)
765
782
  end
766
783
 
767
784
  #=====OTHER FIELDS=====
@@ -862,6 +879,8 @@ module ActiveMerchant #:nodoc:
862
879
  # Failover URL will be attempted in the event of a connection error
863
880
  response =
864
881
  begin
882
+ raise ConnectionError.new 'Should use secondary url', 500 if @use_secondary_url
883
+
865
884
  request.call(remote_url)
866
885
  rescue ConnectionError
867
886
  request.call(remote_url(:secondary))
@@ -942,6 +961,7 @@ module ActiveMerchant #:nodoc:
942
961
 
943
962
  def build_new_order_xml(action, money, payment_source, parameters = {})
944
963
  requires!(parameters, :order_id)
964
+ @use_secondary_url = parameters[:use_secondary_url] if parameters[:use_secondary_url]
945
965
  xml = xml_envelope
946
966
  xml.tag! :Request do
947
967
  xml.tag! :NewOrder do
@@ -969,16 +989,17 @@ module ActiveMerchant #:nodoc:
969
989
  # CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
970
990
 
971
991
  add_soft_descriptors(xml, parameters[:soft_descriptors])
972
- add_dpanind(xml, payment_source)
992
+ add_payment_action_ind(xml, parameters[:payment_action_ind])
993
+ add_dpanind(xml, payment_source, parameters[:industry_type])
973
994
  add_aevv(xml, payment_source, three_d_secure)
974
- add_digital_token_cryptogram(xml, payment_source)
995
+ add_digital_token_cryptogram(xml, payment_source, three_d_secure)
975
996
 
976
997
  xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && payment_source.is_a?(Check)
977
998
 
978
999
  set_recurring_ind(xml, parameters)
979
1000
 
980
1001
  # Append Transaction Reference Number at the end for Refund transactions
981
- add_tx_ref_num(xml, parameters[:authorization]) if action == REFUND
1002
+ add_tx_ref_num(xml, parameters[:authorization]) if action == REFUND && payment_source.nil?
982
1003
 
983
1004
  add_level2_purchase(xml, parameters)
984
1005
  add_level3_purchase(xml, parameters)
@@ -33,7 +33,14 @@ module ActiveMerchant #:nodoc:
33
33
  store: 'customer/create',
34
34
  redact: 'customer/delete',
35
35
  level_3_visa: 'level_three/visa',
36
- level_3_mastercard: 'level_three/mastercard'
36
+ level_3_mastercard: 'level_three/mastercard',
37
+ ach_sale: 'checks/sale/by_account',
38
+ ach_customer_sale: 'checks/sale/by_customer',
39
+ ach_authorize: 'checks/hold/by_account',
40
+ ach_customer_authorize: 'checks/hold/by_customer',
41
+ ach_refund: 'checks/refund/by_transaction',
42
+ ach_capture: 'checks/manage/fund',
43
+ ach_void: 'checks/manage/void'
37
44
  }
38
45
 
39
46
  def initialize(options = {})
@@ -52,7 +59,15 @@ module ActiveMerchant #:nodoc:
52
59
  end
53
60
  else
54
61
  post = build_purchase_request(money, payment_or_customer_id, options)
55
- post[:customer_id] ? endpoint = ENDPOINTS[:customer_id_sale] : endpoint = ENDPOINTS[:keyed_sale]
62
+ endpoint = if payment_or_customer_id.kind_of?(Check)
63
+ ENDPOINTS[:ach_sale]
64
+ elsif options[:check_transaction]
65
+ ENDPOINTS[:ach_customer_sale]
66
+ elsif post[:customer_id]
67
+ ENDPOINTS[:customer_id_sale]
68
+ else
69
+ ENDPOINTS[:keyed_sale]
70
+ end
56
71
  response = commit(endpoint, post)
57
72
  check_token_response(response, endpoint, post, options)
58
73
  end
@@ -63,12 +78,16 @@ module ActiveMerchant #:nodoc:
63
78
  add_amount(post, money, options)
64
79
  if customer_id?(payment_or_customer_id)
65
80
  post[:customer_id] = payment_or_customer_id
66
- endpoint = ENDPOINTS[:customer_id_auth]
81
+ endpoint = if options[:check_transaction]
82
+ ENDPOINTS[:ach_customer_authorize]
83
+ else
84
+ ENDPOINTS[:customer_id_auth]
85
+ end
67
86
  else
68
87
  add_payment(post, payment_or_customer_id)
69
88
  add_address(post, payment_or_customer_id, options)
70
89
  add_customer_data(post, options)
71
- endpoint = ENDPOINTS[:keyed_auth]
90
+ endpoint = payment_or_customer_id.kind_of?(Check) ? ENDPOINTS[:ach_authorize] : ENDPOINTS[:keyed_auth]
72
91
  end
73
92
  response = commit(endpoint, post)
74
93
  check_token_response(response, endpoint, post, options)
@@ -82,8 +101,13 @@ module ActiveMerchant #:nodoc:
82
101
  end
83
102
  else
84
103
  post = build_capture_request(money, authorization, options)
85
- response = commit(ENDPOINTS[:capture], post)
86
- check_token_response(response, ENDPOINTS[:capture], post, options)
104
+ endpoint = if options[:check_transaction]
105
+ ENDPOINTS[:ach_capture]
106
+ else
107
+ ENDPOINTS[:capture]
108
+ end
109
+ response = commit(endpoint, post)
110
+ check_token_response(response, endpoint, post, options)
87
111
  end
88
112
  end
89
113
 
@@ -91,17 +115,29 @@ module ActiveMerchant #:nodoc:
91
115
  # currently only support full and partial refunds of settled transactions via a transaction ID
92
116
  post = {}
93
117
  add_amount(post, money, options)
94
- post[:transaction_id] = authorization
95
- response = commit(ENDPOINTS[:transaction_refund], post)
96
- check_token_response(response, ENDPOINTS[:transaction_refund], post, options)
118
+ if options[:check_transaction]
119
+ post[:check_transaction_id] = authorization
120
+ endpoint = ENDPOINTS[:ach_refund]
121
+ else
122
+ post[:transaction_id] = authorization
123
+ endpoint = ENDPOINTS[:transaction_refund]
124
+ end
125
+ response = commit(endpoint, post)
126
+ check_token_response(response, endpoint, post, options)
97
127
  end
98
128
 
99
129
  def void(authorization, options = {})
100
130
  post = {}
101
- post[:transaction_id] = authorization
131
+ if options[:check_transaction]
132
+ post[:check_transaction_id] = authorization
133
+ endpoint = ENDPOINTS[:ach_void]
134
+ else
135
+ post[:transaction_id] = authorization
136
+ endpoint = ENDPOINTS[:transaction_void]
137
+ end
102
138
 
103
- response = commit(ENDPOINTS[:transaction_void], post)
104
- check_token_response(response, ENDPOINTS[:transaction_void], post, options)
139
+ response = commit(endpoint, post)
140
+ check_token_response(response, endpoint, post, options)
105
141
  end
106
142
 
107
143
  def verify(credit_card, options = {})
@@ -175,7 +211,11 @@ module ActiveMerchant #:nodoc:
175
211
 
176
212
  def build_capture_request(money, authorization, options)
177
213
  post = {}
178
- post[:transaction_id] = authorization
214
+ if options[:check_transaction]
215
+ post[:check_transaction_id] = authorization
216
+ else
217
+ post[:transaction_id] = authorization
218
+ end
179
219
  add_amount(post, money, options)
180
220
 
181
221
  post
@@ -234,10 +274,16 @@ module ActiveMerchant #:nodoc:
234
274
  end
235
275
 
236
276
  def add_payment(post, payment)
237
- post[:credit_card] = {}
238
- post[:credit_card][:number] = payment.number
239
- post[:credit_card][:expiration_month] = payment.month
240
- post[:credit_card][:expiration_year] = payment.year
277
+ if payment.kind_of?(Check)
278
+ post[:check] = {}
279
+ post[:check][:account_number] = payment.account_number
280
+ post[:check][:routing_number] = payment.routing_number
281
+ else
282
+ post[:credit_card] = {}
283
+ post[:credit_card][:number] = payment.number
284
+ post[:credit_card][:expiration_month] = payment.month
285
+ post[:credit_card][:expiration_year] = payment.year
286
+ end
241
287
  end
242
288
 
243
289
  def add_level_3_data(post, options)
@@ -380,7 +426,7 @@ module ActiveMerchant #:nodoc:
380
426
  if action == ENDPOINTS[:store]
381
427
  response['customer_id']
382
428
  else
383
- response['transaction_id']
429
+ response['transaction_id'] || response['check_transaction_id']
384
430
  end
385
431
  end
386
432
 
@@ -41,6 +41,7 @@ module ActiveMerchant
41
41
  add_soft_descriptors(params, options)
42
42
  add_level2_data(params, options)
43
43
  add_stored_credentials(params, options)
44
+ add_external_three_ds(params, payment_method, options)
44
45
 
45
46
  commit(params, options)
46
47
  end
@@ -56,6 +57,7 @@ module ActiveMerchant
56
57
  add_soft_descriptors(params, options)
57
58
  add_level2_data(params, options)
58
59
  add_stored_credentials(params, options)
60
+ add_external_three_ds(params, payment_method, options)
59
61
 
60
62
  commit(params, options)
61
63
  end
@@ -125,6 +127,7 @@ module ActiveMerchant
125
127
  gsub(%r((Apikey: )(\w|-)+), '\1[FILTERED]').
126
128
  gsub(%r((\\?"card_number\\?":\\?")\d+), '\1[FILTERED]').
127
129
  gsub(%r((\\?"cvv\\?":\\?")\d+), '\1[FILTERED]').
130
+ gsub(%r((\\?"cvv\\?":\\?)\d+), '\1[FILTERED]').
128
131
  gsub(%r((\\?"account_number\\?":\\?")\d+), '\1[FILTERED]').
129
132
  gsub(%r((\\?"routing_number\\?":\\?")\d+), '\1[FILTERED]').
130
133
  gsub(%r((\\?card_number=)\d+(&?)), '\1[FILTERED]').
@@ -132,11 +135,33 @@ module ActiveMerchant
132
135
  gsub(%r((\\?apikey=)\w+(&?)), '\1[FILTERED]').
133
136
  gsub(%r{(\\?"credit_card\.card_number\\?":)(\\?"[^"]+\\?")}, '\1[FILTERED]').
134
137
  gsub(%r{(\\?"credit_card\.cvv\\?":)(\\?"[^"]+\\?")}, '\1[FILTERED]').
135
- gsub(%r{(\\?"apikey\\?":)(\\?"[^"]+\\?")}, '\1[FILTERED]')
138
+ gsub(%r{(\\?"apikey\\?":)(\\?"[^"]+\\?")}, '\1[FILTERED]').
139
+ gsub(%r{(\\?"cavv\\?":)(\\?"[^"]+\\?")}, '\1[FILTERED]').
140
+ gsub(%r{(\\?"xid\\?":)(\\?"[^"]+\\?")}, '\1[FILTERED]')
136
141
  end
137
142
 
138
143
  private
139
144
 
145
+ def add_external_three_ds(params, payment_method, options)
146
+ return unless three_ds = options[:three_d_secure]
147
+
148
+ params[:'3DS'] = {
149
+ program_protocol: three_ds[:version][0],
150
+ directory_server_transaction_id: three_ds[:ds_transaction_id],
151
+ cardholder_name: payment_method.name,
152
+ card_number: payment_method.number,
153
+ exp_date: format_exp_date(payment_method.month, payment_method.year),
154
+ cvv: payment_method.verification_value,
155
+ xid: three_ds[:acs_transaction_id],
156
+ cavv: three_ds[:cavv],
157
+ wallet_provider_id: 'NO_WALLET',
158
+ type: 'D'
159
+ }.compact
160
+
161
+ params[:eci_indicator] = options[:three_d_secure][:eci]
162
+ params[:method] = '3DS'
163
+ end
164
+
140
165
  def add_invoice(params, options)
141
166
  params[:merchant_ref] = options[:order_id]
142
167
  end
@@ -152,6 +177,8 @@ module ActiveMerchant
152
177
  def add_authorization_info(params, authorization, options = {})
153
178
  transaction_id, transaction_tag, method, = authorization.split('|')
154
179
  params[:method] = method == 'token' ? 'credit_card' : method
180
+ # If the previous transaction `method` value was 3DS, it needs to be set to `credit_card` on follow up transactions
181
+ params[:method] = 'credit_card' if method == '3DS'
155
182
 
156
183
  if options[:reversal_id]
157
184
  params[:reversal_id] = options[:reversal_id]
@@ -178,6 +205,8 @@ module ActiveMerchant
178
205
  add_echeck(params, payment_method, options)
179
206
  elsif payment_method.is_a? String
180
207
  add_token(params, payment_method, options)
208
+ elsif payment_method.is_a? NetworkTokenizationCreditCard
209
+ add_network_tokenization(params, payment_method, options)
181
210
  else
182
211
  add_creditcard(params, payment_method)
183
212
  end
@@ -190,7 +219,7 @@ module ActiveMerchant
190
219
  tele_check[:check_type] = 'P'
191
220
  tele_check[:routing_number] = echeck.routing_number
192
221
  tele_check[:account_number] = echeck.account_number
193
- tele_check[:accountholder_name] = "#{echeck.first_name} #{echeck.last_name}"
222
+ tele_check[:accountholder_name] = name_from_payment_method(echeck)
194
223
  tele_check[:customer_id_type] = options[:customer_id_type] if options[:customer_id_type]
195
224
  tele_check[:customer_id_number] = options[:customer_id_number] if options[:customer_id_number]
196
225
  tele_check[:client_email] = options[:client_email] if options[:client_email]
@@ -233,10 +262,37 @@ module ActiveMerchant
233
262
  card
234
263
  end
235
264
 
265
+ def add_network_tokenization(params, payment_method, options)
266
+ nt_card = {}
267
+ nt_card[:type] = 'D'
268
+ nt_card[:cardholder_name] = name_from_payment_method(payment_method) || name_from_address(options)
269
+ nt_card[:card_number] = payment_method.number
270
+ nt_card[:exp_date] = format_exp_date(payment_method.month, payment_method.year)
271
+ nt_card[:cvv] = payment_method.verification_value
272
+ nt_card[:xid] = payment_method.payment_cryptogram unless payment_method.payment_cryptogram.empty? || payment_method.brand.include?('american_express')
273
+ nt_card[:cavv] = payment_method.payment_cryptogram unless payment_method.payment_cryptogram.empty?
274
+ nt_card[:wallet_provider_id] = 'APPLE_PAY'
275
+
276
+ params['3DS'] = nt_card
277
+ params[:method] = '3DS'
278
+ params[:eci_indicator] = payment_method.eci.nil? ? '5' : payment_method.eci
279
+ end
280
+
236
281
  def format_exp_date(month, year)
237
282
  "#{format(month, :two_digits)}#{format(year, :two_digits)}"
238
283
  end
239
284
 
285
+ def name_from_address(options)
286
+ return unless address = options[:billing_address]
287
+ return address[:name] if address[:name]
288
+ end
289
+
290
+ def name_from_payment_method(payment_method)
291
+ return unless payment_method.first_name && payment_method.last_name
292
+
293
+ return "#{payment_method.first_name} #{payment_method.last_name}"
294
+ end
295
+
240
296
  def add_address(params, options)
241
297
  address = options[:billing_address]
242
298
  return unless address
@@ -279,8 +335,7 @@ module ActiveMerchant
279
335
  end
280
336
 
281
337
  def original_transaction_id(options)
282
- return options[:cardbrand_original_transaction_id] if options[:cardbrand_original_transaction_id]
283
- return options[:stored_credential][:network_transaction_id] if options.dig(:stored_credential, :network_transaction_id)
338
+ return options[:cardbrand_original_transaction_id] || options.dig(:stored_credential, :network_transaction_id)
284
339
  end
285
340
 
286
341
  def initiator(options)
@@ -137,6 +137,10 @@ module ActiveMerchant #:nodoc:
137
137
  commit_card('delete', post)
138
138
  end
139
139
 
140
+ def inquire(authorization, options = {})
141
+ commit_transaction('inquire', authorization)
142
+ end
143
+
140
144
  def supports_scrubbing?
141
145
  true
142
146
  end
@@ -232,12 +236,20 @@ module ActiveMerchant #:nodoc:
232
236
  end
233
237
 
234
238
  def commit_raw(object, action, parameters)
235
- url = "#{(test? ? test_url : live_url)}#{object}/#{action}"
236
-
237
- begin
238
- raw_response = ssl_post(url, post_data(parameters), headers)
239
- rescue ResponseError => e
240
- raw_response = e.response.body
239
+ if action == 'inquire'
240
+ url = "#{(test? ? test_url : live_url)}#{object}/#{parameters}"
241
+ begin
242
+ raw_response = ssl_get(url, headers)
243
+ rescue ResponseError => e
244
+ raw_response = e.response.body
245
+ end
246
+ else
247
+ url = "#{(test? ? test_url : live_url)}#{object}/#{action}"
248
+ begin
249
+ raw_response = ssl_post(url, post_data(parameters), headers)
250
+ rescue ResponseError => e
251
+ raw_response = e.response.body
252
+ end
241
253
  end
242
254
 
243
255
  begin
@@ -13,6 +13,10 @@ module ActiveMerchant #:nodoc:
13
13
  (@params['PaymentDetails']||{})
14
14
  end
15
15
 
16
+ def checkout_status
17
+ (@params['CheckoutStatus']||{})
18
+ end
19
+
16
20
  def name
17
21
  payer = (info['PayerName']||{})
18
22
  [payer['FirstName'], payer['MiddleName'], payer['LastName']].compact.join(' ')
@@ -108,6 +108,7 @@ module ActiveMerchant #:nodoc:
108
108
  xml.tag! 'n2:PaymentAction', action
109
109
  xml.tag! 'n2:Token', options[:token]
110
110
  xml.tag! 'n2:PayerID', options[:payer_id]
111
+ xml.tag! 'n2:MsgSubID', options[:idempotency_key] if options[:idempotency_key]
111
112
  add_payment_details(xml, money, currency_code, options)
112
113
  end
113
114
  end
@@ -251,6 +252,7 @@ module ActiveMerchant #:nodoc:
251
252
  add_payment_details(xml, money, currency_code, options)
252
253
  xml.tag! 'n2:IPAddress', options[:ip]
253
254
  xml.tag! 'n2:MerchantSessionId', options[:merchant_session_id] if options[:merchant_session_id].present?
255
+ xml.tag! 'n2:MsgSubID', options[:idempotency_key] if options[:idempotency_key]
254
256
  end
255
257
  end
256
258
  end
@@ -17,14 +17,8 @@ module ActiveMerchant #:nodoc:
17
17
 
18
18
  def purchase(money, payment, options = {})
19
19
  post = {}
20
- add_invoice(post, money, options)
21
- add_payment(post, payment)
22
- add_billing_address(post, options)
23
- add_merchant_details(post, options)
20
+ add_auth_purchase_params(post, money, payment, options)
24
21
  add_airline_travel_details(post, options)
25
- add_customer_data(post, payment, options) unless payment.is_a?(String)
26
- add_three_d_secure(post, payment, options) if options[:three_d_secure]
27
- add_stored_credential(post, options) if options[:stored_credential]
28
22
  add_split_pay_details(post, options)
29
23
  post[:settleWithAuth] = true
30
24
 
@@ -33,13 +27,7 @@ module ActiveMerchant #:nodoc:
33
27
 
34
28
  def authorize(money, payment, options = {})
35
29
  post = {}
36
- add_invoice(post, money, options)
37
- add_payment(post, payment)
38
- add_billing_address(post, options)
39
- add_merchant_details(post, options)
40
- add_customer_data(post, payment, options) unless payment.is_a?(String)
41
- add_three_d_secure(post, payment, options) if options[:three_d_secure]
42
- add_stored_credential(post, options) if options[:stored_credential]
30
+ add_auth_purchase_params(post, money, payment, options)
43
31
 
44
32
  commit(:post, 'auths', post, options)
45
33
  end
@@ -111,6 +99,17 @@ module ActiveMerchant #:nodoc:
111
99
 
112
100
  private
113
101
 
102
+ def add_auth_purchase_params(post, money, payment, options)
103
+ add_invoice(post, money, options)
104
+ add_payment(post, payment)
105
+ add_billing_address(post, options)
106
+ add_merchant_details(post, options)
107
+ add_customer_data(post, payment, options) unless payment.is_a?(String)
108
+ add_three_d_secure(post, payment, options) if options[:three_d_secure]
109
+ add_stored_credential(post, options) if options[:stored_credential]
110
+ add_funding_transaction(post, options)
111
+ end
112
+
114
113
  # Customer data can be included in transactions where the payment method is a credit card
115
114
  # but should not be sent when the payment method is a token
116
115
  def add_customer_data(post, creditcard, options)
@@ -286,6 +285,15 @@ module ActiveMerchant #:nodoc:
286
285
  post[:splitpay] = split_pay
287
286
  end
288
287
 
288
+ def add_funding_transaction(post, options)
289
+ return unless options[:funding_transaction]
290
+
291
+ post[:fundingTransaction] = {}
292
+ post[:fundingTransaction][:type] = options[:funding_transaction]
293
+ post[:profile] ||= {}
294
+ post[:profile][:merchantCustomerId] = options[:customer_id] || SecureRandom.hex(12)
295
+ end
296
+
289
297
  def add_stored_credential(post, options)
290
298
  return unless options[:stored_credential]
291
299
 
@@ -313,6 +313,9 @@ module ActiveMerchant #:nodoc:
313
313
  def add_extra_parameters(post, options)
314
314
  extra_parameters = {}
315
315
  extra_parameters[:INSTALLMENTS_NUMBER] = options[:installments_number] || 1
316
+ extra_parameters[:EXTRA1] = options[:extra_1] if options[:extra_1]
317
+ extra_parameters[:EXTRA2] = options[:extra_2] if options[:extra_2]
318
+ extra_parameters[:EXTRA3] = options[:extra_3] if options[:extra_3]
316
319
  post[:transaction][:extraParameters] = extra_parameters
317
320
  end
318
321
 
@@ -452,7 +455,7 @@ module ActiveMerchant #:nodoc:
452
455
  when 'verify_credentials'
453
456
  response['error'] || 'FAILED'
454
457
  else
455
- response['transactionResponse']['errorCode'] || response['transactionResponse']['responseCode'] if response['transactionResponse']
458
+ response['transactionResponse']['paymentNetworkResponseCode'] || response['transactionResponse']['errorCode'] if response['transactionResponse']
456
459
  end
457
460
  end
458
461