activemerchant 1.93.0 → 1.98.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 +111 -0
- 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 +67 -4
- data/lib/active_merchant/billing/gateway.rb +10 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +106 -22
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
- data/lib/active_merchant/billing/gateways/beanstream.rb +2 -0
- 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 +3 -1
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +98 -61
- data/lib/active_merchant/billing/gateways/credorax.rb +29 -3
- data/lib/active_merchant/billing/gateways/cyber_source.rb +30 -13
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +233 -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 +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/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 +3 -2
- 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 +40 -2
- 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/spreedly_core.rb +43 -29
- data/lib/active_merchant/billing/gateways/stripe.rb +54 -9
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +267 -0
- 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 +171 -39
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +19 -4
@@ -544,7 +544,7 @@ module ActiveMerchant #:nodoc:
|
|
544
544
|
end
|
545
545
|
end
|
546
546
|
doc['v1'].addrLn1 billing_address[:address1] if billing_address[:address1]
|
547
|
-
doc['v1'].addrLn2 billing_address[:address2]
|
547
|
+
doc['v1'].addrLn2 billing_address[:address2] unless billing_address[:address2].blank?
|
548
548
|
doc['v1'].city billing_address[:city] if billing_address[:city]
|
549
549
|
doc['v1'].state billing_address[:state] if billing_address[:state]
|
550
550
|
doc['v1'].zipCode billing_address[:zip] if billing_address[:zip]
|
@@ -559,7 +559,7 @@ module ActiveMerchant #:nodoc:
|
|
559
559
|
doc['v1'].ship do
|
560
560
|
doc['v1'].fullName fullname unless fullname.blank?
|
561
561
|
doc['v1'].addrLn1 shipping_address[:address1] if shipping_address[:address1]
|
562
|
-
doc['v1'].addrLn2 shipping_address[:address2]
|
562
|
+
doc['v1'].addrLn2 shipping_address[:address2] unless shipping_address[:address2].blank?
|
563
563
|
doc['v1'].city shipping_address[:city] if shipping_address[:city]
|
564
564
|
doc['v1'].state shipping_address[:state] if shipping_address[:state]
|
565
565
|
doc['v1'].zipCode shipping_address[:zip] if shipping_address[:zip]
|
@@ -104,6 +104,8 @@ module ActiveMerchant #:nodoc:
|
|
104
104
|
TEST_LOGIN = 'TestMerchant'
|
105
105
|
TEST_PASSWORD = 'password'
|
106
106
|
|
107
|
+
VOIDABLE_ACTIONS = %w(preauth sale postauth credit)
|
108
|
+
|
107
109
|
self.money_format = :cents
|
108
110
|
self.supported_cardtypes = [:visa, :master, :discover, :american_express, :diners_club, :jcb]
|
109
111
|
self.supported_countries = ['US']
|
@@ -157,6 +159,8 @@ module ActiveMerchant #:nodoc:
|
|
157
159
|
add_customer_data(parameters, options)
|
158
160
|
add_payment_source(parameters, creditcard_or_billing_id)
|
159
161
|
add_addresses(parameters, options)
|
162
|
+
add_custom_fields(parameters, options)
|
163
|
+
|
160
164
|
commit('preauth', parameters)
|
161
165
|
end
|
162
166
|
|
@@ -172,6 +176,8 @@ module ActiveMerchant #:nodoc:
|
|
172
176
|
add_customer_data(parameters, options)
|
173
177
|
add_payment_source(parameters, creditcard_or_billing_id)
|
174
178
|
add_addresses(parameters, options)
|
179
|
+
add_custom_fields(parameters, options)
|
180
|
+
|
175
181
|
commit('sale', parameters)
|
176
182
|
end
|
177
183
|
|
@@ -179,11 +185,13 @@ module ActiveMerchant #:nodoc:
|
|
179
185
|
# postauth, we preserve active_merchant's nomenclature of capture() for consistency with the rest of the library. To process
|
180
186
|
# a postauthorization with TC, you need an amount in cents or a money object, and a TC transid.
|
181
187
|
def capture(money, authorization, options = {})
|
188
|
+
transaction_id, _ = split_authorization(authorization)
|
182
189
|
parameters = {
|
183
190
|
:amount => amount(money),
|
184
|
-
:transid =>
|
191
|
+
:transid => transaction_id,
|
185
192
|
}
|
186
193
|
add_aggregator(parameters, options)
|
194
|
+
add_custom_fields(parameters, options)
|
187
195
|
|
188
196
|
commit('postauth', parameters)
|
189
197
|
end
|
@@ -191,11 +199,15 @@ module ActiveMerchant #:nodoc:
|
|
191
199
|
# refund() allows you to return money to a card that was previously billed. You need to supply the amount, in cents or a money object,
|
192
200
|
# that you want to refund, and a TC transid for the transaction that you are refunding.
|
193
201
|
def refund(money, identification, options = {})
|
202
|
+
transaction_id, _ = split_authorization(identification)
|
203
|
+
|
194
204
|
parameters = {
|
195
205
|
:amount => amount(money),
|
196
|
-
:transid =>
|
206
|
+
:transid => transaction_id
|
197
207
|
}
|
208
|
+
|
198
209
|
add_aggregator(parameters, options)
|
210
|
+
add_custom_fields(parameters, options)
|
199
211
|
|
200
212
|
commit('credit', parameters)
|
201
213
|
end
|
@@ -214,18 +226,26 @@ module ActiveMerchant #:nodoc:
|
|
214
226
|
# TrustCommerce to allow for reversal transactions before you can use this
|
215
227
|
# method.
|
216
228
|
#
|
229
|
+
# void() is also used to to cancel a capture (postauth), purchase (sale),
|
230
|
+
# or refund (credit) or a before it is sent for settlement.
|
231
|
+
#
|
217
232
|
# NOTE: AMEX preauth's cannot be reversed. If you want to clear it more
|
218
233
|
# quickly than the automatic expiration (7-10 days), you will have to
|
219
234
|
# capture it and then immediately issue a credit for the same amount
|
220
235
|
# which should clear the customers credit card with 48 hours according to
|
221
236
|
# TC.
|
222
237
|
def void(authorization, options = {})
|
238
|
+
transaction_id, original_action = split_authorization(authorization)
|
239
|
+
action = (VOIDABLE_ACTIONS - ['preauth']).include?(original_action) ? 'void' : 'reversal'
|
240
|
+
|
223
241
|
parameters = {
|
224
|
-
:transid =>
|
242
|
+
:transid => transaction_id,
|
225
243
|
}
|
244
|
+
|
226
245
|
add_aggregator(parameters, options)
|
246
|
+
add_custom_fields(parameters, options)
|
227
247
|
|
228
|
-
commit(
|
248
|
+
commit(action, parameters)
|
229
249
|
end
|
230
250
|
|
231
251
|
# recurring() a TrustCommerce account that is activated for Citadel, TrustCommerce's
|
@@ -284,6 +304,8 @@ module ActiveMerchant #:nodoc:
|
|
284
304
|
|
285
305
|
add_creditcard(parameters, creditcard)
|
286
306
|
add_addresses(parameters, options)
|
307
|
+
add_custom_fields(parameters, options)
|
308
|
+
|
287
309
|
commit('store', parameters)
|
288
310
|
end
|
289
311
|
|
@@ -294,6 +316,8 @@ module ActiveMerchant #:nodoc:
|
|
294
316
|
:billingid => identification,
|
295
317
|
}
|
296
318
|
|
319
|
+
add_custom_fields(parameters, options)
|
320
|
+
|
297
321
|
commit('unstore', parameters)
|
298
322
|
end
|
299
323
|
|
@@ -311,6 +335,12 @@ module ActiveMerchant #:nodoc:
|
|
311
335
|
|
312
336
|
private
|
313
337
|
|
338
|
+
def add_custom_fields(params, options)
|
339
|
+
options[:custom_fields]&.each do |key, value|
|
340
|
+
params[key.to_sym] = value
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
314
344
|
def add_aggregator(params, options)
|
315
345
|
if @options[:aggregator_id] || application_id != Gateway.application_id
|
316
346
|
params[:aggregators] = 1
|
@@ -409,14 +439,14 @@ module ActiveMerchant #:nodoc:
|
|
409
439
|
TCLink.send(parameters)
|
410
440
|
else
|
411
441
|
parse(ssl_post(self.live_url, post_data(parameters)))
|
412
|
-
|
442
|
+
end
|
413
443
|
|
414
444
|
# to be considered successful, transaction status must be either "approved" or "accepted"
|
415
445
|
success = SUCCESS_TYPES.include?(data['status'])
|
416
446
|
message = message_from(data)
|
417
447
|
Response.new(success, message, data,
|
418
448
|
:test => test?,
|
419
|
-
:authorization => data
|
449
|
+
:authorization => authorization_from(action, data),
|
420
450
|
:cvv_result => data['cvv'],
|
421
451
|
:avs_result => { :code => data['avs'] }
|
422
452
|
)
|
@@ -446,6 +476,15 @@ module ActiveMerchant #:nodoc:
|
|
446
476
|
end
|
447
477
|
end
|
448
478
|
|
479
|
+
def authorization_from(action, data)
|
480
|
+
authorization = data['transid']
|
481
|
+
authorization = "#{authorization}|#{action}" if authorization && VOIDABLE_ACTIONS.include?(action)
|
482
|
+
authorization
|
483
|
+
end
|
484
|
+
|
485
|
+
def split_authorization(authorization)
|
486
|
+
authorization&.split('|')
|
487
|
+
end
|
449
488
|
end
|
450
489
|
end
|
451
490
|
end
|
@@ -33,9 +33,9 @@ module ActiveMerchant #:nodoc:
|
|
33
33
|
'10110' => STANDARD_ERROR_CODE[:incorrect_address],
|
34
34
|
'10111' => STANDARD_ERROR_CODE[:incorrect_address],
|
35
35
|
'10127' => STANDARD_ERROR_CODE[:card_declined],
|
36
|
-
'
|
37
|
-
'
|
38
|
-
'
|
36
|
+
'00043' => STANDARD_ERROR_CODE[:call_issuer],
|
37
|
+
'10205' => STANDARD_ERROR_CODE[:card_declined],
|
38
|
+
'10204' => STANDARD_ERROR_CODE[:pickup_card]
|
39
39
|
}
|
40
40
|
|
41
41
|
def initialize(options = {})
|
@@ -318,12 +318,15 @@ module ActiveMerchant #:nodoc:
|
|
318
318
|
def commit(action, parameters)
|
319
319
|
url = (test? ? self.test_url : self.live_url)
|
320
320
|
response = parse(ssl_post(url, post_data(action, parameters)))
|
321
|
-
|
321
|
+
approved = response[:status] == 'Approved'
|
322
|
+
error_code = nil
|
323
|
+
error_code = (STANDARD_ERROR_CODE_MAPPING[response[:error_code]] || STANDARD_ERROR_CODE[:processing_error]) unless approved
|
324
|
+
Response.new(approved, message_from(response), response,
|
322
325
|
:test => test?,
|
323
326
|
:authorization => response[:ref_num],
|
324
327
|
:cvv_result => response[:cvv2_result_code],
|
325
328
|
:avs_result => { :code => response[:avs_result_code] },
|
326
|
-
:error_code =>
|
329
|
+
:error_code => error_code
|
327
330
|
)
|
328
331
|
end
|
329
332
|
|
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
|
|
7
7
|
self.default_currency = 'GBP'
|
8
8
|
self.money_format = :cents
|
9
9
|
self.supported_countries = %w(HK GB AU AD AR BE BR CA CH CN CO CR CY CZ DE DK ES FI FR GI GR HU IE IN IT JP LI LU MC MT MY MX NL NO NZ PA PE PL PT SE SG SI SM TR UM VA)
|
10
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :elo]
|
10
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :elo, :naranja, :cabal]
|
11
11
|
self.currencies_without_fractions = %w(HUF IDR ISK JPY KRW)
|
12
12
|
self.currencies_with_three_decimal_places = %w(BHD KWD OMR RSD TND)
|
13
13
|
self.homepage_url = 'http://www.worldpay.com/'
|
@@ -21,7 +21,10 @@ module ActiveMerchant #:nodoc:
|
|
21
21
|
'jcb' => 'JCB-SSL',
|
22
22
|
'maestro' => 'MAESTRO-SSL',
|
23
23
|
'diners_club' => 'DINERS-SSL',
|
24
|
-
'elo' => 'ELO-SSL'
|
24
|
+
'elo' => 'ELO-SSL',
|
25
|
+
'naranja' => 'NARANJA-SSL',
|
26
|
+
'cabal' => 'CABAL-SSL',
|
27
|
+
'unknown' => 'CARD-SSL'
|
25
28
|
}
|
26
29
|
|
27
30
|
AVS_CODE_MAP = {
|
@@ -58,10 +61,12 @@ module ActiveMerchant #:nodoc:
|
|
58
61
|
|
59
62
|
def authorize(money, payment_method, options = {})
|
60
63
|
requires!(options, :order_id)
|
61
|
-
|
64
|
+
payment_details = payment_details_from(payment_method)
|
65
|
+
authorize_request(money, payment_method, payment_details.merge(options))
|
62
66
|
end
|
63
67
|
|
64
68
|
def capture(money, authorization, options = {})
|
69
|
+
authorization = order_id_from_authorization(authorization.to_s)
|
65
70
|
MultiResponse.run do |r|
|
66
71
|
r.process { inquire_request(authorization, options, 'AUTHORISED') } unless options[:authorization_validated]
|
67
72
|
if r.params
|
@@ -73,6 +78,7 @@ module ActiveMerchant #:nodoc:
|
|
73
78
|
end
|
74
79
|
|
75
80
|
def void(authorization, options = {})
|
81
|
+
authorization = order_id_from_authorization(authorization.to_s)
|
76
82
|
MultiResponse.run do |r|
|
77
83
|
r.process { inquire_request(authorization, options, 'AUTHORISED') } unless options[:authorization_validated]
|
78
84
|
r.process { cancel_request(authorization, options) }
|
@@ -80,6 +86,7 @@ module ActiveMerchant #:nodoc:
|
|
80
86
|
end
|
81
87
|
|
82
88
|
def refund(money, authorization, options = {})
|
89
|
+
authorization = order_id_from_authorization(authorization.to_s)
|
83
90
|
response = MultiResponse.run do |r|
|
84
91
|
r.process { inquire_request(authorization, options, 'CAPTURED', 'SETTLED', 'SETTLED_BY_MERCHANT') }
|
85
92
|
r.process { refund_request(money, authorization, options) }
|
@@ -96,16 +103,22 @@ module ActiveMerchant #:nodoc:
|
|
96
103
|
# and other transactions should be performed on a normal eCom-flagged
|
97
104
|
# merchant ID.
|
98
105
|
def credit(money, payment_method, options = {})
|
99
|
-
|
106
|
+
payment_details = payment_details_from(payment_method)
|
107
|
+
credit_request(money, payment_method, payment_details.merge(:credit => true, **options))
|
100
108
|
end
|
101
109
|
|
102
|
-
def verify(
|
110
|
+
def verify(payment_method, options={})
|
103
111
|
MultiResponse.run(:use_first_response) do |r|
|
104
|
-
r.process { authorize(100,
|
112
|
+
r.process { authorize(100, payment_method, options) }
|
105
113
|
r.process(:ignore_result) { void(r.authorization, options.merge(:authorization_validated => true)) }
|
106
114
|
end
|
107
115
|
end
|
108
116
|
|
117
|
+
def store(credit_card, options={})
|
118
|
+
requires!(options, :customer)
|
119
|
+
store_request(credit_card, options)
|
120
|
+
end
|
121
|
+
|
109
122
|
def supports_scrubbing
|
110
123
|
true
|
111
124
|
end
|
@@ -143,6 +156,10 @@ module ActiveMerchant #:nodoc:
|
|
143
156
|
commit('credit', build_authorization_request(money, payment_method, options), :ok, 'SENT_FOR_REFUND', options)
|
144
157
|
end
|
145
158
|
|
159
|
+
def store_request(credit_card, options)
|
160
|
+
commit('store', build_store_request(credit_card, options), options)
|
161
|
+
end
|
162
|
+
|
146
163
|
def build_request
|
147
164
|
xml = Builder::XmlMarkup.new :indent => 2
|
148
165
|
xml.instruct! :xml, :encoding => 'UTF-8'
|
@@ -183,13 +200,14 @@ module ActiveMerchant #:nodoc:
|
|
183
200
|
end
|
184
201
|
end
|
185
202
|
add_payment_method(xml, money, payment_method, options)
|
186
|
-
|
203
|
+
add_shopper(xml, options)
|
187
204
|
if options[:hcg_additional_data]
|
188
205
|
add_hcg_additional_data(xml, options)
|
189
206
|
end
|
190
207
|
if options[:instalments]
|
191
208
|
add_instalments_data(xml, options)
|
192
209
|
end
|
210
|
+
add_moto_flag(xml, options) if options.dig(:metadata, :manual_entry)
|
193
211
|
end
|
194
212
|
end
|
195
213
|
end
|
@@ -223,6 +241,22 @@ module ActiveMerchant #:nodoc:
|
|
223
241
|
end
|
224
242
|
end
|
225
243
|
|
244
|
+
def build_store_request(credit_card, options)
|
245
|
+
build_request do |xml|
|
246
|
+
xml.tag! 'submit' do
|
247
|
+
xml.tag! 'paymentTokenCreate' do
|
248
|
+
add_authenticated_shopper_id(xml, options)
|
249
|
+
xml.tag! 'createToken'
|
250
|
+
xml.tag! 'paymentInstrument' do
|
251
|
+
xml.tag! 'cardDetails' do
|
252
|
+
add_card(xml, credit_card, options)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
226
260
|
def add_amount(xml, money, options)
|
227
261
|
currency = options[:currency] || currency(money)
|
228
262
|
|
@@ -240,7 +274,7 @@ module ActiveMerchant #:nodoc:
|
|
240
274
|
end
|
241
275
|
|
242
276
|
def add_payment_method(xml, amount, payment_method, options)
|
243
|
-
if
|
277
|
+
if options[:payment_type] == :pay_as_order
|
244
278
|
if options[:merchant_code]
|
245
279
|
xml.tag! 'payAsOrder', 'orderCode' => payment_method, 'merchantCode' => options[:merchant_code] do
|
246
280
|
add_amount(xml, amount, options)
|
@@ -252,16 +286,14 @@ module ActiveMerchant #:nodoc:
|
|
252
286
|
end
|
253
287
|
else
|
254
288
|
xml.tag! 'paymentDetails', credit_fund_transfer_attribute(options) do
|
255
|
-
|
256
|
-
xml.tag! '
|
257
|
-
|
258
|
-
|
289
|
+
if options[:payment_type] == :token
|
290
|
+
xml.tag! 'TOKEN-SSL', 'tokenScope' => options[:token_scope] do
|
291
|
+
xml.tag! 'paymentTokenID', options[:token_id]
|
292
|
+
end
|
293
|
+
else
|
294
|
+
xml.tag! card_code_for(payment_method) do
|
295
|
+
add_card(xml, payment_method, options)
|
259
296
|
end
|
260
|
-
|
261
|
-
xml.tag! 'cardHolderName', options[:execute_threed] ? '3D' : payment_method.name
|
262
|
-
xml.tag! 'cvc', payment_method.verification_value
|
263
|
-
|
264
|
-
add_address(xml, (options[:billing_address] || options[:address]))
|
265
297
|
end
|
266
298
|
add_stored_credential_options(xml, options)
|
267
299
|
if options[:ip] && options[:session_id]
|
@@ -272,18 +304,37 @@ module ActiveMerchant #:nodoc:
|
|
272
304
|
end
|
273
305
|
|
274
306
|
if three_d_secure = options[:three_d_secure]
|
275
|
-
xml
|
276
|
-
xml.tag! 'threeDSVersion', three_d_secure[:version]
|
277
|
-
xid_tag = three_d_secure[:version] =~ /^2/ ? 'dsTransactionId' : 'xid'
|
278
|
-
xml.tag! xid_tag, three_d_secure[:xid]
|
279
|
-
xml.tag! 'cavv', three_d_secure[:cavv]
|
280
|
-
xml.tag! 'eci', three_d_secure[:eci]
|
281
|
-
end
|
307
|
+
add_three_d_secure(three_d_secure, xml)
|
282
308
|
end
|
283
309
|
end
|
284
310
|
end
|
285
311
|
end
|
286
312
|
|
313
|
+
def add_three_d_secure(three_d_secure, xml)
|
314
|
+
xml.tag! 'info3DSecure' do
|
315
|
+
xml.tag! 'threeDSVersion', three_d_secure[:version]
|
316
|
+
if three_d_secure[:version] =~ /^2/
|
317
|
+
xml.tag! 'dsTransactionId', three_d_secure[:ds_transaction_id]
|
318
|
+
else
|
319
|
+
xml.tag! 'xid', three_d_secure[:xid]
|
320
|
+
end
|
321
|
+
xml.tag! 'cavv', three_d_secure[:cavv]
|
322
|
+
xml.tag! 'eci', three_d_secure[:eci]
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def add_card(xml, payment_method, options)
|
327
|
+
xml.tag! 'cardNumber', payment_method.number
|
328
|
+
xml.tag! 'expiryDate' do
|
329
|
+
xml.tag! 'date', 'month' => format(payment_method.month, :two_digits), 'year' => format(payment_method.year, :four_digits)
|
330
|
+
end
|
331
|
+
|
332
|
+
xml.tag! 'cardHolderName', options[:execute_threed] ? '3D' : payment_method.name
|
333
|
+
xml.tag! 'cvc', payment_method.verification_value
|
334
|
+
|
335
|
+
add_address(xml, (options[:billing_address] || options[:address]))
|
336
|
+
end
|
337
|
+
|
287
338
|
def add_stored_credential_options(xml, options={})
|
288
339
|
if options[:stored_credential]
|
289
340
|
add_stored_credential_using_normalized_fields(xml, options)
|
@@ -320,10 +371,11 @@ module ActiveMerchant #:nodoc:
|
|
320
371
|
end
|
321
372
|
end
|
322
373
|
|
323
|
-
def
|
324
|
-
return unless options[:execute_threed] || options[:email]
|
374
|
+
def add_shopper(xml, options)
|
375
|
+
return unless options[:execute_threed] || options[:email] || options[:customer]
|
325
376
|
xml.tag! 'shopper' do
|
326
377
|
xml.tag! 'shopperEmailAddress', options[:email] if options[:email]
|
378
|
+
add_authenticated_shopper_id(xml, options)
|
327
379
|
xml.tag! 'browser' do
|
328
380
|
xml.tag! 'acceptHeader', options[:accept_header]
|
329
381
|
xml.tag! 'userAgentHeader', options[:user_agent]
|
@@ -331,6 +383,10 @@ module ActiveMerchant #:nodoc:
|
|
331
383
|
end
|
332
384
|
end
|
333
385
|
|
386
|
+
def add_authenticated_shopper_id(xml, options)
|
387
|
+
xml.tag!('authenticatedShopperID', options[:customer]) if options[:customer]
|
388
|
+
end
|
389
|
+
|
334
390
|
def add_address(xml, address)
|
335
391
|
return unless address
|
336
392
|
|
@@ -368,6 +424,10 @@ module ActiveMerchant #:nodoc:
|
|
368
424
|
end
|
369
425
|
end
|
370
426
|
|
427
|
+
def add_moto_flag(xml, options)
|
428
|
+
xml.tag! 'dynamicInteractionType', 'type' => 'MOTO'
|
429
|
+
end
|
430
|
+
|
371
431
|
def address_with_defaults(address)
|
372
432
|
address ||= {}
|
373
433
|
address.delete_if { |_, v| v.blank? }
|
@@ -389,14 +449,17 @@ module ActiveMerchant #:nodoc:
|
|
389
449
|
end
|
390
450
|
|
391
451
|
def parse_element(raw, node)
|
452
|
+
node_name = node.name.underscore
|
392
453
|
node.attributes.each do |k, v|
|
393
|
-
raw["#{
|
454
|
+
raw["#{node_name}_#{k.underscore}".to_sym] = v
|
394
455
|
end
|
395
456
|
if node.has_elements?
|
396
|
-
raw[
|
457
|
+
raw[node_name.to_sym] = true unless node.name.blank?
|
397
458
|
node.elements.each { |e| parse_element(raw, e) }
|
459
|
+
elsif node.children.count > 1
|
460
|
+
raw[node_name.to_sym] = node.children.join(' ').strip
|
398
461
|
else
|
399
|
-
raw[
|
462
|
+
raw[node_name.to_sym] = node.text unless node.text.nil?
|
400
463
|
end
|
401
464
|
raw
|
402
465
|
end
|
@@ -419,13 +482,14 @@ module ActiveMerchant #:nodoc:
|
|
419
482
|
raw[:cookie] = @cookie
|
420
483
|
raw[:session_id] = options[:session_id]
|
421
484
|
end
|
422
|
-
success
|
485
|
+
success = success_from(action, raw, success_criteria)
|
486
|
+
message = message_from(success, raw, success_criteria)
|
423
487
|
|
424
488
|
Response.new(
|
425
489
|
success,
|
426
490
|
message,
|
427
491
|
raw,
|
428
|
-
:authorization => authorization_from(raw),
|
492
|
+
:authorization => authorization_from(action, raw, options),
|
429
493
|
:error_code => error_code_from(success, raw),
|
430
494
|
:test => test?,
|
431
495
|
:avs_result => AVSResult.new(code: AVS_CODE_MAP[raw[:avs_result_code_description]]),
|
@@ -455,19 +519,30 @@ module ActiveMerchant #:nodoc:
|
|
455
519
|
end
|
456
520
|
end
|
457
521
|
|
522
|
+
def success_from(action, raw, success_criteria)
|
523
|
+
success_criteria_success?(raw, success_criteria) || action_success?(action, raw)
|
524
|
+
end
|
525
|
+
|
526
|
+
def message_from(success, raw, success_criteria)
|
527
|
+
return 'SUCCESS' if success
|
528
|
+
raw[:iso8583_return_code_description] || raw[:error] || required_status_message(raw, success_criteria)
|
529
|
+
end
|
530
|
+
|
458
531
|
# success_criteria can be:
|
459
532
|
# - a string or an array of strings (if one of many responses)
|
460
533
|
# - An array of strings if one of many responses could be considered a
|
461
534
|
# success.
|
462
|
-
def
|
463
|
-
|
464
|
-
|
465
|
-
|
535
|
+
def success_criteria_success?(raw, success_criteria)
|
536
|
+
success_criteria.include?(raw[:last_event]) || raw[:ok].present?
|
537
|
+
end
|
538
|
+
|
539
|
+
def action_success?(action, raw)
|
540
|
+
case action
|
541
|
+
when 'store'
|
542
|
+
raw[:token].present?
|
466
543
|
else
|
467
|
-
|
544
|
+
false
|
468
545
|
end
|
469
|
-
|
470
|
-
[ success, message ]
|
471
546
|
end
|
472
547
|
|
473
548
|
def error_code_from(success, raw)
|
@@ -482,11 +557,64 @@ module ActiveMerchant #:nodoc:
|
|
482
557
|
end
|
483
558
|
end
|
484
559
|
|
485
|
-
def authorization_from(raw)
|
560
|
+
def authorization_from(action, raw, options)
|
561
|
+
order_id = order_id_from(raw)
|
562
|
+
|
563
|
+
case action
|
564
|
+
when 'store'
|
565
|
+
authorization_from_token_details(
|
566
|
+
order_id: order_id,
|
567
|
+
token_id: raw[:payment_token_id],
|
568
|
+
token_scope: 'shopper',
|
569
|
+
customer: options[:customer]
|
570
|
+
)
|
571
|
+
else
|
572
|
+
order_id
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
def order_id_from(raw)
|
486
577
|
pair = raw.detect { |k, v| k.to_s =~ /_order_code$/ }
|
487
578
|
(pair ? pair.last : nil)
|
488
579
|
end
|
489
580
|
|
581
|
+
def authorization_from_token_details(options={})
|
582
|
+
[options[:order_id], options[:token_id], options[:token_scope], options[:customer]].join('|')
|
583
|
+
end
|
584
|
+
|
585
|
+
def order_id_from_authorization(authorization)
|
586
|
+
token_details_from_authorization(authorization)[:order_id]
|
587
|
+
end
|
588
|
+
|
589
|
+
def token_details_from_authorization(authorization)
|
590
|
+
order_id, token_id, token_scope, customer = authorization.split('|')
|
591
|
+
|
592
|
+
token_details = {}
|
593
|
+
token_details[:order_id] = order_id if order_id.present?
|
594
|
+
token_details[:token_id] = token_id if token_id.present?
|
595
|
+
token_details[:token_scope] = token_scope if token_scope.present?
|
596
|
+
token_details[:customer] = customer if customer.present?
|
597
|
+
|
598
|
+
token_details
|
599
|
+
end
|
600
|
+
|
601
|
+
def payment_details_from(payment_method)
|
602
|
+
payment_details = {}
|
603
|
+
if payment_method.respond_to?(:number)
|
604
|
+
payment_details[:payment_type] = :credit
|
605
|
+
else
|
606
|
+
token_details = token_details_from_authorization(payment_method)
|
607
|
+
payment_details.merge!(token_details)
|
608
|
+
if token_details.has_key?(:token_id)
|
609
|
+
payment_details[:payment_type] = :token
|
610
|
+
else
|
611
|
+
payment_details[:payment_type] = :pay_as_order
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
payment_details
|
616
|
+
end
|
617
|
+
|
490
618
|
def credit_fund_transfer_attribute(options)
|
491
619
|
return unless options[:credit]
|
492
620
|
{'action' => 'REFUND'}
|
@@ -502,6 +630,10 @@ module ActiveMerchant #:nodoc:
|
|
502
630
|
return 3 if three_decimal_currency?(currency)
|
503
631
|
return 2
|
504
632
|
end
|
633
|
+
|
634
|
+
def card_code_for(payment_method)
|
635
|
+
CARD_CODES[card_brand(payment_method)] || CARD_CODES['unknown']
|
636
|
+
end
|
505
637
|
end
|
506
638
|
end
|
507
639
|
end
|