activemerchant 1.125.0 → 1.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +316 -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 +91 -23
  6. data/lib/active_merchant/billing/gateway.rb +2 -1
  7. data/lib/active_merchant/billing/gateways/adyen.rb +74 -12
  8. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  9. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -4
  11. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
  12. data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/blue_snap.rb +53 -22
  15. data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
  16. data/lib/active_merchant/billing/gateways/borgun.rb +56 -16
  17. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
  18. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  19. data/lib/active_merchant/billing/gateways/braintree_blue.rb +151 -32
  20. data/lib/active_merchant/billing/gateways/card_connect.rb +28 -10
  21. data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
  22. data/lib/active_merchant/billing/gateways/checkout_v2.rb +228 -57
  23. data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
  24. data/lib/active_merchant/billing/gateways/credorax.rb +56 -26
  25. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  26. data/lib/active_merchant/billing/gateways/cyber_source.rb +112 -58
  27. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
  28. data/lib/active_merchant/billing/gateways/d_local.rb +93 -5
  29. data/lib/active_merchant/billing/gateways/decidir.rb +32 -5
  30. data/lib/active_merchant/billing/gateways/decidir_plus.rb +185 -14
  31. data/lib/active_merchant/billing/gateways/ebanx.rb +39 -26
  32. data/lib/active_merchant/billing/gateways/element.rb +21 -1
  33. data/lib/active_merchant/billing/gateways/global_collect.rb +98 -37
  34. data/lib/active_merchant/billing/gateways/ipg.rb +14 -10
  35. data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
  36. data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
  37. data/lib/active_merchant/billing/gateways/litle.rb +118 -6
  38. data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
  39. data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
  40. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
  41. data/lib/active_merchant/billing/gateways/monei.rb +2 -0
  42. data/lib/active_merchant/billing/gateways/moneris.rb +55 -13
  43. data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
  44. data/lib/active_merchant/billing/gateways/nmi.rb +12 -7
  45. data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
  46. data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
  47. data/lib/active_merchant/billing/gateways/orbital.rb +378 -335
  48. data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
  49. data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
  50. data/lib/active_merchant/billing/gateways/payflow.rb +62 -0
  51. data/lib/active_merchant/billing/gateways/paymentez.rb +44 -13
  52. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  53. data/lib/active_merchant/billing/gateways/paysafe.rb +37 -29
  54. data/lib/active_merchant/billing/gateways/payu_latam.rb +28 -15
  55. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  56. data/lib/active_merchant/billing/gateways/priority.rb +185 -140
  57. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  58. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  59. data/lib/active_merchant/billing/gateways/redsys.rb +9 -5
  60. data/lib/active_merchant/billing/gateways/safe_charge.rb +1 -4
  61. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
  62. data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
  63. data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
  64. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  65. data/lib/active_merchant/billing/gateways/stripe.rb +25 -3
  66. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +155 -70
  67. data/lib/active_merchant/billing/gateways/tns.rb +2 -5
  68. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  69. data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
  70. data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
  71. data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
  72. data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
  73. data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
  74. data/lib/active_merchant/billing/gateways/worldpay.rb +117 -9
  75. data/lib/active_merchant/billing/response.rb +15 -1
  76. data/lib/active_merchant/connection.rb +0 -2
  77. data/lib/active_merchant/country.rb +1 -0
  78. data/lib/active_merchant/errors.rb +4 -1
  79. data/lib/active_merchant/version.rb +1 -1
  80. metadata +28 -3
@@ -83,6 +83,11 @@ module ActiveMerchant #:nodoc:
83
83
  commit(:post, "payments/#{authorization}/refunds", post)
84
84
  end
85
85
 
86
+ def inquire(authorization, options = {})
87
+ options[:action] = 'inquire'
88
+ commit(:get, "payments/#{authorization}", nil, options)
89
+ end
90
+
86
91
  def verify(credit_card, options = {})
87
92
  raise ArgumentError, 'Verify is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
88
93
 
@@ -117,11 +122,11 @@ module ActiveMerchant #:nodoc:
117
122
  post[:establishment_name] = options[:establishment_name] if options[:establishment_name]
118
123
  post[:fraud_detection] = add_fraud_detection(options[:fraud_detection]) if options[:fraud_detection].present?
119
124
  post[:site_id] = options[:site_id] if options[:site_id]
