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
|
@@ -6,6 +6,10 @@ module ActiveMerchant #:nodoc:
|
|
|
6
6
|
self.display_name = 'Credorax Gateway'
|
|
7
7
|
self.homepage_url = 'https://www.credorax.com/'
|
|
8
8
|
|
|
9
|
+
# NOTE: the IP address you run the remote tests from will need to be
|
|
10
|
+
# whitelisted by Credorax; contact support@credorax.com as necessary to
|
|
11
|
+
# request your IP address be added to the whitelist for your test
|
|
12
|
+
# account.
|
|
9
13
|
self.test_url = 'https://intconsole.credorax.com/intenv/service/gateway'
|
|
10
14
|
|
|
11
15
|
# The live URL is assigned on a per merchant basis once certification has passed
|
|
@@ -15,7 +19,7 @@ module ActiveMerchant #:nodoc:
|
|
|
15
19
|
# ActiveMerchant::Billing::CredoraxGateway.live_url = "https://assigned-subdomain.credorax.net/crax_gate/service/gateway"
|
|
16
20
|
self.live_url = 'https://assigned-subdomain.credorax.net/crax_gate/service/gateway'
|
|
17
21
|
|
|
18
|
-
self.supported_countries = %w(
|
|
22
|
+
self.supported_countries = %w(AD AT BE BG HR CY CZ DK EE FR DE GI GR GG HU IS IE IM IT JE LV LI LT LU MT MC NO PL PT RO SM SK ES SE CH GB)
|
|
19
23
|
self.default_currency = 'EUR'
|
|
20
24
|
self.currencies_without_fractions = %w(CLP JPY KRW PYG VND)
|
|
21
25
|
self.currencies_with_three_decimal_places = %w(BHD JOD KWD OMR RSD TND)
|
|
@@ -131,6 +135,7 @@ module ActiveMerchant #:nodoc:
|
|
|
131
135
|
add_echo(post, options)
|
|
132
136
|
add_submerchant_id(post, options)
|
|
133
137
|
add_transaction_type(post, options)
|
|
138
|
+
add_processor(post, options)
|
|
134
139
|
|
|
135
140
|
commit(:purchase, post)
|
|
136
141
|
end
|
|
@@ -145,6 +150,7 @@ module ActiveMerchant #:nodoc:
|
|
|
145
150
|
add_echo(post, options)
|
|
146
151
|
add_submerchant_id(post, options)
|
|
147
152
|
add_transaction_type(post, options)
|
|
153
|
+
add_processor(post, options)
|
|
148
154
|
|
|
149
155
|
commit(:authorize, post)
|
|
150
156
|
end
|
|
@@ -156,6 +162,7 @@ module ActiveMerchant #:nodoc:
|
|
|
156
162
|
add_customer_data(post, options)
|
|
157
163
|
add_echo(post, options)
|
|
158
164
|
add_submerchant_id(post, options)
|
|
165
|
+
add_processor(post, options)
|
|
159
166
|
|
|
160
167
|
commit(:capture, post)
|
|
161
168
|
end
|
|
@@ -167,6 +174,7 @@ module ActiveMerchant #:nodoc:
|
|
|
167
174
|
add_echo(post, options)
|
|
168
175
|
add_submerchant_id(post, options)
|
|
169
176
|
post[:a1] = generate_unique_id
|
|
177
|
+
add_processor(post, options)
|
|
170
178
|
|
|
171
179
|
commit(:void, post, reference_action)
|
|
172
180
|
end
|
|
@@ -178,6 +186,7 @@ module ActiveMerchant #:nodoc:
|
|
|
178
186
|
add_customer_data(post, options)
|
|
179
187
|
add_echo(post, options)
|
|
180
188
|
add_submerchant_id(post, options)
|
|
189
|
+
add_processor(post, options)
|
|
181
190
|
|
|
182
191
|
commit(:refund, post)
|
|
183
192
|
end
|
|
@@ -191,6 +200,7 @@ module ActiveMerchant #:nodoc:
|
|
|
191
200
|
add_echo(post, options)
|
|
192
201
|
add_submerchant_id(post, options)
|
|
193
202
|
add_transaction_type(post, options)
|
|
203
|
+
add_processor(post, options)
|
|
194
204
|
|
|
195
205
|
commit(:credit, post)
|
|
196
206
|
end
|
|
@@ -264,8 +274,56 @@ module ActiveMerchant #:nodoc:
|
|
|
264
274
|
end
|
|
265
275
|
|
|
266
276
|
def add_3d_secure(post, options)
|
|
267
|
-
|
|
268
|
-
|
|
277
|
+
if options[:eci] && options[:xid]
|
|
278
|
+
add_3d_secure_1_data(post, options)
|
|
279
|
+
elsif options[:execute_threed] && options[:three_ds_2]
|
|
280
|
+
three_ds_2_options = options[:three_ds_2]
|
|
281
|
+
browser_info = three_ds_2_options[:browser_info]
|
|
282
|
+
post[:'3ds_initiate'] = options[:three_ds_initiate] || '01'
|
|
283
|
+
post[:'3ds_purchasedate'] = Time.now.utc.strftime('%Y%m%d%I%M%S')
|
|
284
|
+
post[:'3ds_channel'] = '02'
|
|
285
|
+
post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
|
|
286
|
+
post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
|
|
287
|
+
post[:'3ds_version'] = options[:three_ds_version] if options[:three_ds_version]
|
|
288
|
+
post[:d5] = browser_info[:user_agent]
|
|
289
|
+
post[:'3ds_transtype'] = options[:transaction_type] || '01'
|
|
290
|
+
post[:'3ds_browsertz'] = browser_info[:timezone]
|
|
291
|
+
post[:'3ds_browserscreenwidth'] = browser_info[:width]
|
|
292
|
+
post[:'3ds_browserscreenheight'] = browser_info[:height]
|
|
293
|
+
post[:'3ds_browsercolordepth'] = browser_info[:depth]
|
|
294
|
+
post[:d6] = browser_info[:language]
|
|
295
|
+
post[:'3ds_browserjavaenabled'] = browser_info[:java]
|
|
296
|
+
post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
|
|
297
|
+
if (shipping_address = options[:shipping_address])
|
|
298
|
+
post[:'3ds_shipaddrstate'] = shipping_address[:state]
|
|
299
|
+
post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
|
|
300
|
+
post[:'3ds_shipaddrline2'] = shipping_address[:address2]
|
|
301
|
+
post[:'3ds_shipaddrline1'] = shipping_address[:address1]
|
|
302
|
+
post[:'3ds_shipaddrcountry'] = shipping_address[:country]
|
|
303
|
+
post[:'3ds_shipaddrcity'] = shipping_address[:city]
|
|
304
|
+
end
|
|
305
|
+
elsif options[:three_d_secure]
|
|
306
|
+
add_normalized_3d_secure_2_data(post, options)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def add_3d_secure_1_data(post, options)
|
|
311
|
+
post[:i8] = build_i8(options[:eci], options[:cavv], options[:xid])
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def add_normalized_3d_secure_2_data(post, options)
|
|
315
|
+
three_d_secure_options = options[:three_d_secure]
|
|
316
|
+
|
|
317
|
+
post[:i8] = build_i8(
|
|
318
|
+
three_d_secure_options[:eci],
|
|
319
|
+
three_d_secure_options[:cavv]
|
|
320
|
+
)
|
|
321
|
+
post[:'3ds_version'] = three_d_secure_options[:version]
|
|
322
|
+
post[:'3ds_dstrxid'] = three_d_secure_options[:ds_transaction_id]
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def build_i8(eci, cavv=nil, xid=nil)
|
|
326
|
+
"#{eci}:#{cavv || 'none'}:#{xid || 'none'}"
|
|
269
327
|
end
|
|
270
328
|
|
|
271
329
|
def add_echo(post, options)
|
|
@@ -280,6 +338,12 @@ module ActiveMerchant #:nodoc:
|
|
|
280
338
|
|
|
281
339
|
def add_transaction_type(post, options)
|
|
282
340
|
post[:a9] = options[:transaction_type] if options[:transaction_type]
|
|
341
|
+
post[:a2] = '3' if options.dig(:metadata, :manual_entry)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def add_processor(post, options)
|
|
345
|
+
post[:r1] = options[:processor] || 'CREDORAX'
|
|
346
|
+
post[:r2] = options[:processor_merchant_id] if options[:processor_merchant_id]
|
|
283
347
|
end
|
|
284
348
|
|
|
285
349
|
ACTIONS = {
|
|
@@ -291,7 +355,8 @@ module ActiveMerchant #:nodoc:
|
|
|
291
355
|
credit: '6',
|
|
292
356
|
purchase_void: '7',
|
|
293
357
|
refund_void: '8',
|
|
294
|
-
capture_void: '9'
|
|
358
|
+
capture_void: '9',
|
|
359
|
+
threeds_completion: '92'
|
|
295
360
|
}
|
|
296
361
|
|
|
297
362
|
def commit(action, params, reference_action = nil)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
|
3
3
|
# Initial setup instructions can be found in
|
|
4
|
-
# http://cybersource.com/
|
|
4
|
+
# http://apps.cybersource.com/library/documentation/dev_guides/SOAP_Toolkits/SOAP_toolkits.pdf
|
|
5
5
|
#
|
|
6
6
|
# Important Notes
|
|
7
7
|
# * For checks you can purchase and store.
|
|
@@ -24,10 +24,12 @@ module ActiveMerchant #:nodoc:
|
|
|
24
24
|
self.test_url = 'https://ics2wstesta.ic3.com/commerce/1.x/transactionProcessor'
|
|
25
25
|
self.live_url = 'https://ics2wsa.ic3.com/commerce/1.x/transactionProcessor'
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
# Schema files can be found here: https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/
|
|
28
|
+
TEST_XSD_VERSION = '1.159'
|
|
29
|
+
PRODUCTION_XSD_VERSION = '1.159'
|
|
28
30
|
|
|
29
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro]
|
|
30
|
-
self.supported_countries = %w(US BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB)
|
|
31
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro, :elo]
|
|
32
|
+
self.supported_countries = %w(US BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB PK)
|
|
31
33
|
|
|
32
34
|
self.default_currency = 'USD'
|
|
33
35
|
self.currencies_without_fractions = %w(JPY)
|
|
@@ -43,7 +45,8 @@ module ActiveMerchant #:nodoc:
|
|
|
43
45
|
:diners_club => '005',
|
|
44
46
|
:jcb => '007',
|
|
45
47
|
:dankort => '034',
|
|
46
|
-
:maestro => '042'
|
|
48
|
+
:maestro => '042',
|
|
49
|
+
:elo => '054'
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
@@response_codes = {
|
|
@@ -142,9 +145,10 @@ module ActiveMerchant #:nodoc:
|
|
|
142
145
|
end
|
|
143
146
|
end
|
|
144
147
|
|
|
145
|
-
# Adds credit to a subscription (stand alone credit).
|
|
146
|
-
def credit(money,
|
|
147
|
-
|
|
148
|
+
# Adds credit to a card or subscription (stand alone credit).
|
|
149
|
+
def credit(money, creditcard_or_reference, options = {})
|
|
150
|
+
setup_address_hash(options)
|
|
151
|
+
commit(build_credit_request(money, creditcard_or_reference, options), :credit, money, options)
|
|
148
152
|
end
|
|
149
153
|
|
|
150
154
|
# Stores a customer subscription/profile with type "on-demand".
|
|
@@ -254,12 +258,16 @@ module ActiveMerchant #:nodoc:
|
|
|
254
258
|
def build_auth_request(money, creditcard_or_reference, options)
|
|
255
259
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
256
260
|
add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
|
|
261
|
+
add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
|
|
257
262
|
add_decision_manager_fields(xml, options)
|
|
258
263
|
add_mdd_fields(xml, options)
|
|
259
264
|
add_auth_service(xml, creditcard_or_reference, options)
|
|
260
265
|
add_threeds_services(xml, options)
|
|
261
266
|
add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
|
|
262
267
|
add_business_rules_data(xml, creditcard_or_reference, options)
|
|
268
|
+
add_stored_credential_options(xml, options)
|
|
269
|
+
add_issuer_additional_data(xml, options)
|
|
270
|
+
|
|
263
271
|
xml.target!
|
|
264
272
|
end
|
|
265
273
|
|
|
@@ -288,6 +296,7 @@ module ActiveMerchant #:nodoc:
|
|
|
288
296
|
def build_purchase_request(money, payment_method_or_reference, options)
|
|
289
297
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
290
298
|
add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
|
|
299
|
+
add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
|
|
291
300
|
add_decision_manager_fields(xml, options)
|
|
292
301
|
add_mdd_fields(xml, options)
|
|
293
302
|
if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
|
|
@@ -298,6 +307,8 @@ module ActiveMerchant #:nodoc:
|
|
|
298
307
|
add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
|
|
299
308
|
add_business_rules_data(xml, payment_method_or_reference, options) unless options[:pinless_debit_card]
|
|
300
309
|
end
|
|
310
|
+
add_issuer_additional_data(xml, options)
|
|
311
|
+
|
|
301
312
|
xml.target!
|
|
302
313
|
end
|
|
303
314
|
|
|
@@ -326,11 +337,10 @@ module ActiveMerchant #:nodoc:
|
|
|
326
337
|
xml.target!
|
|
327
338
|
end
|
|
328
339
|
|
|
329
|
-
def build_credit_request(money,
|
|
340
|
+
def build_credit_request(money, creditcard_or_reference, options)
|
|
330
341
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
331
342
|
|
|
332
|
-
|
|
333
|
-
add_subscription(xml, options, reference)
|
|
343
|
+
add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
|
|
334
344
|
add_credit_service(xml)
|
|
335
345
|
|
|
336
346
|
xml.target!
|
|
@@ -483,6 +493,14 @@ module ActiveMerchant #:nodoc:
|
|
|
483
493
|
end
|
|
484
494
|
end
|
|
485
495
|
|
|
496
|
+
def add_issuer_additional_data(xml, options)
|
|
497
|
+
return unless options[:issuer_additional_data]
|
|
498
|
+
|
|
499
|
+
xml.tag! 'issuer' do
|
|
500
|
+
xml.tag! 'additionalData', options[:issuer_additional_data]
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
486
504
|
def add_mdd_fields(xml, options)
|
|
487
505
|
return unless options.keys.any? { |key| key.to_s.start_with?('mdd_field') }
|
|
488
506
|
|
|
@@ -513,7 +531,46 @@ module ActiveMerchant #:nodoc:
|
|
|
513
531
|
if network_tokenization?(payment_method)
|
|
514
532
|
add_auth_network_tokenization(xml, payment_method, options)
|
|
515
533
|
else
|
|
516
|
-
xml.tag! 'ccAuthService', {'run' => 'true'}
|
|
534
|
+
xml.tag! 'ccAuthService', {'run' => 'true'} do
|
|
535
|
+
if options[:three_d_secure]
|
|
536
|
+
add_normalized_threeds_2_data(xml, payment_method, options)
|
|
537
|
+
else
|
|
538
|
+
indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options)
|
|
539
|
+
xml.tag!('commerceIndicator', indicator) if indicator
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def add_normalized_threeds_2_data(xml, payment_method, options)
|
|
546
|
+
threeds_2_options = options[:three_d_secure]
|
|
547
|
+
|
|
548
|
+
xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && card_brand(payment_method).to_sym != :master
|
|
549
|
+
xml.tag!('cavvAlgorithm', threeds_2_options[:cavv_algorithm]) if threeds_2_options[:cavv_algorithm]
|
|
550
|
+
xml.tag!('paSpecificationVersion', threeds_2_options[:version]) if threeds_2_options[:version]
|
|
551
|
+
xml.tag!('directoryServerTransactionID', threeds_2_options[:ds_transaction_id]) if threeds_2_options[:ds_transaction_id]
|
|
552
|
+
xml.tag!('commerceIndicator', options[:commerce_indicator]) if options[:commerce_indicator]
|
|
553
|
+
xml.tag!('eciRaw', threeds_2_options[:eci]) if threeds_2_options[:eci]
|
|
554
|
+
xml.tag!('xid', threeds_2_options[:xid]) if threeds_2_options[:xid]
|
|
555
|
+
xml.tag!('veresEnrolled', threeds_2_options[:enrolled]) if threeds_2_options[:enrolled]
|
|
556
|
+
xml.tag!('paresStatus', threeds_2_options[:authentication_response_status]) if threeds_2_options[:authentication_response_status]
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def add_threeds_2_ucaf_data(xml, payment_method, options)
|
|
560
|
+
return unless options[:three_d_secure] && card_brand(payment_method).to_sym == :master
|
|
561
|
+
|
|
562
|
+
xml.tag! 'ucaf' do
|
|
563
|
+
xml.tag!('authenticationData', options[:three_d_secure][:cavv])
|
|
564
|
+
xml.tag!('collectionIndicator', options[:collection_indicator]) if options[:collection_indicator]
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def stored_credential_commerce_indicator(options)
|
|
569
|
+
return unless options[:stored_credential]
|
|
570
|
+
return if options[:stored_credential][:initial_transaction]
|
|
571
|
+
case options[:stored_credential][:reason_type]
|
|
572
|
+
when 'installment' then 'install'
|
|
573
|
+
when 'recurring' then 'recurring'
|
|
517
574
|
end
|
|
518
575
|
end
|
|
519
576
|
|
|
@@ -531,7 +588,7 @@ module ActiveMerchant #:nodoc:
|
|
|
531
588
|
xml.tag!('commerceIndicator', 'vbv')
|
|
532
589
|
xml.tag!('xid', payment_method.payment_cryptogram)
|
|
533
590
|
end
|
|
534
|
-
when :
|
|
591
|
+
when :master
|
|
535
592
|
xml.tag! 'ucaf' do
|
|
536
593
|
xml.tag!('authenticationData', payment_method.payment_cryptogram)
|
|
537
594
|
xml.tag!('collectionIndicator', '2')
|
|
@@ -680,8 +737,22 @@ module ActiveMerchant #:nodoc:
|
|
|
680
737
|
country_code&.code(:alpha2)
|
|
681
738
|
end
|
|
682
739
|
|
|
740
|
+
def add_stored_credential_options(xml, options={})
|
|
741
|
+
return unless options[:stored_credential]
|
|
742
|
+
if options[:stored_credential][:initial_transaction]
|
|
743
|
+
xml.tag! 'subsequentAuthFirst', 'true'
|
|
744
|
+
elsif options[:stored_credential][:reason_type] == 'unscheduled'
|
|
745
|
+
xml.tag! 'subsequentAuth', 'true'
|
|
746
|
+
xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
|
|
747
|
+
else
|
|
748
|
+
xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
|
|
749
|
+
end
|
|
750
|
+
end
|
|
751
|
+
|
|
683
752
|
# Where we actually build the full SOAP request using builder
|
|
684
753
|
def build_request(body, options)
|
|
754
|
+
xsd_version = test? ? TEST_XSD_VERSION : PRODUCTION_XSD_VERSION
|
|
755
|
+
|
|
685
756
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
686
757
|
xml.instruct!
|
|
687
758
|
xml.tag! 's:Envelope', {'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/'} do
|
|
@@ -694,7 +765,7 @@ module ActiveMerchant #:nodoc:
|
|
|
694
765
|
end
|
|
695
766
|
end
|
|
696
767
|
xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
|
|
697
|
-
xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{
|
|
768
|
+
xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}"} do
|
|
698
769
|
add_merchant_data(xml, options)
|
|
699
770
|
xml << body
|
|
700
771
|
end
|
|
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
|
6
6
|
|
|
7
7
|
self.supported_countries = ['AR', 'BR', 'CL', 'CO', 'MX', 'PE', 'UY', 'TR']
|
|
8
8
|
self.default_currency = 'USD'
|
|
9
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
|
|
9
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro, :naranja, :cabal]
|
|
10
10
|
|
|
11
11
|
self.homepage_url = 'https://dlocal.com/'
|
|
12
12
|
self.display_name = 'dLocal'
|
|
@@ -93,7 +93,7 @@ module ActiveMerchant #:nodoc:
|
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def lookup_country_code(country)
|
|
96
|
-
Country.find(country).code(:alpha2)
|
|
96
|
+
Country.find(country).code(:alpha2).value
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
def add_payer(post, card, options)
|
|
@@ -102,7 +102,7 @@ module ActiveMerchant #:nodoc:
|
|
|
102
102
|
post[:payer][:name] = card.name
|
|
103
103
|
post[:payer][:email] = options[:email] if options[:email]
|
|
104
104
|
post[:payer][:birth_date] = options[:birth_date] if options[:birth_date]
|
|
105
|
-
post[:payer][:phone] = address[:phone] if address[:phone]
|
|
105
|
+
post[:payer][:phone] = address[:phone] if address && address[:phone]
|
|
106
106
|
post[:payer][:document] = options[:document] if options[:document]
|
|
107
107
|
post[:payer][:document2] = options[:document2] if options[:document2]
|
|
108
108
|
post[:payer][:user_reference] = options[:user_reference] if options[:user_reference]
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
class DecidirGateway < Gateway
|
|
4
|
+
self.test_url = 'https://developers.decidir.com/api/v2'
|
|
5
|
+
self.live_url = 'https://live.decidir.com/api/v2'
|
|
6
|
+
|
|
7
|
+
self.supported_countries = ['AR']
|
|
8
|
+
self.money_format = :cents
|
|
9
|
+
self.default_currency = 'ARS'
|
|
10
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :naranja, :cabal]
|
|
11
|
+
|
|
12
|
+
self.homepage_url = 'http://www.decidir.com'
|
|
13
|
+
self.display_name = 'Decidir'
|
|
14
|
+
|
|
15
|
+
STANDARD_ERROR_CODE_MAPPING = {
|
|
16
|
+
1 => STANDARD_ERROR_CODE[:call_issuer],
|
|
17
|
+
2 => STANDARD_ERROR_CODE[:call_issuer],
|
|
18
|
+
3 => STANDARD_ERROR_CODE[:config_error],
|
|
19
|
+
4 => STANDARD_ERROR_CODE[:pickup_card],
|
|
20
|
+
5 => STANDARD_ERROR_CODE[:card_declined],
|
|
21
|
+
7 => STANDARD_ERROR_CODE[:pickup_card],
|
|
22
|
+
12 => STANDARD_ERROR_CODE[:processing_error],
|
|
23
|
+
14 => STANDARD_ERROR_CODE[:invalid_number],
|
|
24
|
+
28 => STANDARD_ERROR_CODE[:processing_error],
|
|
25
|
+
38 => STANDARD_ERROR_CODE[:incorrect_pin],
|
|
26
|
+
39 => STANDARD_ERROR_CODE[:invalid_number],
|
|
27
|
+
43 => STANDARD_ERROR_CODE[:pickup_card],
|
|
28
|
+
45 => STANDARD_ERROR_CODE[:card_declined],
|
|
29
|
+
46 => STANDARD_ERROR_CODE[:invalid_number],
|
|
30
|
+
47 => STANDARD_ERROR_CODE[:card_declined],
|
|
31
|
+
48 => STANDARD_ERROR_CODE[:card_declined],
|
|
32
|
+
49 => STANDARD_ERROR_CODE[:invalid_expiry_date],
|
|
33
|
+
51 => STANDARD_ERROR_CODE[:card_declined],
|
|
34
|
+
53 => STANDARD_ERROR_CODE[:card_declined],
|
|
35
|
+
54 => STANDARD_ERROR_CODE[:expired_card],
|
|
36
|
+
55 => STANDARD_ERROR_CODE[:incorrect_pin],
|
|
37
|
+
56 => STANDARD_ERROR_CODE[:card_declined],
|
|
38
|
+
57 => STANDARD_ERROR_CODE[:card_declined],
|
|
39
|
+
76 => STANDARD_ERROR_CODE[:call_issuer],
|
|
40
|
+
96 => STANDARD_ERROR_CODE[:processing_error],
|
|
41
|
+
97 => STANDARD_ERROR_CODE[:processing_error],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def initialize(options={})
|
|
45
|
+
requires!(options, :api_key)
|
|
46
|
+
super
|
|
47
|
+
@options[:preauth_mode] ||= false
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def purchase(money, payment, options={})
|
|
51
|
+
raise ArgumentError, 'Purchase is not supported on Decidir gateways configured with the preauth_mode option' if @options[:preauth_mode]
|
|
52
|
+
|
|
53
|
+
post = {}
|
|
54
|
+
add_auth_purchase_params(post, money, payment, options)
|
|
55
|
+
commit(:post, 'payments', post)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def authorize(money, payment, options={})
|
|
59
|
+
raise ArgumentError, 'Authorize is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
|
|
60
|
+
|
|
61
|
+
post = {}
|
|
62
|
+
add_auth_purchase_params(post, money, payment, options)
|
|
63
|
+
commit(:post, 'payments', post)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def capture(money, authorization, options={})
|
|
67
|
+
raise ArgumentError, 'Capture is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
|
|
68
|
+
|
|
69
|
+
post = {}
|
|
70
|
+
add_amount(post, money, options)
|
|
71
|
+
commit(:put, "payments/#{authorization}", post)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def refund(money, authorization, options={})
|
|
75
|
+
post = {}
|
|
76
|
+
add_amount(post, money, options)
|
|
77
|
+
commit(:post, "payments/#{authorization}/refunds", post)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def void(authorization, options={})
|
|
81
|
+
post = {}
|
|
82
|
+
commit(:post, "payments/#{authorization}/refunds", post)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def verify(credit_card, options={})
|
|
86
|
+
raise ArgumentError, 'Verify is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
|
|
87
|
+
|
|
88
|
+
MultiResponse.run(:use_first_response) do |r|
|
|
89
|
+
r.process { authorize(100, credit_card, options) }
|
|
90
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def supports_scrubbing?
|
|
95
|
+
true
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def scrub(transcript)
|
|
99
|
+
transcript.
|
|
100
|
+
gsub(%r((apikey: )\w+)i, '\1[FILTERED]').
|
|
101
|
+
gsub(%r((\"card_number\\\":\\\")\d+), '\1[FILTERED]').
|
|
102
|
+
gsub(%r((\"security_code\\\":\\\")\d+), '\1[FILTERED]').
|
|
103
|
+
gsub(%r((\"emv_issuer_data\\\":\\\")\d+), '\1[FILTERED]')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def add_auth_purchase_params(post, money, credit_card, options)
|
|
109
|
+
post[:payment_method_id] = add_payment_method_id(credit_card)
|
|
110
|
+
post[:site_transaction_id] = options[:order_id]
|
|
111
|
+
post[:bin] = credit_card.number[0..5]
|
|
112
|
+
post[:payment_type] = options[:payment_type] || 'single'
|
|
113
|
+
post[:installments] = options[:installments] ? options[:installments].to_i : 1
|
|
114
|
+
post[:description] = options[:description] if options[:description]
|
|
115
|
+
post[:email] = options[:email] if options[:email]
|
|
116
|
+
post[:sub_payments] = []
|
|
117
|
+
|
|
118
|
+
add_invoice(post, money, options)
|
|
119
|
+
add_payment(post, credit_card, options)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def add_payment_method_id(credit_card)
|
|
123
|
+
if options[:payment_method_id]
|
|
124
|
+
options[:payment_method_id].to_i
|
|
125
|
+
elsif CreditCard.brand?(credit_card.number) == 'cabal'
|
|
126
|
+
63
|
|
127
|
+
elsif CreditCard.brand?(credit_card.number) == 'naranja'
|
|
128
|
+
24
|
|
129
|
+
else
|
|
130
|
+
1
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def add_invoice(post, money, options)
|
|
135
|
+
add_amount(post, money, options)
|
|
136
|
+
post[:currency] = (options[:currency] || currency(money))
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def add_amount(post, money, options)
|
|
140
|
+
currency = (options[:currency] || currency(money))
|
|
141
|
+
post[:amount] = localized_amount(money, currency).to_i
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def add_payment(post, credit_card, options)
|
|
145
|
+
card_data = {}
|
|
146
|
+
card_data[:card_number] = credit_card.number
|
|
147
|
+
card_data[:card_expiration_month] = format(credit_card.month, :two_digits)
|
|
148
|
+
card_data[:card_expiration_year] = format(credit_card.year, :two_digits)
|
|
149
|
+
card_data[:security_code] = credit_card.verification_value if credit_card.verification_value?
|
|
150
|
+
card_data[:card_holder_name] = credit_card.name if credit_card.name
|
|
151
|
+
|
|
152
|
+
# additional data used for Visa transactions
|
|
153
|
+
card_data[:card_holder_door_number] = options[:card_holder_door_number].to_i if options[:card_holder_door_number]
|
|
154
|
+
card_data[:card_holder_birthday] = options[:card_holder_birthday] if options[:card_holder_birthday]
|
|
155
|
+
|
|
156
|
+
card_data[:card_holder_identification] = {}
|
|
157
|
+
card_data[:card_holder_identification][:type] = options[:card_holder_identification_type] if options[:card_holder_identification_type]
|
|
158
|
+
card_data[:card_holder_identification][:number] = options[:card_holder_identification_number] if options[:card_holder_identification_number]
|
|
159
|
+
|
|
160
|
+
post[:card_data] = card_data
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def headers(options = {})
|
|
164
|
+
{
|
|
165
|
+
'apikey' => @options[:api_key],
|
|
166
|
+
'Content-type' => 'application/json',
|
|
167
|
+
'Cache-Control' => 'no-cache'
|
|
168
|
+
}
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def commit(method, endpoint, parameters, options={})
|
|
172
|
+
url = "#{(test? ? test_url : live_url)}/#{endpoint}"
|
|
173
|
+
|
|
174
|
+
begin
|
|
175
|
+
raw_response = ssl_request(method, url, post_data(parameters), headers(options))
|
|
176
|
+
response = parse(raw_response)
|
|
177
|
+
rescue ResponseError => e
|
|
178
|
+
raw_response = e.response.body
|
|
179
|
+
response = parse(raw_response)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
success = success_from(response)
|
|
183
|
+
Response.new(
|
|
184
|
+
success,
|
|
185
|
+
message_from(success, response),
|
|
186
|
+
response,
|
|
187
|
+
authorization: authorization_from(response),
|
|
188
|
+
test: test?,
|
|
189
|
+
error_code: success ? nil : error_code_from(response)
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def post_data(parameters = {})
|
|
194
|
+
parameters.to_json
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def parse(body)
|
|
198
|
+
JSON.parse(body)
|
|
199
|
+
rescue JSON::ParserError
|
|
200
|
+
{
|
|
201
|
+
'message' => "A non-JSON response was received from Decidir where one was expected. The raw response was:\n\n#{body}"
|
|
202
|
+
}
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def message_from(success, response)
|
|
206
|
+
return response['status'] if success
|
|
207
|
+
return response['message'] if response['message']
|
|
208
|
+
|
|
209
|
+
message = nil
|
|
210
|
+
|
|
211
|
+
if error = response.dig('status_details', 'error')
|
|
212
|
+
message = error.dig('reason', 'description')
|
|
213
|
+
elsif response['error_type']
|
|
214
|
+
if response['validation_errors']
|
|
215
|
+
message = response['validation_errors'].map { |errors| "#{errors['code']}: #{errors['param']}" }.join(', ')
|
|
216
|
+
end
|
|
217
|
+
message ||= response['error_type']
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
message
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def success_from(response)
|
|
224
|
+
response['status'] == 'approved' || response['status'] == 'pre_approved'
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def authorization_from(response)
|
|
228
|
+
response['id']
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def error_code_from(response)
|
|
232
|
+
error_code = nil
|
|
233
|
+
if error = response.dig('status_details', 'error')
|
|
234
|
+
code = error.dig('reason', 'id')
|
|
235
|
+
error_code = STANDARD_ERROR_CODE_MAPPING[code]
|
|
236
|
+
error_code ||= error['type']
|
|
237
|
+
elsif response['error_type']
|
|
238
|
+
error_code = response['error_type'] if response['validation_errors']
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
error_code || STANDARD_ERROR_CODE[:processing_error]
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
@@ -42,6 +42,7 @@ module ActiveMerchant #:nodoc:
|
|
|
42
42
|
else
|
|
43
43
|
add_creditcard(form, payment_method)
|
|
44
44
|
end
|
|
45
|
+
add_currency(form, money, options)
|
|
45
46
|
add_address(form, options)
|
|
46
47
|
add_customer_data(form, options)
|
|
47
48
|
add_test_mode(form, options)
|
|
@@ -54,6 +55,7 @@ module ActiveMerchant #:nodoc:
|
|
|
54
55
|
add_salestax(form, options)
|
|
55
56
|
add_invoice(form, options)
|
|
56
57
|
add_creditcard(form, creditcard)
|
|
58
|
+
add_currency(form, money, options)
|
|
57
59
|
add_address(form, options)
|
|
58
60
|
add_customer_data(form, options)
|
|
59
61
|
add_test_mode(form, options)
|
|
@@ -69,6 +71,7 @@ module ActiveMerchant #:nodoc:
|
|
|
69
71
|
add_approval_code(form, authorization)
|
|
70
72
|
add_invoice(form, options)
|
|
71
73
|
add_creditcard(form, options[:credit_card])
|
|
74
|
+
add_currency(form, money, options)
|
|
72
75
|
add_customer_data(form, options)
|
|
73
76
|
add_test_mode(form, options)
|
|
74
77
|
else
|
|
@@ -102,6 +105,7 @@ module ActiveMerchant #:nodoc:
|
|
|
102
105
|
form = {}
|
|
103
106
|
add_invoice(form, options)
|
|
104
107
|
add_creditcard(form, creditcard)
|
|
108
|
+
add_currency(form, money, options)
|
|
105
109
|
add_address(form, options)
|
|
106
110
|
add_customer_data(form, options)
|
|
107
111
|
add_test_mode(form, options)
|
|
@@ -178,6 +182,11 @@ module ActiveMerchant #:nodoc:
|
|
|
178
182
|
form[:last_name] = truncate(creditcard.last_name, 30)
|
|
179
183
|
end
|
|
180
184
|
|
|
185
|
+
def add_currency(form, money, options)
|
|
186
|
+
currency = options[:currency] || currency(money)
|
|
187
|
+
form[:transaction_currency] = currency if currency && (@options[:multi_currency] || options[:multi_currency])
|
|
188
|
+
end
|
|
189
|
+
|
|
181
190
|
def add_token(form, token)
|
|
182
191
|
form[:token] = token
|
|
183
192
|
end
|