activemerchant 1.125.0 → 1.126.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.
- checksums.yaml +4 -4
- data/CHANGELOG +75 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +12 -0
- data/lib/active_merchant/billing/gateway.rb +2 -1
- data/lib/active_merchant/billing/gateways/adyen.rb +7 -4
- data/lib/active_merchant/billing/gateways/airwallex.rb +341 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
- data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/blue_snap.rb +31 -21
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +87 -15
- data/lib/active_merchant/billing/gateways/card_connect.rb +1 -1
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +1 -1
- data/lib/active_merchant/billing/gateways/credorax.rb +10 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +13 -33
- data/lib/active_merchant/billing/gateways/d_local.rb +49 -0
- data/lib/active_merchant/billing/gateways/decidir.rb +17 -1
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +185 -14
- data/lib/active_merchant/billing/gateways/ebanx.rb +3 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +26 -16
- data/lib/active_merchant/billing/gateways/ipg.rb +1 -2
- data/lib/active_merchant/billing/gateways/litle.rb +93 -1
- data/lib/active_merchant/billing/gateways/moneris.rb +35 -8
- data/lib/active_merchant/billing/gateways/nmi.rb +12 -7
- data/lib/active_merchant/billing/gateways/orbital.rb +349 -327
- data/lib/active_merchant/billing/gateways/payflow.rb +62 -0
- data/lib/active_merchant/billing/gateways/paymentez.rb +26 -7
- data/lib/active_merchant/billing/gateways/paysafe.rb +15 -15
- data/lib/active_merchant/billing/gateways/payu_latam.rb +25 -15
- data/lib/active_merchant/billing/gateways/priority.rb +158 -136
- data/lib/active_merchant/billing/gateways/rapyd.rb +258 -0
- data/lib/active_merchant/billing/gateways/safe_charge.rb +1 -4
- data/lib/active_merchant/billing/gateways/simetrik.rb +362 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +4 -2
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +93 -48
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
- data/lib/active_merchant/version.rb +1 -1
- metadata +6 -2
@@ -83,6 +83,7 @@ module ActiveMerchant #:nodoc:
|
|
83
83
|
options[:name] = credit_card.name if options[:name].blank? && credit_card
|
84
84
|
request = build_recurring_request(options[:profile_id] ? :modify : :add, money, options) do |xml|
|
85
85
|
add_credit_card(xml, credit_card, options) if credit_card
|
86
|
+
add_stored_credential(xml, options[:stored_credential])
|
86
87
|
end
|
87
88
|
commit(request, options.merge(request_type: :recurring))
|
88
89
|
end
|
@@ -158,6 +159,7 @@ module ActiveMerchant #:nodoc:
|
|
158
159
|
xml.tag! 'ExtData', 'Name' => 'ORIGID', 'Value' => reference
|
159
160
|
end
|
160
161
|
end
|
162
|
+
add_stored_credential(xml, options[:stored_credential])
|
161
163
|
end
|
162
164
|
xml.tag! 'ExtData', 'Name' => 'BUTTONSOURCE', 'Value' => application_id unless application_id.blank?
|
163
165
|
end
|
@@ -190,15 +192,43 @@ module ActiveMerchant #:nodoc:
|
|
190
192
|
xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
|
191
193
|
end
|
192
194
|
|
195
|
+
if %i(authorization purchase).include? action
|
196
|
+
add_mpi_3ds(xml, options[:three_d_secure]) if options[:three_d_secure]
|
197
|
+
end
|
198
|
+
|
193
199
|
xml.tag! 'Tender' do
|
194
200
|
add_credit_card(xml, credit_card, options)
|
195
201
|
end
|
202
|
+
add_stored_credential(xml, options[:stored_credential])
|
196
203
|
end
|
197
204
|
xml.tag! 'ExtData', 'Name' => 'BUTTONSOURCE', 'Value' => application_id unless application_id.blank?
|
198
205
|
end
|
199
206
|
add_level_two_three_fields(xml.target!, options)
|
200
207
|
end
|
201
208
|
|
209
|
+
def add_mpi_3ds(xml, three_d_secure_options)
|
210
|
+
# structure as per https://developer.paypal.com/api/nvp-soap/payflow/3d-secure-mpi/
|
211
|
+
authentication_id = three_d_secure_options[:authentication_id]
|
212
|
+
authentication_status = three_d_secure_options[:authentication_response_status]
|
213
|
+
|
214
|
+
eci = three_d_secure_options[:eci]
|
215
|
+
cavv = three_d_secure_options[:cavv]
|
216
|
+
xid = three_d_secure_options[:xid]
|
217
|
+
version = three_d_secure_options[:version]
|
218
|
+
|
219
|
+
# 3DS2 only
|
220
|
+
ds_transaction_id = three_d_secure_options[:ds_transaction_id] if version_2_or_newer?(three_d_secure_options)
|
221
|
+
|
222
|
+
xml.tag!('ExtData', 'Name' => 'AUTHENTICATION_ID', 'Value' => authentication_id) unless authentication_id.blank?
|
223
|
+
xml.tag!('ExtData', 'Name' => 'AUTHENTICATION_STATUS', 'Value' => authentication_status) unless authentication_status.blank?
|
224
|
+
|
225
|
+
xml.tag!('ExtData', 'Name' => 'CAVV', 'Value' => cavv) unless cavv.blank?
|
226
|
+
xml.tag!('ExtData', 'Name' => 'ECI', 'Value' => eci) unless eci.blank?
|
227
|
+
xml.tag!('ExtData', 'Name' => 'XID', 'Value' => xid) unless xid.blank?
|
228
|
+
xml.tag!('ExtData', 'Name' => 'THREEDSVERSION', 'Value' => version) unless version.blank?
|
229
|
+
xml.tag!('ExtData', 'Name' => 'DSTRANSACTIONID', 'Value' => ds_transaction_id) unless ds_transaction_id.blank?
|
230
|
+
end
|
231
|
+
|
202
232
|
def add_level_two_three_fields(xml_string, options)
|
203
233
|
if options[:level_two_fields] || options[:level_three_fields]
|
204
234
|
xml_doc = Nokogiri::XML.parse(xml_string)
|
@@ -258,6 +288,7 @@ module ActiveMerchant #:nodoc:
|
|
258
288
|
xml.tag! 'ABA', check.routing_number
|
259
289
|
end
|
260
290
|
end
|
291
|
+
add_stored_credential(xml, options[:stored_credential])
|
261
292
|
end
|
262
293
|
xml.tag! 'ExtData', 'Name' => 'BUTTONSOURCE', 'Value' => application_id unless application_id.blank?
|
263
294
|
end
|
@@ -278,6 +309,37 @@ module ActiveMerchant #:nodoc:
|
|
278
309
|
end
|
279
310
|
end
|
280
311
|
|
312
|
+
def add_stored_credential(xml, stored_credential)
|
313
|
+
return unless stored_credential
|
314
|
+
|
315
|
+
xml.tag! 'CardOnFile', add_card_on_file_type(stored_credential)
|
316
|
+
xml.tag! 'TxnId', stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
317
|
+
end
|
318
|
+
|
319
|
+
def card_on_file_initiator(initator)
|
320
|
+
case initator
|
321
|
+
when 'merchant'
|
322
|
+
'MIT'
|
323
|
+
when 'cardholder'
|
324
|
+
'CIT'
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def card_on_file_reason(stored_credential)
|
329
|
+
return 'I' if stored_credential[:initial_transaction] && stored_credential[:reason_type] == 'unscheduled'
|
330
|
+
|
331
|
+
case stored_credential[:reason_type]
|
332
|
+
when 'recurring', 'installment'
|
333
|
+
'R'
|
334
|
+
when 'unscheduled'
|
335
|
+
'U'
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def add_card_on_file_type(stored_credential)
|
340
|
+
card_on_file_initiator(stored_credential[:initiator]).to_s + card_on_file_reason(stored_credential).to_s
|
341
|
+
end
|
342
|
+
|
281
343
|
def add_three_d_secure(options, xml)
|
282
344
|
if options[:three_d_secure]
|
283
345
|
three_d_secure = options[:three_d_secure]
|
@@ -34,6 +34,8 @@ module ActiveMerchant #:nodoc:
|
|
34
34
|
28 => :card_declined
|
35
35
|
}.freeze
|
36
36
|
|
37
|
+
SUCCESS_STATUS = ['success', 'pending', 1, 0]
|
38
|
+
|
37
39
|
CARD_MAPPING = {
|
38
40
|
'visa' => 'vi',
|
39
41
|
'master' => 'mc',
|
@@ -67,6 +69,8 @@ module ActiveMerchant #:nodoc:
|
|
67
69
|
end
|
68
70
|
|
69
71
|
def authorize(money, payment, options = {})
|
72
|
+
return purchase(money, payment, options) if options[:otp_flow]
|
73
|
+
|
70
74
|
post = {}
|
71
75
|
|
72
76
|
add_invoice(post, money, options)
|
@@ -77,13 +81,21 @@ module ActiveMerchant #:nodoc:
|
|
77
81
|
commit_transaction('authorize', post)
|
78
82
|
end
|
79
83
|
|
80
|
-
def capture(money, authorization,
|
84
|
+
def capture(money, authorization, options = {})
|
81
85
|
post = {
|
82
86
|
transaction: { id: authorization }
|
83
87
|
}
|
84
|
-
|
88
|
+
verify_flow = options[:type] && options[:value]
|
89
|
+
|
90
|
+
if verify_flow
|
91
|
+
add_customer_data(post, options)
|
92
|
+
add_verify_value(post, options)
|
93
|
+
elsif money
|
94
|
+
post[:order] = { amount: amount(money).to_f }
|
95
|
+
end
|
85
96
|
|
86
|
-
|
97
|
+
action = verify_flow ? 'verify' : 'capture'
|
98
|
+
commit_transaction(action, post)
|
87
99
|
end
|
88
100
|
|
89
101
|
def refund(money, authorization, options = {})
|
@@ -139,10 +151,10 @@ module ActiveMerchant #:nodoc:
|
|
139
151
|
private
|
140
152
|
|
141
153
|
def add_customer_data(post, options)
|
142
|
-
requires!(options, :user_id
|
154
|
+
requires!(options, :user_id)
|
143
155
|
post[:user] ||= {}
|
144
156
|
post[:user][:id] = options[:user_id]
|
145
|
-
post[:user][:email] = options[:email]
|
157
|
+
post[:user][:email] = options[:email] if options[:email]
|
146
158
|
post[:user][:ip_address] = options[:ip] if options[:ip]
|
147
159
|
post[:user][:fiscal_number] = options[:fiscal_number] if options[:fiscal_number]
|
148
160
|
if phone = options[:phone] || options.dig(:billing_address, :phone)
|
@@ -179,6 +191,11 @@ module ActiveMerchant #:nodoc:
|
|
179
191
|
end
|
180
192
|
end
|
181
193
|
|
194
|
+
def add_verify_value(post, options)
|
195
|
+
post[:type] = options[:type] if options[:type]
|
196
|
+
post[:value] = options[:value] if options[:value]
|
197
|
+
end
|
198
|
+
|
182
199
|
def add_extra_params(post, options)
|
183
200
|
extra_params = {}
|
184
201
|
extra_params.merge!(options[:extra_params]) if options[:extra_params]
|
@@ -262,7 +279,9 @@ module ActiveMerchant #:nodoc:
|
|
262
279
|
end
|
263
280
|
|
264
281
|
def success_from(response)
|
265
|
-
|
282
|
+
return false if response.include?('error')
|
283
|
+
|
284
|
+
SUCCESS_STATUS.include?(response['status'] || response['transaction']['status'])
|
266
285
|
end
|
267
286
|
|
268
287
|
def card_success_from(response)
|
@@ -278,7 +297,7 @@ module ActiveMerchant #:nodoc:
|
|
278
297
|
if !success_from(response) && response['error']
|
279
298
|
response['error'] && response['error']['type']
|
280
299
|
else
|
281
|
-
response['transaction'] && response['transaction']['message']
|
300
|
+
(response['transaction'] && response['transaction']['message']) || (response['message'])
|
282
301
|
end
|
283
302
|
end
|
284
303
|
|
@@ -95,7 +95,7 @@ module ActiveMerchant #:nodoc:
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def unstore(pm_profile_id)
|
98
|
-
|
98
|
+
commit(:delete, "profiles/#{get_id_from_store_auth(pm_profile_id)}", nil, nil)
|
99
99
|
end
|
100
100
|
|
101
101
|
def supports_scrubbing?
|
@@ -179,7 +179,7 @@ module ActiveMerchant #:nodoc:
|
|
179
179
|
def add_payment(post, payment)
|
180
180
|
if payment.is_a?(String)
|
181
181
|
post[:card] = {}
|
182
|
-
post[:card][:paymentToken] = payment
|
182
|
+
post[:card][:paymentToken] = get_pm_from_store_auth(payment)
|
183
183
|
else
|
184
184
|
post[:card] = { cardExpiry: {} }
|
185
185
|
post[:card][:cardNum] = payment.number
|
@@ -299,7 +299,7 @@ module ActiveMerchant #:nodoc:
|
|
299
299
|
end
|
300
300
|
|
301
301
|
case options[:stored_credential][:reason_type]
|
302
|
-
when 'recurring'
|
302
|
+
when 'recurring', 'installment'
|
303
303
|
post[:storedCredential][:type] = 'RECURRING'
|
304
304
|
when 'unscheduled'
|
305
305
|
if options[:stored_credential][:initiator] == 'merchant'
|
@@ -321,6 +321,8 @@ module ActiveMerchant #:nodoc:
|
|
321
321
|
end
|
322
322
|
|
323
323
|
def parse(body)
|
324
|
+
return {} if body.empty?
|
325
|
+
|
324
326
|
JSON.parse(body)
|
325
327
|
end
|
326
328
|
|
@@ -342,17 +344,6 @@ module ActiveMerchant #:nodoc:
|
|
342
344
|
)
|
343
345
|
end
|
344
346
|
|
345
|
-
def commit_for_unstore(method, action, parameters, options)
|
346
|
-
url = url(action)
|
347
|
-
response = raw_ssl_request(method, url, post_data(parameters, options), headers)
|
348
|
-
success = true if response.code == '200'
|
349
|
-
|
350
|
-
Response.new(
|
351
|
-
success,
|
352
|
-
message: response.message
|
353
|
-
)
|
354
|
-
end
|
355
|
-
|
356
347
|
def headers
|
357
348
|
{
|
358
349
|
'Content-Type' => 'application/json',
|
@@ -384,12 +375,21 @@ module ActiveMerchant #:nodoc:
|
|
384
375
|
|
385
376
|
def authorization_from(action, response)
|
386
377
|
if action == 'profiles'
|
387
|
-
response['cards'].first['paymentToken']
|
378
|
+
pm = response['cards'].first['paymentToken']
|
379
|
+
"#{pm}|#{response['id']}"
|
388
380
|
else
|
389
381
|
response['id']
|
390
382
|
end
|
391
383
|
end
|
392
384
|
|
385
|
+
def get_pm_from_store_auth(authorization)
|
386
|
+
authorization.split('|')[0]
|
387
|
+
end
|
388
|
+
|
389
|
+
def get_id_from_store_auth(authorization)
|
390
|
+
authorization.split('|')[1]
|
391
|
+
end
|
392
|
+
|
393
393
|
def post_data(parameters = {}, options = {})
|
394
394
|
return unless parameters.present?
|
395
395
|
|
@@ -392,26 +392,36 @@ module ActiveMerchant #:nodoc:
|
|
392
392
|
def message_from(action, success, response)
|
393
393
|
case action
|
394
394
|
when 'store'
|
395
|
-
|
396
|
-
|
397
|
-
error_description = response['creditCardToken']['errorDescription'] if response['creditCardToken']
|
398
|
-
response['error'] || error_description || 'FAILED'
|
395
|
+
message_from_store(success, response)
|
399
396
|
when 'verify_credentials'
|
400
|
-
|
401
|
-
|
402
|
-
'FAILED'
|
397
|
+
message_from_verify_credentials(success)
|
403
398
|
else
|
404
|
-
|
405
|
-
|
399
|
+
message_from_transaction_response(success, response)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def message_from_store(success, response)
|
404
|
+
return response['code'] if success
|
406
405
|
|
407
|
-
|
406
|
+
error_description = response['creditCardToken']['errorDescription'] if response['creditCardToken']
|
407
|
+
response['error'] || error_description || 'FAILED'
|
408
|
+
end
|
408
409
|
|
409
|
-
|
410
|
-
|
411
|
-
return response_code if success
|
410
|
+
def message_from_verify_credentials(success)
|
411
|
+
return 'VERIFIED' if success
|
412
412
|
|
413
|
-
|
414
|
-
|
413
|
+
'FAILED'
|
414
|
+
end
|
415
|
+
|
416
|
+
def message_from_transaction_response(success, response)
|
417
|
+
response_code = response.dig('transactionResponse', 'responseCode') || response.dig('transactionResponse', 'pendingReason')
|
418
|
+
return response_code if success
|
419
|
+
return response_code + ' | ' + response.dig('transactionResponse', 'paymentNetworkResponseErrorMessage') if response.dig('transactionResponse', 'paymentNetworkResponseErrorMessage')
|
420
|
+
return response.dig('transactionResponse', 'responseMessage') if response.dig('transactionResponse', 'responseMessage')
|
421
|
+
return response['error'] if response['error']
|
422
|
+
return response_code if response_code
|
423
|
+
|
424
|
+
'FAILED'
|
415
425
|
end
|
416
426
|
|
417
427
|
def authorization_from(action, response)
|