activemerchant 1.94.0 → 1.99.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +120 -1
- data/README.md +3 -0
- data/lib/active_merchant/billing/avs_result.rb +4 -5
- data/lib/active_merchant/billing/credit_card.rb +6 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +65 -2
- data/lib/active_merchant/billing/gateway.rb +10 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +119 -34
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
- data/lib/active_merchant/billing/gateways/beanstream.rb +11 -6
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +3 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -2
- data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +56 -9
- data/lib/active_merchant/billing/gateways/card_connect.rb +2 -1
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +37 -27
- data/lib/active_merchant/billing/gateways/credorax.rb +69 -4
- data/lib/active_merchant/billing/gateways/cyber_source.rb +51 -11
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +245 -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 +6 -0
- 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/kushki.rb +1 -1
- 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/mundipagg.rb +33 -6
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/nmi.rb +39 -1
- data/lib/active_merchant/billing/gateways/opp.rb +20 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +60 -10
- data/lib/active_merchant/billing/gateways/payflow.rb +64 -14
- 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/payu_latam.rb +6 -2
- data/lib/active_merchant/billing/gateways/qvalent.rb +43 -1
- data/lib/active_merchant/billing/gateways/realex.rb +32 -9
- 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 +38 -9
- 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 +2 -2
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +45 -6
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -5
- data/lib/active_merchant/billing/gateways/worldpay.rb +177 -39
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +19 -4
@@ -27,6 +27,7 @@ module ActiveMerchant #:nodoc:
|
|
27
27
|
add_order_number(post, options)
|
28
28
|
add_payment_method(post, payment_method)
|
29
29
|
add_verification_value(post, payment_method)
|
30
|
+
add_stored_credential_data(post, payment_method, options)
|
30
31
|
add_customer_data(post, options)
|
31
32
|
add_soft_descriptors(post, options)
|
32
33
|
|
@@ -39,6 +40,7 @@ module ActiveMerchant #:nodoc:
|
|
39
40
|
add_order_number(post, options)
|
40
41
|
add_payment_method(post, payment_method)
|
41
42
|
add_verification_value(post, payment_method)
|
43
|
+
add_stored_credential_data(post, payment_method, options)
|
42
44
|
add_customer_data(post, options)
|
43
45
|
add_soft_descriptors(post, options)
|
44
46
|
|
@@ -61,6 +63,7 @@ module ActiveMerchant #:nodoc:
|
|
61
63
|
add_reference(post, authorization, options)
|
62
64
|
add_customer_data(post, options)
|
63
65
|
add_soft_descriptors(post, options)
|
66
|
+
post['order.ECI'] = options[:eci] || 'SSL'
|
64
67
|
|
65
68
|
commit('refund', post)
|
66
69
|
end
|
@@ -124,7 +127,6 @@ module ActiveMerchant #:nodoc:
|
|
124
127
|
def add_invoice(post, money, options)
|
125
128
|
post['order.amount'] = amount(money)
|
126
129
|
post['card.currency'] = CURRENCY_CODES[options[:currency] || currency(money)]
|
127
|
-
post['order.ECI'] = options[:eci] || 'SSL'
|
128
130
|
end
|
129
131
|
|
130
132
|
def add_payment_method(post, payment_method)
|
@@ -134,6 +136,46 @@ module ActiveMerchant #:nodoc:
|
|
134
136
|
post['card.expiryMonth'] = format(payment_method.month, :two_digits)
|
135
137
|
end
|
136
138
|
|
139
|
+
def add_stored_credential_data(post, payment_method, options)
|
140
|
+
post['order.ECI'] = options[:eci] || eci(options)
|
141
|
+
if (stored_credential = options[:stored_credential]) && %w(visa master).include?(payment_method.brand)
|
142
|
+
post['card.posEntryMode'] = stored_credential[:initial_transaction] ? 'MANUAL' : 'STORED_CREDENTIAL'
|
143
|
+
stored_credential_usage(post, payment_method, options) unless stored_credential[:initiator] && stored_credential[:initiator] == 'cardholder'
|
144
|
+
post['order.authTraceId'] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def stored_credential_usage(post, payment_method, options)
|
149
|
+
return unless payment_method.brand == 'visa'
|
150
|
+
stored_credential = options[:stored_credential]
|
151
|
+
if stored_credential[:initial_transaction]
|
152
|
+
post['card.storedCredentialUsage'] = 'INITIAL_STORAGE'
|
153
|
+
elsif stored_credential[:reason_type] == ('recurring' || 'installment')
|
154
|
+
post['card.storedCredentialUsage'] = 'RECURRING'
|
155
|
+
elsif stored_credential[:reason_type] == 'unscheduled'
|
156
|
+
post['card.storedCredentialUsage'] = 'UNSCHEDULED'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def eci(options)
|
161
|
+
if options.dig(:stored_credential, :initial_transaction)
|
162
|
+
'SSL'
|
163
|
+
elsif options.dig(:stored_credential, :initiator) && options[:stored_credential][:initiator] == 'cardholder'
|
164
|
+
'MTO'
|
165
|
+
elsif options.dig(:stored_credential, :reason_type)
|
166
|
+
case options[:stored_credential][:reason_type]
|
167
|
+
when 'recurring'
|
168
|
+
'REC'
|
169
|
+
when 'installment'
|
170
|
+
'INS'
|
171
|
+
when 'unscheduled'
|
172
|
+
'MTO'
|
173
|
+
end
|
174
|
+
else
|
175
|
+
'SSL'
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
137
179
|
def add_verification_value(post, payment_method)
|
138
180
|
post['card.CVN'] = payment_method.verification_value
|
139
181
|
end
|
@@ -42,7 +42,8 @@ module ActiveMerchant
|
|
42
42
|
|
43
43
|
def initialize(options = {})
|
44
44
|
requires!(options, :login, :password)
|
45
|
-
options[:refund_hash] = Digest::SHA1.hexdigest(options[:rebate_secret]) if options.
|
45
|
+
options[:refund_hash] = Digest::SHA1.hexdigest(options[:rebate_secret]) if options[:rebate_secret].present?
|
46
|
+
options[:credit_hash] = Digest::SHA1.hexdigest(options[:refund_secret]) if options[:refund_secret].present?
|
46
47
|
super
|
47
48
|
end
|
48
49
|
|
@@ -70,9 +71,9 @@ module ActiveMerchant
|
|
70
71
|
commit(request)
|
71
72
|
end
|
72
73
|
|
73
|
-
def credit(money,
|
74
|
-
|
75
|
-
|
74
|
+
def credit(money, creditcard, options = {})
|
75
|
+
request = build_credit_request(money, creditcard, options)
|
76
|
+
commit(request)
|
76
77
|
end
|
77
78
|
|
78
79
|
def void(authorization, options = {})
|
@@ -184,6 +185,22 @@ module ActiveMerchant
|
|
184
185
|
xml.target!
|
185
186
|
end
|
186
187
|
|
188
|
+
def build_credit_request(money, credit_card, options)
|
189
|
+
timestamp = new_timestamp
|
190
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
191
|
+
xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'credit' do
|
192
|
+
add_merchant_details(xml, options)
|
193
|
+
xml.tag! 'orderid', sanitize_order_id(options[:order_id])
|
194
|
+
add_amount(xml, money, options)
|
195
|
+
add_card(xml, credit_card)
|
196
|
+
xml.tag! 'refundhash', @options[:credit_hash] if @options[:credit_hash]
|
197
|
+
xml.tag! 'autosettle', 'flag' => 1
|
198
|
+
add_comments(xml, options)
|
199
|
+
add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), credit_card.number)
|
200
|
+
end
|
201
|
+
xml.target!
|
202
|
+
end
|
203
|
+
|
187
204
|
def build_void_request(authorization, options)
|
188
205
|
timestamp = new_timestamp
|
189
206
|
xml = Builder::XmlMarkup.new :indent => 2
|
@@ -289,12 +306,18 @@ module ActiveMerchant
|
|
289
306
|
end
|
290
307
|
|
291
308
|
def add_three_d_secure(xml, options)
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
xml.tag! '
|
309
|
+
return unless three_d_secure = options[:three_d_secure]
|
310
|
+
version = three_d_secure.fetch(:version, '')
|
311
|
+
xml.tag! 'mpi' do
|
312
|
+
if version =~ /^2/
|
313
|
+
xml.tag! 'authentication_value', three_d_secure[:cavv]
|
314
|
+
xml.tag! 'ds_trans_id', three_d_secure[:ds_transaction_id]
|
315
|
+
else
|
316
|
+
xml.tag! 'cavv', three_d_secure[:cavv]
|
317
|
+
xml.tag! 'xid', three_d_secure[:xid]
|
297
318
|
end
|
319
|
+
xml.tag! 'eci', three_d_secure[:eci]
|
320
|
+
xml.tag! 'message_version', version
|
298
321
|
end
|
299
322
|
end
|
300
323
|
|
@@ -193,28 +193,32 @@ module ActiveMerchant #:nodoc:
|
|
193
193
|
requires!(options, :order_id)
|
194
194
|
|
195
195
|
data = {}
|
196
|
-
add_action(data, :purchase)
|
196
|
+
add_action(data, :purchase, options)
|
197
197
|
add_amount(data, money, options)
|
198
198
|
add_order(data, options[:order_id])
|
199
199
|
add_payment(data, payment)
|
200
|
+
add_threeds(data, options) if options[:execute_threed]
|
200
201
|
data[:description] = options[:description]
|
201
202
|
data[:store_in_vault] = options[:store]
|
203
|
+
data[:sca_exemption] = options[:sca_exemption]
|
202
204
|
|
203
|
-
commit data
|
205
|
+
commit data, options
|
204
206
|
end
|
205
207
|
|
206
208
|
def authorize(money, payment, options = {})
|
207
209
|
requires!(options, :order_id)
|
208
210
|
|
209
211
|
data = {}
|
210
|
-
add_action(data, :authorize)
|
212
|
+
add_action(data, :authorize, options)
|
211
213
|
add_amount(data, money, options)
|
212
214
|
add_order(data, options[:order_id])
|
213
215
|
add_payment(data, payment)
|
216
|
+
add_threeds(data, options) if options[:execute_threed]
|
214
217
|
data[:description] = options[:description]
|
215
218
|
data[:store_in_vault] = options[:store]
|
219
|
+
data[:sca_exemption] = options[:sca_exemption]
|
216
220
|
|
217
|
-
commit data
|
221
|
+
commit data, options
|
218
222
|
end
|
219
223
|
|
220
224
|
def capture(money, authorization, options = {})
|
@@ -225,7 +229,7 @@ module ActiveMerchant #:nodoc:
|
|
225
229
|
add_order(data, order_id)
|
226
230
|
data[:description] = options[:description]
|
227
231
|
|
228
|
-
commit data
|
232
|
+
commit data, options
|
229
233
|
end
|
230
234
|
|
231
235
|
def void(authorization, options = {})
|
@@ -236,7 +240,7 @@ module ActiveMerchant #:nodoc:
|
|
236
240
|
add_order(data, order_id)
|
237
241
|
data[:description] = options[:description]
|
238
242
|
|
239
|
-
commit data
|
243
|
+
commit data, options
|
240
244
|
end
|
241
245
|
|
242
246
|
def refund(money, authorization, options = {})
|
@@ -247,7 +251,7 @@ module ActiveMerchant #:nodoc:
|
|
247
251
|
add_order(data, order_id)
|
248
252
|
data[:description] = options[:description]
|
249
253
|
|
250
|
-
commit data
|
254
|
+
commit data, options
|
251
255
|
end
|
252
256
|
|
253
257
|
def verify(creditcard, options = {})
|
@@ -278,8 +282,8 @@ module ActiveMerchant #:nodoc:
|
|
278
282
|
|
279
283
|
private
|
280
284
|
|
281
|
-
def add_action(data, action)
|
282
|
-
data[:action] = transaction_code(action)
|
285
|
+
def add_action(data, action, options = {})
|
286
|
+
data[:action] = options[:execute_threed].present? ? '0' : transaction_code(action)
|
283
287
|
end
|
284
288
|
|
285
289
|
def add_amount(data, money, options)
|
@@ -295,6 +299,10 @@ module ActiveMerchant #:nodoc:
|
|
295
299
|
test? ? test_url : live_url
|
296
300
|
end
|
297
301
|
|
302
|
+
def threeds_url
|
303
|
+
test? ? 'https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2': 'https://sis.redsys.es/sis/services/SerClsWSEntradaV2'
|
304
|
+
end
|
305
|
+
|
298
306
|
def add_payment(data, card)
|
299
307
|
if card.is_a?(String)
|
300
308
|
data[:credit_card_token] = card
|
@@ -311,21 +319,57 @@ module ActiveMerchant #:nodoc:
|
|
311
319
|
end
|
312
320
|
end
|
313
321
|
|
314
|
-
def
|
315
|
-
|
322
|
+
def add_threeds(data, options)
|
323
|
+
if options[:execute_threed] == true
|
324
|
+
data[:threeds] = {threeDSInfo: 'CardData'}
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def determine_3ds_action(threeds_hash)
|
329
|
+
return 'iniciaPeticion' if threeds_hash[:threeDSInfo] == 'CardData'
|
330
|
+
return 'trataPeticion' if threeds_hash[:threeDSInfo] == 'AuthenticationData' ||
|
331
|
+
threeds_hash[:threeDSInfo] == 'ChallengeResponse'
|
332
|
+
end
|
333
|
+
|
334
|
+
def commit(data, options = {})
|
335
|
+
if data[:threeds]
|
336
|
+
action = determine_3ds_action(data[:threeds])
|
337
|
+
request = <<-EOS
|
338
|
+
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://webservice.sis.sermepa.es" xmlns:intf="http://webservice.sis.sermepa.es" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
|
339
|
+
<soapenv:Header/>
|
340
|
+
<soapenv:Body>
|
341
|
+
<intf:#{action} xmlns:intf="http://webservice.sis.sermepa.es">
|
342
|
+
<intf:datoEntrada>
|
343
|
+
<![CDATA[#{xml_request_from(data, options)}]]>
|
344
|
+
</intf:datoEntrada>
|
345
|
+
</intf:#{action}>
|
346
|
+
</soapenv:Body>
|
347
|
+
</soapenv:Envelope>
|
348
|
+
EOS
|
349
|
+
parse(ssl_post(threeds_url, request, headers(action)), action)
|
350
|
+
else
|
351
|
+
parse(ssl_post(url, "entrada=#{CGI.escape(xml_request_from(data, options))}", headers), action)
|
352
|
+
end
|
316
353
|
end
|
317
354
|
|
318
|
-
def headers
|
319
|
-
|
320
|
-
|
321
|
-
|
355
|
+
def headers(action=nil)
|
356
|
+
if action
|
357
|
+
{
|
358
|
+
'Content-Type' => 'text/xml',
|
359
|
+
'SOAPAction' => action
|
360
|
+
}
|
361
|
+
else
|
362
|
+
{
|
363
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
364
|
+
}
|
365
|
+
end
|
322
366
|
end
|
323
367
|
|
324
|
-
def xml_request_from(data)
|
368
|
+
def xml_request_from(data, options = {})
|
325
369
|
if sha256_authentication?
|
326
|
-
build_sha256_xml_request(data)
|
370
|
+
build_sha256_xml_request(data, options)
|
327
371
|
else
|
328
|
-
build_sha1_xml_request(data)
|
372
|
+
build_sha1_xml_request(data, options)
|
329
373
|
end
|
330
374
|
end
|
331
375
|
|
@@ -351,30 +395,30 @@ module ActiveMerchant #:nodoc:
|
|
351
395
|
Digest::SHA1.hexdigest(str)
|
352
396
|
end
|
353
397
|
|
354
|
-
def build_sha256_xml_request(data)
|
398
|
+
def build_sha256_xml_request(data, options = {})
|
355
399
|
xml = Builder::XmlMarkup.new
|
356
400
|
xml.instruct!
|
357
401
|
xml.REQUEST do
|
358
|
-
build_merchant_data(xml, data)
|
402
|
+
build_merchant_data(xml, data, options)
|
359
403
|
xml.DS_SIGNATUREVERSION 'HMAC_SHA256_V1'
|
360
|
-
xml.DS_SIGNATURE sign_request(merchant_data_xml(data), data[:order_id])
|
404
|
+
xml.DS_SIGNATURE sign_request(merchant_data_xml(data, options), data[:order_id])
|
361
405
|
end
|
362
406
|
xml.target!
|
363
407
|
end
|
364
408
|
|
365
|
-
def build_sha1_xml_request(data)
|
409
|
+
def build_sha1_xml_request(data, options = {})
|
366
410
|
xml = Builder::XmlMarkup.new :indent => 2
|
367
|
-
build_merchant_data(xml, data)
|
411
|
+
build_merchant_data(xml, data, options)
|
368
412
|
xml.target!
|
369
413
|
end
|
370
414
|
|
371
|
-
def merchant_data_xml(data)
|
415
|
+
def merchant_data_xml(data, options = {})
|
372
416
|
xml = Builder::XmlMarkup.new
|
373
|
-
build_merchant_data(xml, data)
|
417
|
+
build_merchant_data(xml, data, options)
|
374
418
|
xml.target!
|
375
419
|
end
|
376
420
|
|
377
|
-
def build_merchant_data(xml, data)
|
421
|
+
def build_merchant_data(xml, data, options = {})
|
378
422
|
xml.DATOSENTRADA do
|
379
423
|
# Basic elements
|
380
424
|
xml.DS_Version 0.1
|
@@ -383,9 +427,10 @@ module ActiveMerchant #:nodoc:
|
|
383
427
|
xml.DS_MERCHANT_ORDER data[:order_id]
|
384
428
|
xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
|
385
429
|
xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
|
386
|
-
xml.DS_MERCHANT_TERMINAL @options[:terminal]
|
430
|
+
xml.DS_MERCHANT_TERMINAL options[:terminal] || @options[:terminal]
|
387
431
|
xml.DS_MERCHANT_MERCHANTCODE @options[:login]
|
388
432
|
xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) unless sha256_authentication?
|
433
|
+
xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
|
389
434
|
|
390
435
|
# Only when card is present
|
391
436
|
if data[:card]
|
@@ -398,22 +443,42 @@ module ActiveMerchant #:nodoc:
|
|
398
443
|
xml.DS_MERCHANT_IDENTIFIER data[:credit_card_token]
|
399
444
|
xml.DS_MERCHANT_DIRECTPAYMENT 'true'
|
400
445
|
end
|
446
|
+
|
447
|
+
# Set moto flag only if explicitly requested via moto field
|
448
|
+
# Requires account configuration to be able to use
|
449
|
+
if options.dig(:moto) && options.dig(:metadata, :manual_entry)
|
450
|
+
xml.DS_MERCHANT_DIRECTPAYMENT 'moto'
|
451
|
+
end
|
452
|
+
|
453
|
+
if data[:threeds]
|
454
|
+
xml.DS_MERCHANT_EMV3DS data[:threeds].to_json
|
455
|
+
end
|
401
456
|
end
|
402
457
|
end
|
403
458
|
|
404
|
-
def parse(data)
|
459
|
+
def parse(data, action)
|
405
460
|
params = {}
|
406
461
|
success = false
|
407
462
|
message = ''
|
408
463
|
options = @options.merge(:test => test?)
|
409
464
|
xml = Nokogiri::XML(data)
|
410
465
|
code = xml.xpath('//RETORNOXML/CODIGO').text
|
411
|
-
|
466
|
+
|
467
|
+
if ['iniciaPeticion', 'trataPeticion'].include?(action)
|
468
|
+
vxml = Nokogiri::XML(data).remove_namespaces!.xpath("//Envelope/Body/#{action}Response/#{action}Return").inner_text
|
469
|
+
xml = Nokogiri::XML(vxml)
|
470
|
+
node = (action == 'iniciaPeticion' ? 'INFOTARJETA' : 'OPERACION')
|
471
|
+
op = xml.xpath("//RETORNOXML/#{node}")
|
472
|
+
op.children.each do |element|
|
473
|
+
params[element.name.downcase.to_sym] = element.text
|
474
|
+
end
|
475
|
+
message = response_text_3ds(xml, params)
|
476
|
+
success = params.size > 0 && is_success_response?(params[:ds_response])
|
477
|
+
elsif code == '0'
|
412
478
|
op = xml.xpath('//RETORNOXML/OPERACION')
|
413
479
|
op.children.each do |element|
|
414
480
|
params[element.name.downcase.to_sym] = element.text
|
415
481
|
end
|
416
|
-
|
417
482
|
if validate_signature(params)
|
418
483
|
message = response_text(params[:ds_response])
|
419
484
|
options[:authorization] = build_authorization(params)
|
@@ -474,6 +539,20 @@ module ActiveMerchant #:nodoc:
|
|
474
539
|
RESPONSE_TEXTS[code] || 'Unkown code, please check in manual'
|
475
540
|
end
|
476
541
|
|
542
|
+
def response_text_3ds(xml, params)
|
543
|
+
code = xml.xpath('//RETORNOXML/CODIGO').text
|
544
|
+
message = ''
|
545
|
+
if code != '0'
|
546
|
+
message = "#{code} ERROR"
|
547
|
+
elsif params[:ds_emv3ds]
|
548
|
+
three_ds_data = JSON.parse(params[:ds_emv3ds])
|
549
|
+
message = three_ds_data['threeDSInfo']
|
550
|
+
elsif params[:ds_response]
|
551
|
+
message = response_text(params[:ds_response])
|
552
|
+
end
|
553
|
+
message
|
554
|
+
end
|
555
|
+
|
477
556
|
def is_success_response?(code)
|
478
557
|
(code.to_i < 100) || [400, 481, 500, 900].include?(code.to_i)
|
479
558
|
end
|
@@ -523,6 +602,10 @@ module ActiveMerchant #:nodoc:
|
|
523
602
|
xml_signed_fields += data[:ds_cardnumber]
|
524
603
|
end
|
525
604
|
|
605
|
+
if data[:ds_emv3ds]
|
606
|
+
xml_signed_fields += data[:ds_emv3ds]
|
607
|
+
end
|
608
|
+
|
526
609
|
xml_signed_fields + data[:ds_transactiontype] + data[:ds_securepayment]
|
527
610
|
end
|
528
611
|
|
@@ -35,19 +35,13 @@ module ActiveMerchant #:nodoc:
|
|
35
35
|
# Public: Run a purchase transaction.
|
36
36
|
#
|
37
37
|
# money - The monetary amount of the transaction in cents.
|
38
|
-
# payment_method - The CreditCard or the Spreedly payment method token.
|
38
|
+
# payment_method - The CreditCard or Check or the Spreedly payment method token.
|
39
39
|
# options - A hash of options:
|
40
40
|
# :store - Retain the payment method if the purchase
|
41
41
|
# succeeds. Defaults to false. (optional)
|
42
42
|
def purchase(money, payment_method, options = {})
|
43
|
-
|
44
|
-
|
45
|
-
else
|
46
|
-
MultiResponse.run do |r|
|
47
|
-
r.process { save_card(options[:store], payment_method, options) }
|
48
|
-
r.process { purchase_with_token(money, r.authorization, options) }
|
49
|
-
end
|
50
|
-
end
|
43
|
+
request = build_transaction_request(money, payment_method, options)
|
44
|
+
commit("gateways/#{options[:gateway_token] || @options[:gateway_token]}/purchase.xml", request)
|
51
45
|
end
|
52
46
|
|
53
47
|
# Public: Run an authorize transaction.
|
@@ -58,14 +52,8 @@ module ActiveMerchant #:nodoc:
|
|
58
52
|
# :store - Retain the payment method if the authorize
|
59
53
|
# succeeds. Defaults to false. (optional)
|
60
54
|
def authorize(money, payment_method, options = {})
|
61
|
-
|
62
|
-
|
63
|
-
else
|
64
|
-
MultiResponse.run do |r|
|
65
|
-
r.process { save_card(options[:store], payment_method, options) }
|
66
|
-
r.process { authorize_with_token(money, r.authorization, options) }
|
67
|
-
end
|
68
|
-
end
|
55
|
+
request = build_transaction_request(money, payment_method, options)
|
56
|
+
commit("gateways/#{@options[:gateway_token]}/authorize.xml", request)
|
69
57
|
end
|
70
58
|
|
71
59
|
def capture(money, authorization, options={})
|
@@ -79,6 +67,7 @@ module ActiveMerchant #:nodoc:
|
|
79
67
|
def refund(money, authorization, options={})
|
80
68
|
request = build_xml_request('transaction') do |doc|
|
81
69
|
add_invoice(doc, money, options)
|
70
|
+
add_extra_options(:gateway_specific_fields, doc, options)
|
82
71
|
end
|
83
72
|
|
84
73
|
commit("transactions/#{authorization}/credit.xml", request)
|
@@ -155,32 +144,25 @@ module ActiveMerchant #:nodoc:
|
|
155
144
|
end
|
156
145
|
|
157
146
|
def purchase_with_token(money, payment_method_token, options)
|
158
|
-
request =
|
147
|
+
request = build_transaction_request(money, payment_method_token, options)
|
159
148
|
commit("gateways/#{options[:gateway_token] || @options[:gateway_token]}/purchase.xml", request)
|
160
149
|
end
|
161
150
|
|
162
151
|
def authorize_with_token(money, payment_method_token, options)
|
163
|
-
request =
|
152
|
+
request = build_transaction_request(money, payment_method_token, options)
|
164
153
|
commit("gateways/#{@options[:gateway_token]}/authorize.xml", request)
|
165
154
|
end
|
166
155
|
|
167
156
|
def verify_with_token(payment_method_token, options)
|
168
|
-
request =
|
169
|
-
add_invoice(doc, nil, options)
|
170
|
-
doc.payment_method_token(payment_method_token)
|
171
|
-
doc.retain_on_success(true) if options[:store]
|
172
|
-
add_extra_options(:gateway_specific_fields, doc, options)
|
173
|
-
end
|
174
|
-
|
157
|
+
request = build_transaction_request(nil, payment_method_token, options)
|
175
158
|
commit("gateways/#{@options[:gateway_token]}/verify.xml", request)
|
176
159
|
end
|
177
160
|
|
178
|
-
def
|
161
|
+
def build_transaction_request(money, payment_method, options)
|
179
162
|
build_xml_request('transaction') do |doc|
|
180
163
|
add_invoice(doc, money, options)
|
164
|
+
add_payment_method(doc, payment_method, options)
|
181
165
|
add_extra_options(:gateway_specific_fields, doc, options)
|
182
|
-
doc.payment_method_token(payment_method_token)
|
183
|
-
doc.retain_on_success(true) if options[:store]
|
184
166
|
end
|
185
167
|
end
|
186
168
|
|
@@ -190,6 +172,27 @@ module ActiveMerchant #:nodoc:
|
|
190
172
|
doc.order_id(options[:order_id])
|
191
173
|
doc.ip(options[:ip]) if options[:ip]
|
192
174
|
doc.description(options[:description]) if options[:description]
|
175
|
+
|
176
|
+
if options[:merchant_name_descriptor]
|
177
|
+
doc.merchant_name_descriptor(options[:merchant_name_descriptor])
|
178
|
+
end
|
179
|
+
if options[:merchant_location_descriptor]
|
180
|
+
doc.merchant_location_descriptor(options[:merchant_location_descriptor])
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_payment_method(doc, payment_method, options)
|
185
|
+
doc.retain_on_success(true) if options[:store]
|
186
|
+
|
187
|
+
if payment_method.is_a?(String)
|
188
|
+
doc.payment_method_token(payment_method)
|
189
|
+
elsif payment_method.is_a?(CreditCard)
|
190
|
+
add_credit_card(doc, payment_method, options)
|
191
|
+
elsif payment_method.is_a?(Check)
|
192
|
+
add_bank_account(doc, payment_method, options)
|
193
|
+
else
|
194
|
+
raise TypeError, 'Payment method not supported'
|
195
|
+
end
|
193
196
|
end
|
194
197
|
|
195
198
|
def add_credit_card(doc, credit_card, options)
|
@@ -210,6 +213,17 @@ module ActiveMerchant #:nodoc:
|
|
210
213
|
end
|
211
214
|
end
|
212
215
|
|
216
|
+
def add_bank_account(doc, bank_account, options)
|
217
|
+
doc.bank_account do
|
218
|
+
doc.first_name(bank_account.first_name)
|
219
|
+
doc.last_name(bank_account.last_name)
|
220
|
+
doc.bank_routing_number(bank_account.routing_number)
|
221
|
+
doc.bank_account_number(bank_account.account_number)
|
222
|
+
doc.bank_account_type(bank_account.account_type)
|
223
|
+
doc.bank_account_holder_type(bank_account.account_holder_type)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
213
227
|
def add_extra_options(type, doc, options)
|
214
228
|
doc.send(type) do
|
215
229
|
extra_options_to_doc(doc, options[type])
|