activemerchant 1.94.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 +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])
|