120
- post[:sub_payments] = []
121
125
 
122
126
  add_invoice(post, money, options)
123
127
  add_payment(post, credit_card, options)
124
128
  add_aggregate_data(post, options) if options[:aggregate_data]
129
+ add_sub_payments(post, options)
125
130
  end
126
131
 
127
132
  def add_payment_method_id(credit_card, options)
@@ -210,6 +215,22 @@ module ActiveMerchant #:nodoc:
210
215
  post[:aggregate_data] = aggregate_data
211
216
  end
212
217
 
218
+ def add_sub_payments(post, options)
219
+ # sub_payments field is required for purchase transactions, even if empty
220
+ post[:sub_payments] = []
221
+
222
+ return unless sub_payments = options[:sub_payments]
223
+
224
+ sub_payments.each do |sub_payment|
225
+ sub_payment_hash = {
226
+ site_id: sub_payment[:site_id],
227
+ installments: sub_payment[:installments].to_i,
228
+ amount: sub_payment[:amount].to_i
229
+ }
230
+ post[:sub_payments] << sub_payment_hash
231
+ end
232
+ end
233
+
213
234
  def add_fraud_detection(options = {})
214
235
  {}.tap do |hsh|
215
236
  hsh[:send_to_cs] = options[:send_to_cs] if valid_fraud_detection_option?(options[:send_to_cs]) # true/false
@@ -251,7 +272,7 @@ module ActiveMerchant #:nodoc:
251
272
  response = parse(raw_response)
252
273
  end
253
274
 
