activemerchant 1.90.0 → 1.99.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 +202 -0
- data/README.md +6 -2
- data/lib/active_merchant/billing/avs_result.rb +4 -5
- data/lib/active_merchant/billing/credit_card.rb +8 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +81 -5
- data/lib/active_merchant/billing/gateway.rb +10 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +206 -54
- data/lib/active_merchant/billing/gateways/bambora_apac.rb +226 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +3 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +11 -6
- data/lib/active_merchant/billing/gateways/blue_pay.rb +10 -8
- data/lib/active_merchant/billing/gateways/blue_snap.rb +211 -36
- data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +79 -18
- data/lib/active_merchant/billing/gateways/card_connect.rb +6 -1
- data/lib/active_merchant/billing/gateways/cecabank.rb +20 -9
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +98 -61
- data/lib/active_merchant/billing/gateways/credorax.rb +69 -4
- data/lib/active_merchant/billing/gateways/cyber_source.rb +85 -14
- data/lib/active_merchant/billing/gateways/d_local.rb +3 -3
- data/lib/active_merchant/billing/gateways/decidir.rb +245 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +9 -0
- data/lib/active_merchant/billing/gateways/epay.rb +13 -2
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +42 -12
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +26 -7
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +42 -3
- data/lib/active_merchant/billing/gateways/global_collect.rb +3 -7
- data/lib/active_merchant/billing/gateways/hps.rb +46 -1
- data/lib/active_merchant/billing/gateways/ipp.rb +1 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
- data/lib/active_merchant/billing/gateways/litle.rb +61 -3
- data/lib/active_merchant/billing/gateways/mastercard.rb +30 -5
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
- data/lib/active_merchant/billing/gateways/migs.rb +8 -0
- data/lib/active_merchant/billing/gateways/monei.rb +31 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +3 -4
- data/lib/active_merchant/billing/gateways/mundipagg.rb +37 -9
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/netbanx.rb +4 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +45 -5
- data/lib/active_merchant/billing/gateways/openpay.rb +1 -1
- data/lib/active_merchant/billing/gateways/opp.rb +20 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +92 -11
- data/lib/active_merchant/billing/gateways/payflow.rb +64 -14
- data/lib/active_merchant/billing/gateways/payment_express.rb +7 -0
- data/lib/active_merchant/billing/gateways/paymentez.rb +7 -11
- data/lib/active_merchant/billing/gateways/paymill.rb +5 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +14 -1
- data/lib/active_merchant/billing/gateways/paypal_express.rb +3 -1
- data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -2
- data/lib/active_merchant/billing/gateways/pin.rb +19 -6
- data/lib/active_merchant/billing/gateways/pro_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -1
- data/lib/active_merchant/billing/gateways/qvalent.rb +54 -1
- data/lib/active_merchant/billing/gateways/realex.rb +42 -5
- data/lib/active_merchant/billing/gateways/redsys.rb +113 -30
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +43 -29
- data/lib/active_merchant/billing/gateways/stripe.rb +66 -34
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +271 -0
- data/lib/active_merchant/billing/gateways/tns.rb +10 -5
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +5 -5
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +46 -6
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +19 -8
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +22 -10
- data/lib/active_merchant/billing/gateways/worldpay.rb +237 -34
- data/lib/active_merchant/country.rb +2 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +20 -4
|
@@ -324,15 +324,15 @@ module ActiveMerchant #:nodoc:
|
|
|
324
324
|
:region => address[:state],
|
|
325
325
|
:postal_code => scrub_zip(address[:zip]),
|
|
326
326
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
mapped[:country_code_alpha3]
|
|
333
|
-
elsif address[:country_code_numeric]
|
|
334
|
-
mapped[:country_code_numeric] = address[:country_code_numeric]
|
|
327
|
+
|
|
328
|
+
mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2]) if address[:country] || address[:country_code_alpha2]
|
|
329
|
+
mapped[:country_name] = address[:country_name] if address[:country_name]
|
|
330
|
+
mapped[:country_code_alpha3] = address[:country_code_alpha3] if address[:country_code_alpha3]
|
|
331
|
+
unless address[:country].blank?
|
|
332
|
+
mapped[:country_code_alpha3] ||= Country.find(address[:country]).code(:alpha3).value
|
|
335
333
|
end
|
|
334
|
+
mapped[:country_code_numeric] = address[:country_code_numeric] if address[:country_code_numeric]
|
|
335
|
+
|
|
336
336
|
mapped
|
|
337
337
|
end
|
|
338
338
|
|
|
@@ -419,7 +419,9 @@ module ActiveMerchant #:nodoc:
|
|
|
419
419
|
'street: A, zip: N' => 'C',
|
|
420
420
|
'street: A, zip: U' => 'I',
|
|
421
421
|
'street: A, zip: I' => 'I',
|
|
422
|
-
'street: A, zip: A' => 'I'
|
|
422
|
+
'street: A, zip: A' => 'I',
|
|
423
|
+
|
|
424
|
+
'street: B, zip: B' => 'B'
|
|
423
425
|
}
|
|
424
426
|
end
|
|
425
427
|
|
|
@@ -445,7 +447,6 @@ module ActiveMerchant #:nodoc:
|
|
|
445
447
|
|
|
446
448
|
def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
|
|
447
449
|
transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
|
|
448
|
-
|
|
449
450
|
commit do
|
|
450
451
|
result = @braintree_gateway.transaction.send(transaction_type, transaction_params)
|
|
451
452
|
response = Response.new(result.success?, message_from_transaction_result(result), response_params(result), response_options(result))
|
|
@@ -543,6 +544,17 @@ module ActiveMerchant #:nodoc:
|
|
|
543
544
|
'token' => transaction.credit_card_details.token
|
|
544
545
|
}
|
|
545
546
|
|
|
547
|
+
if transaction.risk_data
|
|
548
|
+
risk_data = {
|
|
549
|
+
'id' => transaction.risk_data.id,
|
|
550
|
+
'decision' => transaction.risk_data.decision,
|
|
551
|
+
'device_data_captured' => transaction.risk_data.device_data_captured,
|
|
552
|
+
'fraud_service_provider' => transaction.risk_data.fraud_service_provider
|
|
553
|
+
}
|
|
554
|
+
else
|
|
555
|
+
risk_data = nil
|
|
556
|
+
end
|
|
557
|
+
|
|
546
558
|
{
|
|
547
559
|
'order_id' => transaction.order_id,
|
|
548
560
|
'amount' => transaction.amount.to_s,
|
|
@@ -553,6 +565,8 @@ module ActiveMerchant #:nodoc:
|
|
|
553
565
|
'shipping_details' => shipping_details,
|
|
554
566
|
'vault_customer' => vault_customer,
|
|
555
567
|
'merchant_account_id' => transaction.merchant_account_id,
|
|
568
|
+
'risk_data' => risk_data,
|
|
569
|
+
'network_transaction_id' => transaction.network_transaction_id || nil,
|
|
556
570
|
'processor_response_code' => response_code_from_result(result)
|
|
557
571
|
}
|
|
558
572
|
end
|
|
@@ -578,6 +592,14 @@ module ActiveMerchant #:nodoc:
|
|
|
578
592
|
parameters[:options][:skip_advanced_fraud_checking] = options[:skip_advanced_fraud_checking]
|
|
579
593
|
end
|
|
580
594
|
|
|
595
|
+
if options[:skip_avs]
|
|
596
|
+
parameters[:options][:skip_avs] = options[:skip_avs]
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
if options[:skip_cvv]
|
|
600
|
+
parameters[:options][:skip_cvv] = options[:skip_cvv]
|
|
601
|
+
end
|
|
602
|
+
|
|
581
603
|
parameters[:custom_fields] = options[:custom_fields]
|
|
582
604
|
parameters[:device_data] = options[:device_data] if options[:device_data]
|
|
583
605
|
parameters[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
|
|
@@ -585,11 +607,14 @@ module ActiveMerchant #:nodoc:
|
|
|
585
607
|
parameters[:merchant_account_id] = merchant_account_id
|
|
586
608
|
end
|
|
587
609
|
|
|
588
|
-
if options[:
|
|
610
|
+
if options[:transaction_source]
|
|
611
|
+
parameters[:transaction_source] = options[:transaction_source]
|
|
612
|
+
elsif options[:recurring]
|
|
589
613
|
parameters[:recurring] = true
|
|
590
614
|
end
|
|
591
615
|
|
|
592
616
|
add_payment_method(parameters, credit_card_or_vault_id, options)
|
|
617
|
+
add_stored_credential_data(parameters, credit_card_or_vault_id, options)
|
|
593
618
|
|
|
594
619
|
parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
|
|
595
620
|
parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
|
|
@@ -605,13 +630,7 @@ module ActiveMerchant #:nodoc:
|
|
|
605
630
|
}
|
|
606
631
|
end
|
|
607
632
|
|
|
608
|
-
|
|
609
|
-
parameters[:three_d_secure_pass_thru] = {
|
|
610
|
-
cavv: options[:three_d_secure][:cavv],
|
|
611
|
-
eci_flag: options[:three_d_secure][:eci],
|
|
612
|
-
xid: options[:three_d_secure][:xid],
|
|
613
|
-
}
|
|
614
|
-
end
|
|
633
|
+
add_3ds_info(parameters, options[:three_d_secure])
|
|
615
634
|
|
|
616
635
|
parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
|
|
617
636
|
parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
|
|
@@ -626,6 +645,48 @@ module ActiveMerchant #:nodoc:
|
|
|
626
645
|
parameters
|
|
627
646
|
end
|
|
628
647
|
|
|
648
|
+
def add_3ds_info(parameters, three_d_secure_opts)
|
|
649
|
+
return if empty?(three_d_secure_opts)
|
|
650
|
+
pass_thru = {}
|
|
651
|
+
|
|
652
|
+
pass_thru[:three_d_secure_version] = three_d_secure_opts[:version] if three_d_secure_opts[:version]
|
|
653
|
+
pass_thru[:eci_flag] = three_d_secure_opts[:eci] if three_d_secure_opts[:eci]
|
|
654
|
+
pass_thru[:cavv_algorithm] = three_d_secure_opts[:cavv_algorithm] if three_d_secure_opts[:cavv_algorithm]
|
|
655
|
+
pass_thru[:cavv] = three_d_secure_opts[:cavv] if three_d_secure_opts[:cavv]
|
|
656
|
+
pass_thru[:directory_response] = three_d_secure_opts[:directory_response_status] if three_d_secure_opts[:directory_response_status]
|
|
657
|
+
pass_thru[:authentication_response] = three_d_secure_opts[:authentication_response_status] if three_d_secure_opts[:authentication_response_status]
|
|
658
|
+
|
|
659
|
+
parameters[:three_d_secure_pass_thru] = pass_thru.merge(xid_or_ds_trans_id(three_d_secure_opts))
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
def xid_or_ds_trans_id(three_d_secure_opts)
|
|
663
|
+
if three_d_secure_opts[:version].to_f >= 2
|
|
664
|
+
{ ds_transaction_id: three_d_secure_opts[:ds_transaction_id] }
|
|
665
|
+
else
|
|
666
|
+
{ xid: three_d_secure_opts[:xid] }
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
def add_stored_credential_data(parameters, credit_card_or_vault_id, options)
|
|
671
|
+
return unless (stored_credential = options[:stored_credential])
|
|
672
|
+
parameters[:external_vault] = {}
|
|
673
|
+
if stored_credential[:initial_transaction]
|
|
674
|
+
parameters[:external_vault][:status] = 'will_vault'
|
|
675
|
+
else
|
|
676
|
+
parameters[:external_vault][:status] = 'vaulted'
|
|
677
|
+
parameters[:external_vault][:previous_network_transaction_id] = stored_credential[:network_transaction_id]
|
|
678
|
+
end
|
|
679
|
+
if stored_credential[:initiator] == 'merchant'
|
|
680
|
+
if stored_credential[:reason_type] == 'installment'
|
|
681
|
+
parameters[:transaction_source] = 'recurring'
|
|
682
|
+
else
|
|
683
|
+
parameters[:transaction_source] = stored_credential[:reason_type]
|
|
684
|
+
end
|
|
685
|
+
else
|
|
686
|
+
parameters[:transaction_source] = ''
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
|
|
629
690
|
def add_payment_method(parameters, credit_card_or_vault_id, options)
|
|
630
691
|
if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
|
|
631
692
|
if options[:payment_method_token]
|
|
@@ -68,7 +68,7 @@ module ActiveMerchant #:nodoc:
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def require_valid_domain!(options, param)
|
|
71
|
-
if options
|
|
71
|
+
if options[param]
|
|
72
72
|
raise ArgumentError.new('not a valid cardconnect domain') unless /\Dcardconnect.com:\d{1,}\D/ =~ options[param]
|
|
73
73
|
end
|
|
74
74
|
end
|
|
@@ -233,6 +233,7 @@ module ActiveMerchant #:nodoc:
|
|
|
233
233
|
item.each_pair do |k, v|
|
|
234
234
|
updated.merge!(k.to_s.gsub(/_/, '') => v)
|
|
235
235
|
end
|
|
236
|
+
updated
|
|
236
237
|
end
|
|
237
238
|
end
|
|
238
239
|
end
|
|
@@ -267,6 +268,7 @@ module ActiveMerchant #:nodoc:
|
|
|
267
268
|
end
|
|
268
269
|
|
|
269
270
|
def commit(action, parameters, verb: :put, path: '')
|
|
271
|
+
parameters[:frontendid] = application_id
|
|
270
272
|
parameters[:merchid] = @options[:merchant_id]
|
|
271
273
|
url = url(action, path)
|
|
272
274
|
response = parse(ssl_request(verb, url, post_data(parameters), headers))
|
|
@@ -281,6 +283,9 @@ module ActiveMerchant #:nodoc:
|
|
|
281
283
|
test: test?,
|
|
282
284
|
error_code: error_code_from(response)
|
|
283
285
|
)
|
|
286
|
+
rescue ResponseError => e
|
|
287
|
+
return Response.new(false, 'Unable to authenticate. Please check your credentials.', {}, :test => test?) if e.response.code == '401'
|
|
288
|
+
raise
|
|
284
289
|
end
|
|
285
290
|
|
|
286
291
|
def success_from(response)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
|
3
3
|
class CecabankGateway < Gateway
|
|
4
|
-
self.test_url = '
|
|
4
|
+
self.test_url = 'https://tpv.ceca.es'
|
|
5
5
|
self.live_url = 'https://pgw.ceca.es'
|
|
6
6
|
|
|
7
7
|
self.supported_countries = ['ES']
|
|
@@ -13,14 +13,14 @@ module ActiveMerchant #:nodoc:
|
|
|
13
13
|
|
|
14
14
|
#### CECA's MAGIC NUMBERS
|
|
15
15
|
CECA_NOTIFICATIONS_URL = 'NONE'
|
|
16
|
-
CECA_ENCRIPTION = '
|
|
16
|
+
CECA_ENCRIPTION = 'SHA2'
|
|
17
17
|
CECA_DECIMALS = '2'
|
|
18
18
|
CECA_MODE = 'SSL'
|
|
19
19
|
CECA_UI_LESS_LANGUAGE = 'XML'
|
|
20
20
|
CECA_UI_LESS_LANGUAGE_REFUND = '1'
|
|
21
21
|
CECA_UI_LESS_REFUND_PAGE = 'anulacion_xml'
|
|
22
|
-
CECA_ACTION_REFUND = '
|
|
23
|
-
CECA_ACTION_PURCHASE = 'tpv'
|
|
22
|
+
CECA_ACTION_REFUND = 'anulaciones/anularParcial' # use partial refund's URL to avoid time frame limitations and decision logic on client side
|
|
23
|
+
CECA_ACTION_PURCHASE = 'tpv/compra'
|
|
24
24
|
CECA_CURRENCIES_DICTIONARY = {'EUR' => 978, 'USD' => 840, 'GBP' => 826}
|
|
25
25
|
|
|
26
26
|
# Creates a new CecabankGateway
|
|
@@ -168,18 +168,29 @@ module ActiveMerchant #:nodoc:
|
|
|
168
168
|
'AcquirerBIN' => options[:acquirer_bin],
|
|
169
169
|
'TerminalID' => options[:terminal_id]
|
|
170
170
|
)
|
|
171
|
-
url = (test? ? self.test_url : self.live_url) + "/
|
|
172
|
-
xml = ssl_post(url, post_data(parameters))
|
|
171
|
+
url = (test? ? self.test_url : self.live_url) + "/tpvweb/#{action}.action"
|
|
172
|
+
xml = ssl_post("#{url}?", post_data(parameters))
|
|
173
173
|
response = parse(xml)
|
|
174
174
|
Response.new(
|
|
175
175
|
response[:success],
|
|
176
|
-
response
|
|
176
|
+
message_from(response),
|
|
177
177
|
response,
|
|
178
178
|
:test => test?,
|
|
179
|
-
:authorization => build_authorization(response)
|
|
179
|
+
:authorization => build_authorization(response),
|
|
180
|
+
:error_code => response[:error_code]
|
|
180
181
|
)
|
|
181
182
|
end
|
|
182
183
|
|
|
184
|
+
def message_from(response)
|
|
185
|
+
if response[:message] == 'ERROR' && response[:error_message]
|
|
186
|
+
response[:error_message]
|
|
187
|
+
elsif response[:error_message]
|
|
188
|
+
"#{response[:message]} #{response[:error_message]}"
|
|
189
|
+
else
|
|
190
|
+
response[:message]
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
183
194
|
def post_data(params)
|
|
184
195
|
return nil unless params
|
|
185
196
|
|
|
@@ -231,7 +242,7 @@ module ActiveMerchant #:nodoc:
|
|
|
231
242
|
CECA_NOTIFICATIONS_URL +
|
|
232
243
|
CECA_NOTIFICATIONS_URL
|
|
233
244
|
end
|
|
234
|
-
Digest::
|
|
245
|
+
Digest::SHA2.hexdigest(signature_fields)
|
|
235
246
|
end
|
|
236
247
|
end
|
|
237
248
|
end
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
|
3
3
|
class CheckoutV2Gateway < Gateway
|
|
4
|
-
self.display_name = 'Checkout.com
|
|
4
|
+
self.display_name = 'Checkout.com Unified Payments'
|
|
5
5
|
self.homepage_url = 'https://www.checkout.com/'
|
|
6
|
-
self.live_url = 'https://
|
|
7
|
-
self.test_url = 'https://sandbox.checkout.com
|
|
6
|
+
self.live_url = 'https://api.checkout.com'
|
|
7
|
+
self.test_url = 'https://api.sandbox.checkout.com'
|
|
8
8
|
|
|
9
9
|
self.supported_countries = ['AD', 'AE', 'AT', 'BE', 'BG', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FO', 'FI', 'FR', 'GB', 'GI', 'GL', 'GR', 'HR', 'HU', 'IE', 'IS', 'IL', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SM', 'SK', 'SJ', 'TR', 'VA']
|
|
10
10
|
self.default_currency = 'USD'
|
|
11
11
|
self.money_format = :cents
|
|
12
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
|
|
12
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :maestro, :discover]
|
|
13
13
|
|
|
14
|
-
def initialize(options={})
|
|
14
|
+
def initialize(options = {})
|
|
15
15
|
requires!(options, :secret_key)
|
|
16
16
|
super
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def purchase(amount, payment_method, options={})
|
|
19
|
+
def purchase(amount, payment_method, options = {})
|
|
20
20
|
multi = MultiResponse.run do |r|
|
|
21
21
|
r.process { authorize(amount, payment_method, options) }
|
|
22
22
|
r.process { capture(amount, r.authorization, options) }
|
|
@@ -28,18 +28,19 @@ module ActiveMerchant #:nodoc:
|
|
|
28
28
|
response(:purchase, succeeded, merged_params)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def authorize(amount, payment_method, options={})
|
|
31
|
+
def authorize(amount, payment_method, options = {})
|
|
32
32
|
post = {}
|
|
33
|
-
post[:
|
|
33
|
+
post[:capture] = false
|
|
34
34
|
add_invoice(post, amount, options)
|
|
35
|
-
add_payment_method(post, payment_method)
|
|
35
|
+
add_payment_method(post, payment_method, options)
|
|
36
36
|
add_customer_data(post, options)
|
|
37
37
|
add_transaction_data(post, options)
|
|
38
|
+
add_3ds(post, options)
|
|
38
39
|
|
|
39
40
|
commit(:authorize, post)
|
|
40
41
|
end
|
|
41
42
|
|
|
42
|
-
def capture(amount, authorization, options={})
|
|
43
|
+
def capture(amount, authorization, options = {})
|
|
43
44
|
post = {}
|
|
44
45
|
add_invoice(post, amount, options)
|
|
45
46
|
add_customer_data(post, options)
|
|
@@ -47,12 +48,12 @@ module ActiveMerchant #:nodoc:
|
|
|
47
48
|
commit(:capture, post, authorization)
|
|
48
49
|
end
|
|
49
50
|
|
|
50
|
-
def void(authorization,
|
|
51
|
+
def void(authorization, _options = {})
|
|
51
52
|
post = {}
|
|
52
53
|
commit(:void, post, authorization)
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
def refund(amount, authorization, options={})
|
|
56
|
+
def refund(amount, authorization, options = {})
|
|
56
57
|
post = {}
|
|
57
58
|
add_invoice(post, amount, options)
|
|
58
59
|
add_customer_data(post, options)
|
|
@@ -60,72 +61,102 @@ module ActiveMerchant #:nodoc:
|
|
|
60
61
|
commit(:refund, post, authorization)
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
def verify(credit_card, options={})
|
|
64
|
+
def verify(credit_card, options = {})
|
|
64
65
|
MultiResponse.run(:use_first_response) do |r|
|
|
65
66
|
r.process { authorize(100, credit_card, options) }
|
|
66
67
|
r.process(:ignore_result) { void(r.authorization, options) }
|
|
67
68
|
end
|
|
68
69
|
end
|
|
69
70
|
|
|
71
|
+
def verify_payment(authorization, option={})
|
|
72
|
+
commit(:verify_payment, authorization)
|
|
73
|
+
end
|
|
74
|
+
|
|
70
75
|
def supports_scrubbing?
|
|
71
76
|
true
|
|
72
77
|
end
|
|
73
78
|
|
|
74
79
|
def scrub(transcript)
|
|
75
80
|
transcript.
|
|
76
|
-
gsub(
|
|
77
|
-
gsub(
|
|
78
|
-
gsub(
|
|
81
|
+
gsub(/(Authorization: )[^\\]*/i, '\1[FILTERED]').
|
|
82
|
+
gsub(/("number\\":\\")\d+/, '\1[FILTERED]').
|
|
83
|
+
gsub(/("cvv\\":\\")\d+/, '\1[FILTERED]')
|
|
79
84
|
end
|
|
80
85
|
|
|
81
86
|
private
|
|
82
87
|
|
|
83
88
|
def add_invoice(post, money, options)
|
|
84
|
-
post[:
|
|
85
|
-
post[:
|
|
89
|
+
post[:amount] = localized_amount(money, options[:currency])
|
|
90
|
+
post[:reference] = options[:order_id]
|
|
86
91
|
post[:currency] = options[:currency] || currency(money)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
if options[:descriptor_name] || options[:descriptor_city]
|
|
93
|
+
post[:billing_descriptor] = {}
|
|
94
|
+
post[:billing_descriptor][:name] = options[:descriptor_name] if options[:descriptor_name]
|
|
95
|
+
post[:billing_descriptor][:city] = options[:descriptor_city] if options[:descriptor_city]
|
|
96
|
+
end
|
|
97
|
+
post[:metadata] = {}
|
|
98
|
+
post[:metadata][:udf5] = application_id || 'ActiveMerchant'
|
|
90
99
|
end
|
|
91
100
|
|
|
92
|
-
def add_payment_method(post, payment_method)
|
|
93
|
-
post[:
|
|
94
|
-
post[:
|
|
95
|
-
post[:
|
|
96
|
-
post[:
|
|
97
|
-
post[:
|
|
98
|
-
post[:
|
|
101
|
+
def add_payment_method(post, payment_method, options)
|
|
102
|
+
post[:source] = {}
|
|
103
|
+
post[:source][:type] = 'card'
|
|
104
|
+
post[:source][:name] = payment_method.name
|
|
105
|
+
post[:source][:number] = payment_method.number
|
|
106
|
+
post[:source][:cvv] = payment_method.verification_value
|
|
107
|
+
post[:source][:expiry_year] = format(payment_method.year, :four_digits)
|
|
108
|
+
post[:source][:expiry_month] = format(payment_method.month, :two_digits)
|
|
109
|
+
post[:source][:stored] = 'true' if options[:card_on_file] == true
|
|
99
110
|
end
|
|
100
111
|
|
|
101
112
|
def add_customer_data(post, options)
|
|
102
|
-
post[:
|
|
103
|
-
post[:
|
|
113
|
+
post[:customer] = {}
|
|
114
|
+
post[:customer][:email] = options[:email] || nil
|
|
115
|
+
post[:payment_ip] = options[:ip] if options[:ip]
|
|
104
116
|
address = options[:billing_address]
|
|
105
|
-
if
|
|
106
|
-
post[:
|
|
107
|
-
post[:
|
|
108
|
-
post[:
|
|
109
|
-
post[:
|
|
110
|
-
post[:
|
|
111
|
-
post[:
|
|
112
|
-
post[:
|
|
113
|
-
post[:card][:billingDetails][:phone] = { number: address[:phone] } unless address[:phone].blank?
|
|
117
|
+
if address && post[:source]
|
|
118
|
+
post[:source][:billing_address] = {}
|
|
119
|
+
post[:source][:billing_address][:address_line1] = address[:address1] unless address[:address1].blank?
|
|
120
|
+
post[:source][:billing_address][:address_line2] = address[:address2] unless address[:address2].blank?
|
|
121
|
+
post[:source][:billing_address][:city] = address[:city] unless address[:city].blank?
|
|
122
|
+
post[:source][:billing_address][:state] = address[:state] unless address[:state].blank?
|
|
123
|
+
post[:source][:billing_address][:country] = address[:country] unless address[:country].blank?
|
|
124
|
+
post[:source][:billing_address][:zip] = address[:zip] unless address[:zip].blank?
|
|
114
125
|
end
|
|
115
126
|
end
|
|
116
127
|
|
|
117
|
-
def add_transaction_data(post, options={})
|
|
118
|
-
post[:
|
|
119
|
-
post[:
|
|
120
|
-
post[:
|
|
128
|
+
def add_transaction_data(post, options = {})
|
|
129
|
+
post[:payment_type] = 'Regular' if options[:transaction_indicator] == 1
|
|
130
|
+
post[:payment_type] = 'Recurring' if options[:transaction_indicator] == 2
|
|
131
|
+
post[:payment_type] = 'MOTO' if options[:transaction_indicator] == 3 || options.dig(:metadata, :manual_entry)
|
|
132
|
+
post[:previous_payment_id] = options[:previous_charge_id] if options[:previous_charge_id]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def add_3ds(post, options)
|
|
136
|
+
if options[:three_d_secure] || options[:execute_threed]
|
|
137
|
+
post[:'3ds'] = {}
|
|
138
|
+
post[:'3ds'][:enabled] = true
|
|
139
|
+
post[:success_url] = options[:callback_url] if options[:callback_url]
|
|
140
|
+
post[:failure_url] = options[:callback_url] if options[:callback_url]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
if options[:three_d_secure]
|
|
144
|
+
post[:'3ds'][:eci] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
|
|
145
|
+
post[:'3ds'][:cryptogram] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
|
|
146
|
+
post[:'3ds'][:version] = options[:three_d_secure][:version] if options[:three_d_secure][:version]
|
|
147
|
+
post[:'3ds'][:xid] = options[:three_d_secure][:ds_transaction_id] || options[:three_d_secure][:xid]
|
|
148
|
+
end
|
|
121
149
|
end
|
|
122
150
|
|
|
123
151
|
def commit(action, post, authorization = nil)
|
|
124
152
|
begin
|
|
125
|
-
raw_response = ssl_post(url(post, action, authorization), post.to_json, headers)
|
|
153
|
+
raw_response = (action == :verify_payment ? ssl_get("#{base_url}/payments/#{post}", headers) : ssl_post(url(post, action, authorization), post.to_json, headers))
|
|
126
154
|
response = parse(raw_response)
|
|
155
|
+
if action == :capture && response.key?('_links')
|
|
156
|
+
response['id'] = response['_links']['payment']['href'].split('/')[-1]
|
|
157
|
+
end
|
|
127
158
|
rescue ResponseError => e
|
|
128
|
-
raise unless
|
|
159
|
+
raise unless e.response.code.to_s =~ /4\d\d/
|
|
129
160
|
response = parse(e.response.body)
|
|
130
161
|
end
|
|
131
162
|
|
|
@@ -154,15 +185,21 @@ module ActiveMerchant #:nodoc:
|
|
|
154
185
|
def headers
|
|
155
186
|
{
|
|
156
187
|
'Authorization' => @options[:secret_key],
|
|
157
|
-
'Content-Type'
|
|
188
|
+
'Content-Type' => 'application/json;charset=UTF-8',
|
|
158
189
|
}
|
|
159
190
|
end
|
|
160
191
|
|
|
161
|
-
def url(
|
|
192
|
+
def url(_post, action, authorization)
|
|
162
193
|
if action == :authorize
|
|
163
|
-
"#{base_url}/
|
|
194
|
+
"#{base_url}/payments"
|
|
195
|
+
elsif action == :capture
|
|
196
|
+
"#{base_url}/payments/#{authorization}/captures"
|
|
197
|
+
elsif action == :refund
|
|
198
|
+
"#{base_url}/payments/#{authorization}/refunds"
|
|
199
|
+
elsif action == :void
|
|
200
|
+
"#{base_url}/payments/#{authorization}/voids"
|
|
164
201
|
else
|
|
165
|
-
"#{base_url}/
|
|
202
|
+
"#{base_url}/payments/#{authorization}/#{action}"
|
|
166
203
|
end
|
|
167
204
|
end
|
|
168
205
|
|
|
@@ -171,33 +208,33 @@ module ActiveMerchant #:nodoc:
|
|
|
171
208
|
end
|
|
172
209
|
|
|
173
210
|
def avs_result(response)
|
|
174
|
-
response['
|
|
211
|
+
response['source'] && response['source']['avs_check'] ? AVSResult.new(code: response['source']['avs_check']) : nil
|
|
175
212
|
end
|
|
176
213
|
|
|
177
214
|
def cvv_result(response)
|
|
178
|
-
response['
|
|
215
|
+
response['source'] && response['source']['cvv_check'] ? CVVResult.new(response['source']['cvv_check']) : nil
|
|
179
216
|
end
|
|
180
217
|
|
|
181
218
|
def parse(body)
|
|
182
219
|
JSON.parse(body)
|
|
183
220
|
rescue JSON::ParserError
|
|
184
221
|
{
|
|
185
|
-
'message' => 'Invalid JSON response received from
|
|
222
|
+
'message' => 'Invalid JSON response received from Checkout.com Unified Payments Gateway. Please contact Checkout.com if you continue to receive this message.',
|
|
186
223
|
'raw_response' => scrub(body)
|
|
187
224
|
}
|
|
188
225
|
end
|
|
189
226
|
|
|
190
227
|
def success_from(response)
|
|
191
|
-
|
|
228
|
+
response['response_summary'] == 'Approved' || response['approved'] == true || !response.key?('response_summary') && response.key?('action_id')
|
|
192
229
|
end
|
|
193
230
|
|
|
194
231
|
def message_from(succeeded, response)
|
|
195
232
|
if succeeded
|
|
196
233
|
'Succeeded'
|
|
197
|
-
elsif response['
|
|
198
|
-
response['
|
|
234
|
+
elsif response['error_type']
|
|
235
|
+
response['error_type'] + ': ' + response['error_codes'].first
|
|
199
236
|
else
|
|
200
|
-
response['
|
|
237
|
+
response['response_summary'] || response['response_code'] || 'Unable to read error message'
|
|
201
238
|
end
|
|
202
239
|
end
|
|
203
240
|
|
|
@@ -220,12 +257,12 @@ module ActiveMerchant #:nodoc:
|
|
|
220
257
|
|
|
221
258
|
def error_code_from(succeeded, response)
|
|
222
259
|
return if succeeded
|
|
223
|
-
if response['
|
|
224
|
-
"#{response[
|
|
225
|
-
elsif response['
|
|
226
|
-
response['
|
|
260
|
+
if response['error_type'] && response['error_codes']
|
|
261
|
+
"#{response['error_type']}: #{response['error_codes'].join(', ')}"
|
|
262
|
+
elsif response['error_type']
|
|
263
|
+
response['error_type']
|
|
227
264
|
else
|
|
228
|
-
STANDARD_ERROR_CODE_MAPPING[response['
|
|
265
|
+
STANDARD_ERROR_CODE_MAPPING[response['response_code']]
|
|
229
266
|
end
|
|
230
267
|
end
|
|
231
268
|
end
|