activemerchant 1.123.0 → 1.126.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 +206 -0
- data/lib/active_merchant/billing/check.rb +5 -8
- data/lib/active_merchant/billing/credit_card.rb +10 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +18 -3
- data/lib/active_merchant/billing/gateway.rb +3 -2
- data/lib/active_merchant/billing/gateways/adyen.rb +66 -11
- data/lib/active_merchant/billing/gateways/airwallex.rb +341 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
- data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/blue_snap.rb +31 -21
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +87 -15
- data/lib/active_merchant/billing/gateways/card_connect.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
- data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +34 -5
- data/lib/active_merchant/billing/gateways/credorax.rb +10 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +24 -36
- data/lib/active_merchant/billing/gateways/d_local.rb +61 -6
- data/lib/active_merchant/billing/gateways/decidir.rb +17 -1
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +19 -3
- data/lib/active_merchant/billing/gateways/elavon.rb +6 -3
- data/lib/active_merchant/billing/gateways/element.rb +20 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +137 -32
- data/lib/active_merchant/billing/gateways/ipg.rb +415 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +7 -0
- data/lib/active_merchant/billing/gateways/litle.rb +93 -1
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -1
- data/lib/active_merchant/billing/gateways/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/moka.rb +24 -11
- data/lib/active_merchant/billing/gateways/moneris.rb +35 -8
- data/lib/active_merchant/billing/gateways/mundipagg.rb +8 -6
- data/lib/active_merchant/billing/gateways/nmi.rb +27 -8
- data/lib/active_merchant/billing/gateways/orbital.rb +357 -319
- data/lib/active_merchant/billing/gateways/pay_arc.rb +9 -7
- data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
- data/lib/active_merchant/billing/gateways/pay_trace.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +76 -6
- data/lib/active_merchant/billing/gateways/paymentez.rb +35 -9
- data/lib/active_merchant/billing/gateways/paysafe.rb +155 -34
- data/lib/active_merchant/billing/gateways/payu_latam.rb +31 -16
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
- data/lib/active_merchant/billing/gateways/pin.rb +31 -4
- data/lib/active_merchant/billing/gateways/priority.rb +369 -0
- data/lib/active_merchant/billing/gateways/rapyd.rb +258 -0
- data/lib/active_merchant/billing/gateways/realex.rb +18 -0
- data/lib/active_merchant/billing/gateways/safe_charge.rb +7 -6
- data/lib/active_merchant/billing/gateways/simetrik.rb +362 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +30 -8
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +175 -72
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +20 -6
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
- data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +196 -64
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/billing/response.rb +4 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +11 -2
@@ -286,16 +286,18 @@ module ActiveMerchant #:nodoc:
|
|
286
286
|
end
|
287
287
|
|
288
288
|
def add_address(post, options)
|
289
|
-
|
290
|
-
|
291
|
-
post['
|
292
|
-
post['
|
293
|
-
post['
|
294
|
-
post['
|
289
|
+
return unless billing_address = options[:billing_address]
|
290
|
+
|
291
|
+
post['address_line1'] = billing_address[:address1]
|
292
|
+
post['address_line2'] = billing_address[:address2]
|
293
|
+
post['city'] = billing_address[:city]
|
294
|
+
post['state'] = billing_address[:state]
|
295
|
+
post['zip'] = billing_address[:zip]
|
296
|
+
post['country'] = billing_address[:country]
|
295
297
|
end
|
296
298
|
|
297
299
|
def add_phone(post, options)
|
298
|
-
post['
|
300
|
+
post['phone_number'] = options[:billing_address][:phone] if options.dig(:billing_address, :phone)
|
299
301
|
end
|
300
302
|
|
301
303
|
def add_money(post, money, options)
|
@@ -79,7 +79,9 @@ module ActiveMerchant #:nodoc:
|
|
79
79
|
force_utf8(transcript).
|
80
80
|
gsub(%r((api_accesskey=)\w+), '\1[FILTERED]').
|
81
81
|
gsub(%r((card_number=)\w+), '\1[FILTERED]').
|
82
|
-
gsub(%r((card_verification=)\w+), '\1[FILTERED]')
|
82
|
+
gsub(%r((card_verification=)\w+), '\1[FILTERED]').
|
83
|
+
gsub(%r((bank_account_number=)\w+), '\1[FILTERED]').
|
84
|
+
gsub(%r((bank_routing_number=)\w+), '\1[FILTERED]')
|
83
85
|
end
|
84
86
|
|
85
87
|
private
|
@@ -118,7 +118,7 @@ module ActiveMerchant #:nodoc:
|
|
118
118
|
check_token_response(response, ENDPOINTS[:store], post, options)
|
119
119
|
end
|
120
120
|
|
121
|
-
def
|
121
|
+
def unstore(customer_id)
|
122
122
|
post = {}
|
123
123
|
post[:customer_id] = customer_id
|
124
124
|
response = commit(ENDPOINTS[:redact], post)
|
@@ -83,6 +83,7 @@ module ActiveMerchant #:nodoc:
|
|
83
83
|
options[:name] = credit_card.name if options[:name].blank? && credit_card
|
84
84
|
request = build_recurring_request(options[:profile_id] ? :modify : :add, money, options) do |xml|
|
85
85
|
add_credit_card(xml, credit_card, options) if credit_card
|
86
|
+
add_stored_credential(xml, options[:stored_credential])
|
86
87
|
end
|
87
88
|
commit(request, options.merge(request_type: :recurring))
|
88
89
|
end
|
@@ -158,6 +159,7 @@ module ActiveMerchant #:nodoc:
|
|
158
159
|
xml.tag! 'ExtData', 'Name' => 'ORIGID', 'Value' => reference
|
159
160
|
end
|
160
161
|
end
|
162
|
+
add_stored_credential(xml, options[:stored_credential])
|
161
163
|
end
|
162
164
|
xml.tag! 'ExtData', 'Name' => 'BUTTONSOURCE', 'Value' => application_id unless application_id.blank?
|
163
165
|
end
|
@@ -190,15 +192,43 @@ module ActiveMerchant #:nodoc:
|
|
190
192
|
xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
|
191
193
|
end
|
192
194
|
|
195
|
+
if %i(authorization purchase).include? action
|
196
|
+
add_mpi_3ds(xml, options[:three_d_secure]) if options[:three_d_secure]
|
197
|
+
end
|
198
|
+
|
193
199
|
xml.tag! 'Tender' do
|
194
200
|
add_credit_card(xml, credit_card, options)
|
195
201
|
end
|
202
|
+
add_stored_credential(xml, options[:stored_credential])
|
196
203
|
end
|
197
204
|
xml.tag! 'ExtData', 'Name' => 'BUTTONSOURCE', 'Value' => application_id unless application_id.blank?
|
198
205
|
end
|
199
206
|
add_level_two_three_fields(xml.target!, options)
|
200
207
|
end
|
201
208
|
|
209
|
+
def add_mpi_3ds(xml, three_d_secure_options)
|
210
|
+
# structure as per https://developer.paypal.com/api/nvp-soap/payflow/3d-secure-mpi/
|
211
|
+
authentication_id = three_d_secure_options[:authentication_id]
|
212
|
+
authentication_status = three_d_secure_options[:authentication_response_status]
|
213
|
+
|
214
|
+
eci = three_d_secure_options[:eci]
|
215
|
+
cavv = three_d_secure_options[:cavv]
|
216
|
+
xid = three_d_secure_options[:xid]
|
217
|
+
version = three_d_secure_options[:version]
|
218
|
+
|
219
|
+
# 3DS2 only
|
220
|
+
ds_transaction_id = three_d_secure_options[:ds_transaction_id] if version_2_or_newer?(three_d_secure_options)
|
221
|
+
|
222
|
+
xml.tag!('ExtData', 'Name' => 'AUTHENTICATION_ID', 'Value' => authentication_id) unless authentication_id.blank?
|
223
|
+
xml.tag!('ExtData', 'Name' => 'AUTHENTICATION_STATUS', 'Value' => authentication_status) unless authentication_status.blank?
|
224
|
+
|
225
|
+
xml.tag!('ExtData', 'Name' => 'CAVV', 'Value' => cavv) unless cavv.blank?
|
226
|
+
xml.tag!('ExtData', 'Name' => 'ECI', 'Value' => eci) unless eci.blank?
|
227
|
+
xml.tag!('ExtData', 'Name' => 'XID', 'Value' => xid) unless xid.blank?
|
228
|
+
xml.tag!('ExtData', 'Name' => 'THREEDSVERSION', 'Value' => version) unless version.blank?
|
229
|
+
xml.tag!('ExtData', 'Name' => 'DSTRANSACTIONID', 'Value' => ds_transaction_id) unless ds_transaction_id.blank?
|
230
|
+
end
|
231
|
+
|
202
232
|
def add_level_two_three_fields(xml_string, options)
|
203
233
|
if options[:level_two_fields] || options[:level_three_fields]
|
204
234
|
xml_doc = Nokogiri::XML.parse(xml_string)
|
@@ -258,6 +288,7 @@ module ActiveMerchant #:nodoc:
|
|
258
288
|
xml.tag! 'ABA', check.routing_number
|
259
289
|
end
|
260
290
|
end
|
291
|
+
add_stored_credential(xml, options[:stored_credential])
|
261
292
|
end
|
262
293
|
xml.tag! 'ExtData', 'Name' => 'BUTTONSOURCE', 'Value' => application_id unless application_id.blank?
|
263
294
|
end
|
@@ -278,6 +309,37 @@ module ActiveMerchant #:nodoc:
|
|
278
309
|
end
|
279
310
|
end
|
280
311
|
|
312
|
+
def add_stored_credential(xml, stored_credential)
|
313
|
+
return unless stored_credential
|
314
|
+
|
315
|
+
xml.tag! 'CardOnFile', add_card_on_file_type(stored_credential)
|
316
|
+
xml.tag! 'TxnId', stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
317
|
+
end
|
318
|
+
|
319
|
+
def card_on_file_initiator(initator)
|
320
|
+
case initator
|
321
|
+
when 'merchant'
|
322
|
+
'MIT'
|
323
|
+
when 'cardholder'
|
324
|
+
'CIT'
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def card_on_file_reason(stored_credential)
|
329
|
+
return 'I' if stored_credential[:initial_transaction] && stored_credential[:reason_type] == 'unscheduled'
|
330
|
+
|
331
|
+
case stored_credential[:reason_type]
|
332
|
+
when 'recurring', 'installment'
|
333
|
+
'R'
|
334
|
+
when 'unscheduled'
|
335
|
+
'U'
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def add_card_on_file_type(stored_credential)
|
340
|
+
card_on_file_initiator(stored_credential[:initiator]).to_s + card_on_file_reason(stored_credential).to_s
|
341
|
+
end
|
342
|
+
|
281
343
|
def add_three_d_secure(options, xml)
|
282
344
|
if options[:three_d_secure]
|
283
345
|
three_d_secure = options[:three_d_secure]
|
@@ -289,20 +351,28 @@ module ActiveMerchant #:nodoc:
|
|
289
351
|
xml.tag! 'ECI', three_d_secure[:eci] unless three_d_secure[:eci].blank?
|
290
352
|
xml.tag! 'CAVV', three_d_secure[:cavv] unless three_d_secure[:cavv].blank?
|
291
353
|
xml.tag! 'XID', three_d_secure[:xid] unless three_d_secure[:xid].blank?
|
292
|
-
xml.tag! '
|
293
|
-
xml.tag! '
|
354
|
+
xml.tag! 'ThreeDSVersion', three_d_secure[:version] unless three_d_secure[:version].blank?
|
355
|
+
xml.tag! 'DSTransactionID', three_d_secure[:ds_transaction_id] unless three_d_secure[:ds_transaction_id].blank?
|
294
356
|
end
|
295
357
|
end
|
296
358
|
end
|
297
359
|
|
298
360
|
def authentication_status(three_d_secure, xml)
|
299
|
-
if three_d_secure[:authentication_response_status].present?
|
300
|
-
|
301
|
-
|
302
|
-
|
361
|
+
status = if three_d_secure[:authentication_response_status].present?
|
362
|
+
three_d_secure[:authentication_response_status]
|
363
|
+
elsif three_d_secure[:directory_response_status].present?
|
364
|
+
three_d_secure[:directory_response_status]
|
365
|
+
end
|
366
|
+
if status.present?
|
367
|
+
xml.tag! 'Status', status
|
368
|
+
xml.tag! 'AuthenticationStatus', status if version_2_or_newer?(three_d_secure)
|
303
369
|
end
|
304
370
|
end
|
305
371
|
|
372
|
+
def version_2_or_newer?(three_d_secure)
|
373
|
+
three_d_secure[:version]&.start_with?('2')
|
374
|
+
end
|
375
|
+
|
306
376
|
def credit_card_type(credit_card)
|
307
377
|
return '' if card_brand(credit_card).blank?
|
308
378
|
|
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
|
|
9
9
|
|
10
10
|
self.supported_countries = %w[MX EC CO BR CL PE]
|
11
11
|
self.default_currency = 'USD'
|
12
|
-
self.supported_cardtypes = %i[visa master american_express diners_club elo alia olimpica]
|
12
|
+
self.supported_cardtypes = %i[visa master american_express diners_club elo alia olimpica discover maestro sodexo carnet unionpay jcb]
|
13
13
|
|
14
14
|
self.homepage_url = 'https://secure.paymentez.com/'
|
15
15
|
self.display_name = 'Paymentez'
|
@@ -34,12 +34,21 @@ module ActiveMerchant #:nodoc:
|
|
34
34
|
28 => :card_declined
|
35
35
|
}.freeze
|
36
36
|
|
37
|
+
SUCCESS_STATUS = ['success', 'pending', 1, 0]
|
38
|
+
|
37
39
|
CARD_MAPPING = {
|
38
40
|
'visa' => 'vi',
|
39
41
|
'master' => 'mc',
|
40
42
|
'american_express' => 'ax',
|
41
43
|
'diners_club' => 'di',
|
42
|
-
'elo' => 'el'
|
44
|
+
'elo' => 'el',
|
45
|
+
'discover' => 'dc',
|
46
|
+
'maestro' => 'ms',
|
47
|
+
'sodexo' => 'sx',
|
48
|
+
'olimpica' => 'ol',
|
49
|
+
'carnet' => 'ct',
|
50
|
+
'unionpay' => 'up',
|
51
|
+
'jcb' => 'jc'
|
43
52
|
}.freeze
|
44
53
|
|
45
54
|
def initialize(options = {})
|
@@ -60,6 +69,8 @@ module ActiveMerchant #:nodoc:
|
|
60
69
|
end
|
61
70
|
|
62
71
|
def authorize(money, payment, options = {})
|
72
|
+
return purchase(money, payment, options) if options[:otp_flow]
|
73
|
+
|
63
74
|
post = {}
|
64
75
|
|
65
76
|
add_invoice(post, money, options)
|
@@ -70,13 +81,21 @@ module ActiveMerchant #:nodoc:
|
|
70
81
|
commit_transaction('authorize', post)
|
71
82
|
end
|
72
83
|
|
73
|
-
def capture(money, authorization,
|
84
|
+
def capture(money, authorization, options = {})
|
74
85
|
post = {
|
75
86
|
transaction: { id: authorization }
|
76
87
|
}
|
77
|
-
|
88
|
+
verify_flow = options[:type] && options[:value]
|
89
|
+
|
90
|
+
if verify_flow
|
91
|
+
add_customer_data(post, options)
|
92
|
+
add_verify_value(post, options)
|
93
|
+
elsif money
|
94
|
+
post[:order] = { amount: amount(money).to_f }
|
95
|
+
end
|
78
96
|
|
79
|
-
|
97
|
+
action = verify_flow ? 'verify' : 'capture'
|
98
|
+
commit_transaction(action, post)
|
80
99
|
end
|
81
100
|
|
82
101
|
def refund(money, authorization, options = {})
|
@@ -132,10 +151,10 @@ module ActiveMerchant #:nodoc:
|
|
132
151
|
private
|
133
152
|
|
134
153
|
def add_customer_data(post, options)
|
135
|
-
requires!(options, :user_id
|
154
|
+
requires!(options, :user_id)
|
136
155
|
post[:user] ||= {}
|
137
156
|
post[:user][:id] = options[:user_id]
|
138
|
-
post[:user][:email] = options[:email]
|
157
|
+
post[:user][:email] = options[:email] if options[:email]
|
139
158
|
post[:user][:ip_address] = options[:ip] if options[:ip]
|
140
159
|
post[:user][:fiscal_number] = options[:fiscal_number] if options[:fiscal_number]
|
141
160
|
if phone = options[:phone] || options.dig(:billing_address, :phone)
|
@@ -172,6 +191,11 @@ module ActiveMerchant #:nodoc:
|
|
172
191
|
end
|
173
192
|
end
|
174
193
|
|
194
|
+
def add_verify_value(post, options)
|
195
|
+
post[:type] = options[:type] if options[:type]
|
196
|
+
post[:value] = options[:value] if options[:value]
|
197
|
+
end
|
198
|
+
|
175
199
|
def add_extra_params(post, options)
|
176
200
|
extra_params = {}
|
177
201
|
extra_params.merge!(options[:extra_params]) if options[:extra_params]
|
@@ -255,7 +279,9 @@ module ActiveMerchant #:nodoc:
|
|
255
279
|
end
|
256
280
|
|
257
281
|
def success_from(response)
|
258
|
-
|
282
|
+
return false if response.include?('error')
|
283
|
+
|
284
|
+
SUCCESS_STATUS.include?(response['status'] || response['transaction']['status'])
|
259
285
|
end
|
260
286
|
|
261
287
|
def card_success_from(response)
|
@@ -271,7 +297,7 @@ module ActiveMerchant #:nodoc:
|
|
271
297
|
if !success_from(response) && response['error']
|
272
298
|
response['error'] && response['error']['type']
|
273
299
|
else
|
274
|
-
response['transaction'] && response['transaction']['message']
|
300
|
+
(response['transaction'] && response['transaction']['message']) || (response['message'])
|
275
301
|
end
|
276
302
|
end
|
277
303
|
|
@@ -4,8 +4,7 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
self.test_url = 'https://api.test.paysafe.com'
|
5
5
|
self.live_url = 'https://api.paysafe.com'
|
6
6
|
|
7
|
-
self.supported_countries = %w(FR)
|
8
|
-
self.default_currency = 'EUR'
|
7
|
+
self.supported_countries = %w(AL AT BE BA BG CA HR CY CZ DK EE FI FR DE GR HU IS IE IT LV LI LT LU MT ME NL MK NO PL PT RO RS SK SI ES SE CH TR GB US)
|
9
8
|
self.supported_cardtypes = %i[visa master american_express discover]
|
10
9
|
|
11
10
|
self.homepage_url = 'https://www.paysafe.com/'
|
@@ -22,8 +21,11 @@ module ActiveMerchant #:nodoc:
|
|
22
21
|
add_payment(post, payment)
|
23
22
|
add_billing_address(post, options)
|
24
23
|
add_merchant_details(post, options)
|
24
|
+
add_airline_travel_details(post, options)
|
25
25
|
add_customer_data(post, payment, options) unless payment.is_a?(String)
|
26
26
|
add_three_d_secure(post, payment, options) if options[:three_d_secure]
|
27
|
+
add_stored_credential(post, options) if options[:stored_credential]
|
28
|
+
add_split_pay_details(post, options)
|
27
29
|
post[:settleWithAuth] = true
|
28
30
|
|
29
31
|
commit(:post, 'auths', post, options)
|
@@ -37,6 +39,7 @@ module ActiveMerchant #:nodoc:
|
|
37
39
|
add_merchant_details(post, options)
|
38
40
|
add_customer_data(post, payment, options) unless payment.is_a?(String)
|
39
41
|
add_three_d_secure(post, payment, options) if options[:three_d_secure]
|
42
|
+
add_stored_credential(post, options) if options[:stored_credential]
|
40
43
|
|
41
44
|
commit(:post, 'auths', post, options)
|
42
45
|
end
|
@@ -91,8 +94,8 @@ module ActiveMerchant #:nodoc:
|
|
91
94
|
commit(:post, 'profiles', post, options)
|
92
95
|
end
|
93
96
|
|
94
|
-
def
|
95
|
-
|
97
|
+
def unstore(pm_profile_id)
|
98
|
+
commit(:delete, "profiles/#{get_id_from_store_auth(pm_profile_id)}", nil, nil)
|
96
99
|
end
|
97
100
|
|
98
101
|
def supports_scrubbing?
|
@@ -119,9 +122,8 @@ module ActiveMerchant #:nodoc:
|
|
119
122
|
end
|
120
123
|
|
121
124
|
def add_billing_address(post, options)
|
122
|
-
return unless options[:billing_address] || options[:address]
|
125
|
+
return unless address = options[:billing_address] || options[:address]
|
123
126
|
|
124
|
-
address = options[:billing_address] || options[:address]
|
125
127
|
post[:billingDetails] = {}
|
126
128
|
post[:billingDetails][:street] = address[:address1]
|
127
129
|
post[:billingDetails][:city] = address[:city]
|
@@ -134,21 +136,19 @@ module ActiveMerchant #:nodoc:
|
|
134
136
|
# The add_address_for_vaulting method is applicable to the store method, as the APIs address
|
135
137
|
# object is formatted differently from the standard transaction billing address
|
136
138
|
def add_address_for_vaulting(post, options)
|
137
|
-
return unless options[:billing_address || options[:address]
|
139
|
+
return unless address = options[:billing_address] || options[:address]
|
138
140
|
|
139
|
-
|
140
|
-
post[:billingAddress] =
|
141
|
-
post[:billingAddress][:
|
142
|
-
post[:billingAddress][:city] = address[:city]
|
143
|
-
post[:billingAddress][:zip] = address[:zip]
|
144
|
-
post[:billingAddress][:country] = address[:country]
|
145
|
-
post[:billingAddress][:state] = address[:state] if address[:state]
|
141
|
+
post[:card][:billingAddress] = {}
|
142
|
+
post[:card][:billingAddress][:street] = address[:address1]
|
143
|
+
post[:card][:billingAddress][:street2] = address[:address2]
|
144
|
+
post[:card][:billingAddress][:city] = address[:city]
|
145
|
+
post[:card][:billingAddress][:zip] = address[:zip]
|
146
|
+
post[:card][:billingAddress][:country] = address[:country]
|
147
|
+
post[:card][:billingAddress][:state] = address[:state] if address[:state]
|
146
148
|
end
|
147
149
|
|
148
150
|
# This data is specific to creating a profile at the gateway's vault level
|
149
151
|
def add_profile_data(post, payment, options)
|
150
|
-
address = options[:billing_address] || options[:address]
|
151
|
-
|
152
152
|
post[:firstName] = payment.first_name
|
153
153
|
post[:lastName] = payment.last_name
|
154
154
|
post[:dateOfBirth] = {}
|
@@ -156,8 +156,13 @@ module ActiveMerchant #:nodoc:
|
|
156
156
|
post[:dateOfBirth][:month] = options[:date_of_birth][:month]
|
157
157
|
post[:dateOfBirth][:day] = options[:date_of_birth][:day]
|
158
158
|
post[:email] = options[:email] if options[:email]
|
159
|
-
post[:phone] = (address[:phone] || options[:phone]) if address[:phone] || options[:phone]
|
160
159
|
post[:ip] = options[:ip] if options[:ip]
|
160
|
+
|
161
|
+
if options[:phone]
|
162
|
+
post[:phone] = options[:phone]
|
163
|
+
elsif address = options[:billing_address] || options[:address]
|
164
|
+
post[:phone] = address[:phone] if address[:phone]
|
165
|
+
end
|
161
166
|
end
|
162
167
|
|
163
168
|
def add_store_data(post, payment, options)
|
@@ -174,7 +179,7 @@ module ActiveMerchant #:nodoc:
|
|
174
179
|
def add_payment(post, payment)
|
175
180
|
if payment.is_a?(String)
|
176
181
|
post[:card] = {}
|
177
|
-
post[:card][:paymentToken] = payment
|
182
|
+
post[:card][:paymentToken] = get_pm_from_store_auth(payment)
|
178
183
|
else
|
179
184
|
post[:card] = { cardExpiry: {} }
|
180
185
|
post[:card][:cardNum] = payment.number
|
@@ -200,10 +205,124 @@ module ActiveMerchant #:nodoc:
|
|
200
205
|
post[:authentication][:cavv] = three_d_secure[:cavv]
|
201
206
|
post[:authentication][:xid] = three_d_secure[:xid] if three_d_secure[:xid]
|
202
207
|
post[:authentication][:threeDSecureVersion] = three_d_secure[:version]
|
203
|
-
post[:authentication][:directoryServerTransactionId] = three_d_secure[:ds_transaction_id] unless payment.is_a?(String) || payment
|
208
|
+
post[:authentication][:directoryServerTransactionId] = three_d_secure[:ds_transaction_id] unless payment.is_a?(String) || !mastercard?(payment)
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_airline_travel_details(post, options)
|
212
|
+
return unless options[:airline_travel_details]
|
213
|
+
|
214
|
+
post[:airlineTravelDetails] = {}
|
215
|
+
post[:airlineTravelDetails][:passengerName] = options[:airline_travel_details][:passenger_name] if options[:airline_travel_details][:passenger_name]
|
216
|
+
post[:airlineTravelDetails][:departureDate] = options[:airline_travel_details][:departure_date] if options[:airline_travel_details][:departure_date]
|
217
|
+
post[:airlineTravelDetails][:origin] = options[:airline_travel_details][:origin] if options[:airline_travel_details][:origin]
|
218
|
+
post[:airlineTravelDetails][:computerizedReservationSystem] = options[:airline_travel_details][:computerized_reservation_system] if options[:airline_travel_details][:computerized_reservation_system]
|
219
|
+
post[:airlineTravelDetails][:customerReferenceNumber] = options[:airline_travel_details][:customer_reference_number] if options[:airline_travel_details][:customer_reference_number]
|
220
|
+
|
221
|
+
add_ticket_details(post, options)
|
222
|
+
add_travel_agency_details(post, options)
|
223
|
+
add_trip_legs(post, options)
|
224
|
+
end
|
225
|
+
|
226
|
+
def add_ticket_details(post, options)
|
227
|
+
return unless ticket = options[:airline_travel_details][:ticket]
|
228
|
+
|
229
|
+
post[:airlineTravelDetails][:ticket] = {}
|
230
|
+
post[:airlineTravelDetails][:ticket][:ticketNumber] = ticket[:ticket_number] if ticket[:ticket_number]
|
231
|
+
post[:airlineTravelDetails][:ticket][:isRestrictedTicket] = ticket[:is_restricted_ticket] if ticket[:is_restricted_ticket]
|
232
|
+
end
|
233
|
+
|
234
|
+
def add_travel_agency_details(post, options)
|
235
|
+
return unless agency = options[:airline_travel_details][:travel_agency]
|
236
|
+
|
237
|
+
post[:airlineTravelDetails][:travelAgency] = {}
|
238
|
+
post[:airlineTravelDetails][:travelAgency][:name] = agency[:name] if agency[:name]
|
239
|
+
post[:airlineTravelDetails][:travelAgency][:code] = agency[:code] if agency[:code]
|
240
|
+
end
|
241
|
+
|
242
|
+
def add_trip_legs(post, options)
|
243
|
+
return unless trip_legs = options[:airline_travel_details][:trip_legs]
|
244
|
+
|
245
|
+
trip_legs_hash = {}
|
246
|
+
trip_legs.each.with_index(1) do |leg, i|
|
247
|
+
my_leg = "leg#{i}".to_sym
|
248
|
+
details = add_leg_details(my_leg, leg[1])
|
249
|
+
|
250
|
+
trip_legs_hash[my_leg] = details
|
251
|
+
end
|
252
|
+
post[:airlineTravelDetails][:tripLegs] = trip_legs_hash
|
253
|
+
end
|
254
|
+
|
255
|
+
def add_leg_details(obj, leg)
|
256
|
+
details = {}
|
257
|
+
add_flight_details(details, obj, leg)
|
258
|
+
details[:serviceClass] = leg[:service_class] if leg[:service_class]
|
259
|
+
details[:isStopOverAllowed] = leg[:is_stop_over_allowed] if leg[:is_stop_over_allowed]
|
260
|
+
details[:destination] = leg[:destination] if leg[:destination]
|
261
|
+
details[:fareBasis] = leg[:fare_basis] if leg[:fare_basis]
|
262
|
+
details[:departureDate] = leg[:departure_date] if leg[:departure_date]
|
263
|
+
|
264
|
+
details
|
265
|
+
end
|
266
|
+
|
267
|
+
def add_flight_details(details, obj, leg)
|
268
|
+
details[:flight] = {}
|
269
|
+
details[:flight][:carrierCode] = leg[:flight][:carrier_code] if leg[:flight][:carrier_code]
|
270
|
+
details[:flight][:flightNumber] = leg[:flight][:flight_number] if leg[:flight][:flight_number]
|
271
|
+
end
|
272
|
+
|
273
|
+
def add_split_pay_details(post, options)
|
274
|
+
return unless options[:split_pay]
|
275
|
+
|
276
|
+
split_pay = []
|
277
|
+
options[:split_pay].each do |pmnt|
|
278
|
+
split = {}
|
279
|
+
|
280
|
+
split[:linkedAccount] = pmnt[:linked_account]
|
281
|
+
split[:amount] = pmnt[:amount].to_i if pmnt[:amount]
|
282
|
+
split[:percent] = pmnt[:percent].to_i if pmnt[:percent]
|
283
|
+
|
284
|
+
split_pay << split
|
285
|
+
end
|
286
|
+
post[:splitpay] = split_pay
|
287
|
+
end
|
288
|
+
|
289
|
+
def add_stored_credential(post, options)
|
290
|
+
return unless options[:stored_credential]
|
291
|
+
|
292
|
+
post[:storedCredential] = {}
|
293
|
+
|
294
|
+
case options[:stored_credential][:initial_transaction]
|
295
|
+
when true
|
296
|
+
post[:storedCredential][:occurrence] = 'INITIAL'
|
297
|
+
when false
|
298
|
+
post[:storedCredential][:occurrence] = 'SUBSEQUENT'
|
299
|
+
end
|
300
|
+
|
301
|
+
case options[:stored_credential][:reason_type]
|
302
|
+
when 'recurring', 'installment'
|
303
|
+
post[:storedCredential][:type] = 'RECURRING'
|
304
|
+
when 'unscheduled'
|
305
|
+
if options[:stored_credential][:initiator] == 'merchant'
|
306
|
+
post[:storedCredential][:type] = 'TOPUP'
|
307
|
+
elsif options[:stored_credential][:initiator] == 'cardholder'
|
308
|
+
post[:storedCredential][:type] = 'ADHOC'
|
309
|
+
else
|
310
|
+
return
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
post[:storedCredential][:initialTransactionId] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
|
315
|
+
end
|
316
|
+
|
317
|
+
def mastercard?(payment)
|
318
|
+
return false unless payment.respond_to?(:brand)
|
319
|
+
|
320
|
+
payment.brand == 'master'
|
204
321
|
end
|
205
322
|
|
206
323
|
def parse(body)
|
324
|
+
return {} if body.empty?
|
325
|
+
|
207
326
|
JSON.parse(body)
|
208
327
|
end
|
209
328
|
|
@@ -217,7 +336,7 @@ module ActiveMerchant #:nodoc:
|
|
217
336
|
success,
|
218
337
|
message_from(success, response),
|
219
338
|
response,
|
220
|
-
authorization: authorization_from(response),
|
339
|
+
authorization: authorization_from(action, response),
|
221
340
|
avs_result: AVSResult.new(code: response['avsResponse']),
|
222
341
|
cvv_result: CVVResult.new(response['cvvVerification']),
|
223
342
|
test: test?,
|
@@ -225,21 +344,10 @@ module ActiveMerchant #:nodoc:
|
|
225
344
|
)
|
226
345
|
end
|
227
346
|
|
228
|
-
def commit_for_redact(method, action, parameters, options)
|
229
|
-
url = url(action)
|
230
|
-
response = raw_ssl_request(method, url, post_data(parameters, options), headers)
|
231
|
-
success = true if response.code == '200'
|
232
|
-
|
233
|
-
Response.new(
|
234
|
-
success,
|
235
|
-
message: response.message
|
236
|
-
)
|
237
|
-
end
|
238
|
-
|
239
347
|
def headers
|
240
348
|
{
|
241
349
|
'Content-Type' => 'application/json',
|
242
|
-
'Authorization' =>
|
350
|
+
'Authorization' => 'Basic ' + Base64.strict_encode64("#{@options[:username]}:#{@options[:password]}")
|
243
351
|
}
|
244
352
|
end
|
245
353
|
|
@@ -265,8 +373,21 @@ module ActiveMerchant #:nodoc:
|
|
265
373
|
"Error(s)- code:#{response['error']['code']}, message:#{response['error']['message']}"
|
266
374
|
end
|
267
375
|
|
268
|
-
def authorization_from(response)
|
269
|
-
|
376
|
+
def authorization_from(action, response)
|
377
|
+
if action == 'profiles'
|
378
|
+
pm = response['cards'].first['paymentToken']
|
379
|
+
"#{pm}|#{response['id']}"
|
380
|
+
else
|
381
|
+
response['id']
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def get_pm_from_store_auth(authorization)
|
386
|
+
authorization.split('|')[0]
|
387
|
+
end
|
388
|
+
|
389
|
+
def get_id_from_store_auth(authorization)
|
390
|
+
authorization.split('|')[1]
|
270
391
|
end
|
271
392
|
|
272
393
|
def post_data(parameters = {}, options = {})
|
@@ -17,6 +17,7 @@ module ActiveMerchant #:nodoc:
|
|
17
17
|
BRAND_MAP = {
|
18
18
|
'visa' => 'VISA',
|
19
19
|
'master' => 'MASTERCARD',
|
20
|
+
'maestro' => 'MASTERCARD',
|
20
21
|
'american_express' => 'AMEX',
|
21
22
|
'diners_club' => 'DINERS',
|
22
23
|
'naranja' => 'NARANJA',
|
@@ -278,6 +279,10 @@ module ActiveMerchant #:nodoc:
|
|
278
279
|
Digest::MD5.hexdigest(signature_string)
|
279
280
|
end
|
280
281
|
|
282
|
+
def codensa_bin?(number)
|
283
|
+
number.start_with?('590712')
|
284
|
+
end
|
285
|
+
|
281
286
|
def add_payment_method(post, payment_method, options)
|
282
287
|
if payment_method.is_a?(String)
|
283
288
|
brand, token = split_authorization(payment_method)
|
@@ -295,7 +300,7 @@ module ActiveMerchant #:nodoc:
|
|
295
300
|
credit_card[:name] = payment_method.name.strip
|
296
301
|
credit_card[:processWithoutCvv2] = true if add_process_without_cvv2(payment_method, options)
|
297
302
|
post[:transaction][:creditCard] = credit_card
|
298
|
-
post[:transaction][:paymentMethod] = BRAND_MAP[payment_method.brand.to_s]
|
303
|
+
post[:transaction][:paymentMethod] = codensa_bin?(payment_method.number) ? 'CODENSA' : BRAND_MAP[payment_method.brand.to_s]
|
299
304
|
end
|
300
305
|
end
|
301
306
|
|
@@ -387,26 +392,36 @@ module ActiveMerchant #:nodoc:
|
|
387
392
|
def message_from(action, success, response)
|
388
393
|
case action
|
389
394
|
when 'store'
|
390
|
-
|
391
|
-
|
392
|
-
error_description = response['creditCardToken']['errorDescription'] if response['creditCardToken']
|
393
|
-
response['error'] || error_description || 'FAILED'
|
395
|
+
message_from_store(success, response)
|
394
396
|
when 'verify_credentials'
|
395
|
-
|
396
|
-
|
397
|
-
'FAILED'
|
397
|
+
message_from_verify_credentials(success)
|
398
398
|
else
|
399
|
-
|
400
|
-
|
399
|
+
message_from_transaction_response(success, response)
|
400
|
+
end
|
401
|
+
end
|
401
402
|
|
402
|
-
|
403
|
+
def message_from_store(success, response)
|
404
|
+
return response['code'] if success
|
403
405
|
|
404
|
-
|
405
|
-
|
406
|
-
|
406
|
+
error_description = response['creditCardToken']['errorDescription'] if response['creditCardToken']
|
407
|
+
response['error'] || error_description || 'FAILED'
|
408
|
+
end
|
407
409
|
|
408
|
-
|
409
|
-
|
410
|
+
def message_from_verify_credentials(success)
|
411
|
+
return 'VERIFIED' if success
|
412
|
+
|
413
|
+
'FAILED'
|
414
|
+
end
|
415
|
+
|
416
|
+
def message_from_transaction_response(success, response)
|
417
|
+
response_code = response.dig('transactionResponse', 'responseCode') || response.dig('transactionResponse', 'pendingReason')
|
418
|
+
return response_code if success
|
419
|
+
return response_code + ' | ' + response.dig('transactionResponse', 'paymentNetworkResponseErrorMessage') if response.dig('transactionResponse', 'paymentNetworkResponseErrorMessage')
|
420
|
+
return response.dig('transactionResponse', 'responseMessage') if response.dig('transactionResponse', 'responseMessage')
|
421
|
+
return response['error'] if response['error']
|
422
|
+
return response_code if response_code
|
423
|
+
|
424
|
+
'FAILED'
|
410
425
|
end
|
411
426
|
|
412
427
|
def authorization_from(action, response)
|