254
- success = success_from(response)
275
+ success = success_from(response, options)
255
276
  Response.new(
256
277
  success,
257
278
  message_from(success, response),
@@ -263,7 +284,7 @@ module ActiveMerchant #:nodoc:
263
284
  end
264
285
 
265
286
  def post_data(parameters = {})
266
- parameters.to_json
287
+ parameters&.to_json
267
288
  end
268
289
 
269
290
  def parse(body)
@@ -295,8 +316,14 @@ module ActiveMerchant #:nodoc:
295
316
  message
296
317
  end
297
318
 
298
- def success_from(response)
299
- response['status'] == 'approved' || response['status'] == 'pre_approved'
319
+ def success_from(response, options)
320
+ status = %w(approved pre_approved)
321
+
322
+ if options[:action] == 'inquire'
323
+ status.include?(response['status']) || response['status'] == 'rejected'
324
+ else
325
+ status.include?(response['status'])
326
+ end
300
327
  end
301
328
 
302
329
  def authorization_from(response)
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
6
6
 
7
7
  self.supported_countries = ['AR']
8
8
  self.default_currency = 'ARS'
9
- self.supported_cardtypes = %i[visa master american_express discover]
9
+ self.supported_cardtypes = %i[visa master american_express discover diners_club naranja cabal]
10
10
 
11
11
  self.homepage_url = 'http://decidir.com.ar/home'
12
12
  self.display_name = 'Decidir Plus'
@@ -18,20 +18,44 @@ module ActiveMerchant #:nodoc:
18
18
 
19
19
  def purchase(money, payment, options = {})
20
20
  post = {}
21
+ build_purchase_authorize_request(post, money, payment, options)
21
22
 
22
- add_payment(post, payment, options)
23
- add_purchase_data(post, money, payment, options)
23
+ commit(:post, 'payments', post)
24
+ end
25
+
26
+ def authorize(money, payment, options = {})
27
+ post = {}
28
+ build_purchase_authorize_request(post, money, payment, options)
24
29
 
25
30
  commit(:post, 'payments', post)
26
31
  end
27
32
 
33
+ def capture(money, authorization, options = {})
34
+ post = {}
35
+ post[:amount] = money
36
+
37
+ commit(:put, "payments/#{add_reference(authorization)}", post)
38
+ end
39
+
28
40
  def refund(money, authorization, options = {})
29
41
  post = {}
30
42
  post[:amount] = money
31
43
 
44
+ commit(:post, "payments/#{add_reference(authorization)}/refunds", post)
45
+ end
46
+
47
+ def void(authorization, options = {})
32
48
  commit(:post, "payments/#{add_reference(authorization)}/refunds")
33
49
  end
34
50
 
51
+ def verify(credit_card, options = {})
52
+ MultiResponse.run(:use_first_response) do |r|
53
+ r.process { store(credit_card, options) }
54
+ r.process { authorize(100, r.authorization, options) }
55
+ r.process(:ignore_result) { void(r.authorization, options) }
56
+ end
57
+ end
58
+
35
59
  def store(payment, options = {})
36
60
  post = {}
37
61
  add_payment(post, payment, options)
@@ -39,6 +63,10 @@ module ActiveMerchant #:nodoc:
39
63
  commit(:post, 'tokens', post)
40
64
  end
41
65
 
66
+ def unstore(customer_token)
67
+ commit(:delete, "cardtokens/#{customer_token}")
68
+ end
69
+
42
70
  def supports_scrubbing?
43
71
  true
44
72
  end
@@ -52,6 +80,13 @@ module ActiveMerchant #:nodoc:
52
80
 
53
81
  private
54
82
 
83
+ def build_purchase_authorize_request(post, money, payment, options)
84
+ add_customer_data(post, options)
85
+ add_payment(post, payment, options)
86
+ add_purchase_data(post, money, payment, options)
87
+ add_fraud_detection(post, options)
88
+ end
89
+
55
90
  def add_reference(authorization)
56
91
  return unless authorization
57
92
 
@@ -65,26 +100,64 @@ module ActiveMerchant #:nodoc:
65
100
  post[:bin] = bin
66
101
  else
67
102
  post[:card_number] = payment.number
68
- post[:card_expiration_month] = payment.month.to_s.rjust(2, '0')
69
- post[:card_expiration_year] = payment.year.to_s[-2..-1]
103
+ post[:card_expiration_month] = format(payment.month, :two_digits)
104
+ post[:card_expiration_year] = format(payment.year, :two_digits)
70
105
  post[:security_code] = payment.verification_value.to_s
71
- post[:card_holder_name] = payment.name
106
+ post[:card_holder_name] = payment.name.empty? ? options[:name_override] : payment.name
72
107
  post[:card_holder_identification] = {}
73
- post[:card_holder_identification][:type] = options[:dni]
74
- post[:card_holder_identification][:number] = options[:card_holder_identification_number]
108
+ post[:card_holder_identification][:type] = options[:card_holder_identification_type] if options[:card_holder_identification_type]
109
+ post[:card_holder_identification][:number] = options[:card_holder_identification_number] if options[:card_holder_identification_number]
110
+
111
+ # additional data used for Visa transactions
112
+ post[:card_holder_door_number] = options[:card_holder_door_number].to_i if options[:card_holder_door_number]
113
+ post[:card_holder_birthday] = options[:card_holder_birthday] if options[:card_holder_birthday]
75
114
  end
76
115
  end
77
116
 
117
+ def add_customer_data(post, options = {})
118
+ return unless customer = options[:customer]
119
+
120
+ post[:customer] = {}
121
+ post[:customer][:id] = customer[:id] if customer[:id]
122
+ post[:customer][:email] = customer[:email] if customer[:email]
123
+ end
124
+
78
125
  def add_purchase_data(post, money, payment, options = {})
79
126
  post[:site_transaction_id] = options[:site_transaction_id] || SecureRandom.hex
80
- post[:payment_method_id] = 1
127
+ post[:payment_method_id] = add_payment_method_id(options)
81
128
  post[:amount] = money
82
129
  post[:currency] = options[:currency] || self.default_currency
83
130
  post[:installments] = options[:installments] || 1
84
131
  post[:payment_type] = options[:payment_type] || 'single'
132
+ post[:establishment_name] = options[:establishment_name] if options[:establishment_name]
133
+
134
+ add_aggregate_data(post, options) if options[:aggregate_data]
85
135
  add_sub_payments(post, options)
86
136
  end
87
137
 
138
+ def add_aggregate_data(post, options)
139
+ aggregate_data = {}
140
+ data = options[:aggregate_data]
141
+ aggregate_data[:indicator] = data[:indicator] if data[:indicator]
142
+ aggregate_data[:identification_number] = data[:identification_number] if data[:identification_number]
143
+ aggregate_data[:bill_to_pay] = data[:bill_to_pay] if data[:bill_to_pay]
144
+ aggregate_data[:bill_to_refund] = data[:bill_to_refund] if data[:bill_to_refund]
145
+ aggregate_data[:merchant_name] = data[:merchant_name] if data[:merchant_name]
146
+ aggregate_data[:street] = data[:street] if data[:street]
147
+ aggregate_data[:number] = data[:number] if data[:number]
148
+ aggregate_data[:postal_code] = data[:postal_code] if data[:postal_code]
149
+ aggregate_data[:category] = data[:category] if data[:category]
150
+ aggregate_data[:channel] = data[:channel] if data[:channel]
151
+ aggregate_data[:geographic_code] = data[:geographic_code] if data[:geographic_code]
152
+ aggregate_data[:city] = data[:city] if data[:city]
153
+ aggregate_data[:merchant_id] = data[:merchant_id] if data[:merchant_id]
154
+ aggregate_data[:province] = data[:province] if data[:province]
155
+ aggregate_data[:country] = data[:country] if data[:country]
156
+ aggregate_data[:merchant_email] = data[:merchant_email] if data[:merchant_email]
157
+ aggregate_data[:merchant_phone] = data[:merchant_phone] if data[:merchant_phone]
158
+ post[:aggregate_data] = aggregate_data
159
+ end
160
+
88
161
  def add_sub_payments(post, options)
89
162
  # sub_payments field is required for purchase transactions, even if empty
90
163
  post[:sub_payments] = []
@@ -94,14 +167,78 @@ module ActiveMerchant #:nodoc:
94
167
  sub_payments.each do |sub_payment|
95
168
  sub_payment_hash = {
96
169
  site_id: sub_payment[:site_id],
97
- installments: sub_payment[:installments],
98
- amount: sub_payment[:amount]
170
+ installments: sub_payment[:installments].to_i,
171
+ amount: sub_payment[:amount].to_i
99
172
  }
100
173
  post[:sub_payments] << sub_payment_hash
101
174
  end
102
175
  end
103
176
 
177
+ def add_payment_method_id(options)
178
+ return options[:payment_method_id].to_i if options[:payment_method_id]
179
+
180
+ if options[:debit]
181
+ case options[:card_brand]
182
+ when 'visa'
183
+ 31
184
+ when 'master'
185
+ 105
186
+ when 'maestro'
187
+ 106
188
+ when 'cabal'
189
+ 108
190
+ else
191
+ 31
192
+ end
193
+ else
194
+ case options[:card_brand]
195
+ when 'visa'
196
+ 1
197
+ when 'master'
198
+ 104
199
+ when 'american_express'
200
+ 65
201
+ when 'american_express_prisma'
202
+ 111
203
+ when 'cabal'
204
+ 63
205
+ when 'diners_club'
206
+ 8
207
+ else
208
+ 1
209
+ end
210
+ end
211
+ end
212
+
213
+ def add_fraud_detection(post, options)
214
+ return unless fraud_detection = options[:fraud_detection]
215
+
216
+ {}.tap do |hsh|
217
+ hsh[:send_to_cs] = fraud_detection[:send_to_cs] == 'true' # true/false
218
+ hsh[:channel] = fraud_detection[:channel] if fraud_detection[:channel]
219
+ hsh[:dispatch_method] = fraud_detection[:dispatch_method] if fraud_detection[:dispatch_method]
220
+ add_csmdds(hsh, fraud_detection)
221
+
222
+ post[:fraud_detection] = hsh
223
+ end
224
+ end
225
+
226
+ def add_csmdds(hsh, fraud_detection)
227
+ return unless fraud_detection[:csmdds]
228
+
229
+ csmdds_arr = []
230
+ fraud_detection[:csmdds].each do |csmdds|
231
+ csmdds_hsh = {}
232
+ csmdds_hsh[:code] = csmdds[:code].to_i
233
+ csmdds_hsh[:description] = csmdds[:description]
234
+ csmdds_arr.append(csmdds_hsh)
235
+ end
236
+ hsh[:csmdds] = csmdds_arr unless csmdds_arr.empty?
237
+ end
238
+
104
239
  def parse(body)
240
+ return {} if body.nil?
241
+
105
242
  JSON.parse(body)
106
243
  end
107
244
 
@@ -140,11 +277,13 @@ module ActiveMerchant #:nodoc:
140
277
  end
141
278
 
142
279
  def success_from(response)
143
- response.dig('status') == 'approved' || response.dig('status') == 'active'
280
+ response.dig('status') == 'approved' || response.dig('status') == 'active' || response.dig('status') == 'pre_approved' || response.empty?
144
281
  end
145
282
 
146
283
  def message_from(response)
147
- response.dig('status') || error_message(response) || response.dig('message')
284
+ return '' if response.empty?
285
+
286
+ rejected?(response) ? message_from_status_details(response) : response.dig('status') || error_message(response) || response.dig('message')
148
287
  end
149
288
 
150
289
  def authorization_from(response)
@@ -158,7 +297,24 @@ module ActiveMerchant #:nodoc:
158
297
  end
159
298
 
160
299
  def error_code_from(response)
161
- response.dig('error_type') unless success_from(response)
300
+ return if success_from(response)
301
+
302
+ error_code = nil
303
+ if error = response.dig('status_details', 'error')
304
+ error_code = error.dig('reason', 'id') || error['type']
305
+ elsif response['error_type']
306
+ error_code = response['error_type']
307
+ elsif response.dig('error', 'validation_errors')
308
+ error = response.dig('error')
309
+ validation_errors = error.dig('validation_errors', 0)
310
+ code = validation_errors['code'] if validation_errors && validation_errors['code']
311
+ param = validation_errors['param'] if validation_errors && validation_errors['param']
312
+ error_code = "#{error['error_type']} | #{code} | #{param}" if error['error_type']
313
+ elsif error = response.dig('error')
314
+ error_code = error.dig('reason', 'id')
315
+ end
316
+
317
+ error_code
162
318
  end
163
319
 
164
320
  def error_message(response)
@@ -168,6 +324,21 @@ module ActiveMerchant #:nodoc:
168
324
 
169
325
  "#{validation_errors.dig('code')}: #{validation_errors.dig('param')}"
170
326
  end
327
+
328
+ def rejected?(response)
329
+ return response.dig('status') == 'rejected'
330
+ end
331
+
332
+ def message_from_status_details(response)
333
+ return unless error = response.dig('status_details', 'error')
334
+ return message_from_fraud_detection(response) if error.dig('type') == 'cybersource_error'
335
+
336
+ "#{error.dig('type')}: #{error.dig('reason', 'description')}"
337
+ end
338
+
339
+ def message_from_fraud_detection(response)
340
+ return error_message(response.dig('fraud_detection', 'status', 'details'))
341
+ end
171
342
  end
172
343
  end
173
344
  end
@@ -6,18 +6,12 @@ module ActiveMerchant #:nodoc:
6
6
 
7
7
  self.supported_countries = %w(BR MX CO CL AR PE)
8
8
  self.default_currency = 'USD'
9
- self.supported_cardtypes = %i[visa master american_express discover diners_club]
9
+ self.supported_cardtypes = %i[visa master american_express discover diners_club elo hipercard]
10
10
 
11
11
  self.homepage_url = 'http://www.ebanx.com/'
12
12
  self.display_name = 'EBANX'
13
13
 
14
- CARD_BRAND = {
15
- visa: 'visa',
16
- master: 'master_card',
17
- american_express: 'amex',
18
- discover: 'discover',
19
- diners_club: 'diners'
20
- }
14
+ TAGS = ['Spreedly']
21
15
 
22
16
  URL_MAP = {
23
17
  purchase: 'direct',
@@ -25,7 +19,8 @@ module ActiveMerchant #:nodoc:
25
19
  capture: 'capture',
26
20
  refund: 'refund',
27
21
  void: 'cancel',
28
- store: 'token'
22
+ store: 'token',
23
+ inquire: 'query'
29
24
  }
30
25
 
31
26
  HTTP_METHOD = {
@@ -34,16 +29,17 @@ module ActiveMerchant #:nodoc:
34
29
  capture: :get,
35
30
  refund: :post,
36
31
  void: :get,
37
- store: :post
32
+ store: :post,
33
+ inquire: :get
38
34
  }
39
35
 
40
36
  VERIFY_AMOUNT_PER_COUNTRY = {
41
37
  'br' => 100,
42
38
  'ar' => 100,
43
- 'co' => 100,
39
+ 'co' => 50000,
44
40
  'pe' => 300,
45
- 'mx' => 300,
46
- 'cl' => 5000
41
+ 'mx' => 2000,
42
+ 'cl' => 80000
47
43
  }
48
44
 
49
45
  def initialize(options = {})
@@ -57,7 +53,7 @@ module ActiveMerchant #:nodoc:
57
53
  add_operation(post)
58
54
  add_invoice(post, money, options)
59
55
  add_customer_data(post, payment, options)
60
- add_card_or_token(post, payment)
56
+ add_card_or_token(post, payment, options)
61
57
  add_address(post, options)
62
58
  add_customer_responsible_person(post, payment, options)
63
59
  add_additional_data(post, options)
@@ -71,7 +67,7 @@ module ActiveMerchant #:nodoc:
71
67
  add_operation(post)
72
68
  add_invoice(post, money, options)
73
69
  add_customer_data(post, payment, options)
74
- add_card_or_token(post, payment)
70
+ add_card_or_token(post, payment, options)
75
71
  add_address(post, options)
76
72
  add_customer_responsible_person(post, payment, options)
77
73
  add_additional_data(post, options)
@@ -124,6 +120,14 @@ module ActiveMerchant #:nodoc:
124
120
  end
125
121
  end
126
122
 
123
+ def inquire(authorization, options = {})
124
+ post = {}
125
+ add_integration_key(post)
126
+ add_authorization(post, authorization)
127
+
128
+ commit(:inquire, post)
129
+ end
130
+
127
131
  def supports_scrubbing?
128
132
  true
129
133
  end
@@ -151,7 +155,7 @@ module ActiveMerchant #:nodoc:
151
155
 
152
156
  def add_customer_data(post, payment, options)
153
157
  post[:payment][:name] = customer_name(payment, options)
154
- post[:payment][:email] = options[:email] || 'unspecified@example.com'
158
+ post[:payment][:email] = options[:email]
155
159
  post[:payment][:document] = options[:document]
156
160
  post[:payment][:birth_date] = options[:birth_date] if options[:birth_date]
157
161
  end
@@ -183,16 +187,18 @@ module ActiveMerchant #:nodoc:
183
187
  post[:payment][:currency_code] = (options[:currency] || currency(money))
184
188
  post[:payment][:merchant_payment_code] = Digest::MD5.hexdigest(options[:order_id])
185
189
  post[:payment][:instalments] = options[:instalments] || 1
190
+ post[:payment][:order_number] = options[:order_id][0..39] if options[:order_id]
186
191
  end
187
192
 
188
- def add_card_or_token(post, payment)
189
- payment, brand = payment.split('|') if payment.is_a?(String)
190
- post[:payment][:payment_type_code] = payment.is_a?(String) ? brand : CARD_BRAND[payment.brand.to_sym]
193
+ def add_card_or_token(post, payment, options)
194
+ payment = payment.split('|')[0] if payment.is_a?(String)
195
+ post[:payment][:payment_type_code] = 'creditcard'
191
196
  post[:payment][:creditcard] = payment_details(payment)
197
+ post[:payment][:creditcard][:soft_descriptor] = options[:soft_descriptor] if options[:soft_descriptor]
192
198
  end
193
199
 
194
200
  def add_payment_details(post, payment)
195
- post[:payment_type_code] = CARD_BRAND[payment.brand.to_sym]
201
+ post[:payment_type_code] = 'creditcard'
196
202
  post[:creditcard] = payment_details(payment)
197
203
  end
198
204
 
@@ -215,6 +221,7 @@ module ActiveMerchant #:nodoc:
215
221
  post[:metadata] = {} if post[:metadata].nil?
216
222
  post[:metadata][:merchant_payment_code] = options[:order_id] if options[:order_id]
217
223
  post[:processing_type] = options[:processing_type] if options[:processing_type]
224
+ post[:payment][:tags] = TAGS
218
225
  end
219
226
 
220
227
  def parse(body)
@@ -252,13 +259,15 @@ module ActiveMerchant #:nodoc:
252
259
  end
253
260
 
254
261
  def success_from(action, response)
262
+ payment_status = response.try(:[], 'payment').try(:[], 'status')
263
+
255
264
  if %i[purchase capture refund].include?(action)
256
- response.try(:[], 'payment').try(:[], 'status') == 'CO'
265
+ payment_status == 'CO'
257
266
  elsif action == :authorize
258
- response.try(:[], 'payment').try(:[], 'status') == 'PE'
267
+ payment_status == 'PE'
259
268
  elsif action == :void
260
- response.try(:[], 'payment').try(:[], 'status') == 'CA'
261
- elsif action == :store
269
+ payment_status == 'CA'
270
+ elsif %i[store inquire].include?(action)
262
271
  response.try(:[], 'status') == 'SUCCESS'
263
272
  else
264
273
  false
@@ -273,7 +282,11 @@ module ActiveMerchant #:nodoc:
273
282
 
274
283
  def authorization_from(action, parameters, response)
275
284
  if action == :store
276
- "#{response.try(:[], 'token')}|#{CARD_BRAND[parameters[:payment_type_code].to_sym]}"
285
+ if success_from(action, response)
286
+ "#{response.try(:[], 'token')}|#{response['payment_type_code']}"
287
+ else
288
+ response.try(:[], 'token')
289
+ end
277
290
  else
278
291
  response.try(:[], 'payment').try(:[], 'hash')
279
292
  end
@@ -293,7 +306,7 @@ module ActiveMerchant #:nodoc:
293
306
  end
294
307
 
295
308
  def requires_http_get(action)
296
- return true if %i[capture void].include?(action)
309
+ return true if %i[capture void inquire].include?(action)
297
310
 
298
311
  false
299
312
  end
@@ -17,6 +17,11 @@ module ActiveMerchant #:nodoc:
17
17
  SERVICE_TEST_URL = 'https://certservices.elementexpress.com/express.asmx'
18
18
  SERVICE_LIVE_URL = 'https://services.elementexpress.com/express.asmx'
19
19
 
20
+ NETWORK_TOKEN_TYPE = {
21
+ apple_pay: '2',
22
+ google_pay: '1'
23
+ }
24
+
20
25
  def initialize(options = {})
21
26
  requires!(options, :account_id, :account_token, :application_id, :acceptor_id, :application_name, :application_version)
22
27
  super
@@ -171,6 +176,8 @@ module ActiveMerchant #:nodoc:
171
176
  add_payment_account_id(xml, payment)
172
177
  elsif payment.is_a?(Check)
173
178
  add_echeck(xml, payment)
179
+ elsif payment.is_a?(NetworkTokenizationCreditCard)
180
+ add_network_tokenization_card(xml, payment)
174
181
  else
175
182
  add_credit_card(xml, payment)
176
183
  end
@@ -200,7 +207,7 @@ module ActiveMerchant #:nodoc:
200
207
  xml.TransactionID options[:trans_id] if options[:trans_id]
201
208
  xml.TransactionAmount amount(money.to_i) if money
202
209
  xml.MarketCode market_code(money, options) if options[:market_code] || money
203
- xml.ReferenceNumber options[:order_id] || SecureRandom.hex(20)
210
+ xml.ReferenceNumber options[:order_id].present? ? options[:order_id][0, 50] : SecureRandom.hex(20)
204
211
  xml.TicketNumber options[:ticket_number] if options[:ticket_number]
205
212
  xml.MerchantSuppliedTransactionId options[:merchant_supplied_transaction_id] if options[:merchant_supplied_transaction_id]
206
213
  xml.PaymentType options[:payment_type] if options[:payment_type]
@@ -246,8 +253,21 @@ module ActiveMerchant #:nodoc:
246
253
  end
247
254
  end
248
255
 
256
+ def add_network_tokenization_card(xml, payment)
257
+ xml.card do
258
+ xml.CardNumber payment.number
259
+ xml.ExpirationMonth format(payment.month, :two_digits)
260
+ xml.ExpirationYear format(payment.year, :two_digits)
261
+ xml.CardholderName "#{payment.first_name} #{payment.last_name}"
262
+ xml.Cryptogram payment.payment_cryptogram
263
+ xml.ElectronicCommerceIndicator payment.eci if payment.eci.present?
264
+ xml.WalletType NETWORK_TOKEN_TYPE.fetch(payment.source, '0')
265
+ end
266
+ end
267
+
249
268
  def add_address(xml, options)
250
269
  if address = options[:billing_address] || options[:address]
270
+ address[:email] ||= options[:email]
251
271
  xml.address do
252
272
  xml.BillingAddress1 address[:address1] if address[:address1]
253
273
  xml.BillingAddress2 address[:address2] if address[:address2]