activemerchant 1.121.0 → 1.125.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 +217 -0
- data/README.md +1 -1
- data/lib/active_merchant/billing/check.rb +13 -19
- data/lib/active_merchant/billing/credit_card.rb +13 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +24 -12
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/adyen.rb +75 -27
- data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -3
- 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 +33 -4
- data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +41 -6
- data/lib/active_merchant/billing/gateways/d_local.rb +12 -6
- data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +65 -30
- data/lib/active_merchant/billing/gateways/element.rb +22 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +130 -26
- data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +30 -0
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +6 -3
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
- data/lib/active_merchant/billing/gateways/mit.rb +260 -0
- data/lib/active_merchant/billing/gateways/moka.rb +290 -0
- data/lib/active_merchant/billing/gateways/monei.rb +228 -144
- data/lib/active_merchant/billing/gateways/mundipagg.rb +22 -11
- data/lib/active_merchant/billing/gateways/nmi.rb +29 -10
- data/lib/active_merchant/billing/gateways/orbital.rb +46 -8
- data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
- data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
- data/lib/active_merchant/billing/gateways/paymentez.rb +14 -2
- data/lib/active_merchant/billing/gateways/paysafe.rb +412 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +9 -4
- 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 +347 -0
- data/lib/active_merchant/billing/gateways/realex.rb +18 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
- data/lib/active_merchant/billing/gateways/safe_charge.rb +8 -2
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +115 -39
- 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 +21 -7
- data/lib/active_merchant/billing/gateways/vpos.rb +49 -6
- data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +226 -62
- 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/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +13 -3
@@ -23,9 +23,9 @@ module ActiveMerchant #:nodoc:
|
|
23
23
|
'unchecked' => 'P'
|
24
24
|
}
|
25
25
|
|
26
|
-
DEFAULT_API_VERSION = '
|
26
|
+
DEFAULT_API_VERSION = '2020-08-27'
|
27
27
|
|
28
|
-
self.supported_countries = %w(AT AU BE BG BR CA CH CY CZ DE DK EE ES FI FR GB GR HK IE IT JP LT LU LV MT MX NL NO NZ PL PT RO SE SG SI SK US)
|
28
|
+
self.supported_countries = %w(AE AT AU BE BG BR CA CH CY CZ DE DK EE ES FI FR GB GR HK HU IE IN IT JP LT LU LV MT MX MY NL NO NZ PL PT RO SE SG SI SK US)
|
29
29
|
self.default_currency = 'USD'
|
30
30
|
self.money_format = :cents
|
31
31
|
self.supported_cardtypes = %i[visa master american_express discover jcb diners_club maestro unionpay]
|
@@ -223,9 +223,10 @@ module ActiveMerchant #:nodoc:
|
|
223
223
|
|
224
224
|
post[:default_card] = r.params['id'] if options[:set_default] && r.success? && !r.params['id'].blank?
|
225
225
|
|
226
|
-
r.process { update_customer(options[:customer], post) } if post.count > 0
|
226
|
+
r.process { update_customer(options[:customer], post.merge(expand: [:sources])) } if post.count > 0
|
227
227
|
end
|
228
228
|
else
|
229
|
+
post[:expand] = [:sources]
|
229
230
|
commit(:post, 'customers', post.merge(params), options)
|
230
231
|
end
|
231
232
|
end
|
@@ -286,13 +287,25 @@ module ActiveMerchant #:nodoc:
|
|
286
287
|
gsub(%r(((\[card\]|card)\[encrypted_pin\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
287
288
|
gsub(%r(((\[card\]|card)\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\3').
|
288
289
|
gsub(%r(((\[card\]|card)\[number\]=)\d+), '\1[FILTERED]').
|
289
|
-
gsub(%r(((\[card\]|card)\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\3')
|
290
|
+
gsub(%r(((\[card\]|card)\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
291
|
+
gsub(%r(((\[bank_account\]|bank_account)\[account_number\]=)\d+), '\1[FILTERED]')
|
290
292
|
end
|
291
293
|
|
292
294
|
def supports_network_tokenization?
|
293
295
|
true
|
294
296
|
end
|
295
297
|
|
298
|
+
# Helper method to prevent hitting the external_account limit from remote test runs
|
299
|
+
def delete_latest_test_external_account(account)
|
300
|
+
return unless test?
|
301
|
+
|
302
|
+
auth_header = { 'Authorization': "Bearer #{options[:login]}" }
|
303
|
+
url = "#{live_url}accounts/#{CGI.escape(account)}/external_accounts"
|
304
|
+
accounts_response = JSON.parse(ssl_get("#{url}?limit=100", auth_header))
|
305
|
+
to_delete = accounts_response['data'].reject { |ac| ac['default_for_currency'] }
|
306
|
+
ssl_request(:delete, "#{url}/#{to_delete.first['id']}", nil, auth_header)
|
307
|
+
end
|
308
|
+
|
296
309
|
private
|
297
310
|
|
298
311
|
class StripePaymentToken < PaymentToken
|
@@ -379,6 +392,7 @@ module ActiveMerchant #:nodoc:
|
|
379
392
|
add_destination(post, options)
|
380
393
|
add_level_three(post, options)
|
381
394
|
add_connected_account(post, options)
|
395
|
+
add_radar_data(post, options)
|
382
396
|
post
|
383
397
|
end
|
384
398
|
|
@@ -532,7 +546,6 @@ module ActiveMerchant #:nodoc:
|
|
532
546
|
post[:metadata].merge!(options[:metadata]) if options[:metadata]
|
533
547
|
post[:metadata][:email] = options[:email] if options[:email]
|
534
548
|
post[:metadata][:order_id] = options[:order_id] if options[:order_id]
|
535
|
-
post.delete(:metadata) if post[:metadata].empty?
|
536
549
|
end
|
537
550
|
|
538
551
|
def add_emv_metadata(post, creditcard)
|
@@ -570,6 +583,14 @@ module ActiveMerchant #:nodoc:
|
|
570
583
|
post[:application_fee_amount] = options[:application_fee_amount] if options[:application_fee_amount]
|
571
584
|
end
|
572
585
|
|
586
|
+
def add_radar_data(post, options = {})
|
587
|
+
radar_options = {}
|
588
|
+
radar_options[:session] = options[:radar_session_id] if options[:radar_session_id]
|
589
|
+
radar_options[:skip_rules] = ['all'] if options[:skip_radar_rules]
|
590
|
+
|
591
|
+
post[:radar_options] = radar_options unless radar_options.empty?
|
592
|
+
end
|
593
|
+
|
573
594
|
def parse(body)
|
574
595
|
JSON.parse(body)
|
575
596
|
end
|
@@ -658,7 +679,6 @@ module ActiveMerchant #:nodoc:
|
|
658
679
|
card = card_from_response(response)
|
659
680
|
avs_code = AVS_CODE_TRANSLATOR["line1: #{card['address_line1_check']}, zip: #{card['address_zip_check']}"]
|
660
681
|
cvc_code = CVC_CODE_TRANSLATOR[card['cvc_check']]
|
661
|
-
|
662
682
|
Response.new(success,
|
663
683
|
message_from(success, response),
|
664
684
|
response,
|
@@ -754,7 +774,7 @@ module ActiveMerchant #:nodoc:
|
|
754
774
|
country: 'US',
|
755
775
|
currency: 'usd',
|
756
776
|
routing_number: bank_account.routing_number,
|
757
|
-
|
777
|
+
account_holder_name: bank_account.name,
|
758
778
|
account_holder_type: account_holder_type
|
759
779
|
}
|
760
780
|
}
|
@@ -5,33 +5,42 @@ module ActiveMerchant #:nodoc:
|
|
5
5
|
# This gateway uses the current Stripe {Payment Intents API}[https://stripe.com/docs/api/payment_intents].
|
6
6
|
# For the legacy API, see the Stripe gateway
|
7
7
|
class StripePaymentIntentsGateway < StripeGateway
|
8
|
-
self.supported_countries = %w(AT AU BE BG BR CA CH CY CZ DE DK EE ES FI FR GB GR HK IE IT JP LT LU LV MT MX NL NO NZ PL PT RO SE SG SI SK US)
|
9
|
-
|
10
8
|
ALLOWED_METHOD_STATES = %w[automatic manual].freeze
|
11
9
|
ALLOWED_CANCELLATION_REASONS = %w[duplicate fraudulent requested_by_customer abandoned].freeze
|
12
10
|
CREATE_INTENT_ATTRIBUTES = %i[description statement_descriptor_suffix statement_descriptor receipt_email save_payment_method]
|
13
11
|
CONFIRM_INTENT_ATTRIBUTES = %i[receipt_email return_url save_payment_method setup_future_usage off_session]
|
14
12
|
UPDATE_INTENT_ATTRIBUTES = %i[description statement_descriptor_suffix statement_descriptor receipt_email setup_future_usage]
|
15
|
-
DEFAULT_API_VERSION = '
|
13
|
+
DEFAULT_API_VERSION = '2020-08-27'
|
14
|
+
NO_WALLET_SUPPORT = %w(apple_pay google_pay android_pay)
|
16
15
|
|
17
16
|
def create_intent(money, payment_method, options = {})
|
17
|
+
card_source_pay = payment_method.source.to_s if defined?(payment_method.source)
|
18
|
+
card_brand_pay = card_brand(payment_method) unless payment_method.is_a?(String) || payment_method.nil?
|
19
|
+
if NO_WALLET_SUPPORT.include?(card_source_pay) || NO_WALLET_SUPPORT.include?(card_brand_pay)
|
20
|
+
store_apple_or_google_pay_token = 'Direct Apple Pay and Google Pay transactions are not supported. Those payment methods must be stored before use.'
|
21
|
+
return Response.new(false, store_apple_or_google_pay_token)
|
22
|
+
end
|
18
23
|
post = {}
|
19
24
|
add_amount(post, money, options, true)
|
20
25
|
add_capture_method(post, options)
|
21
26
|
add_confirmation_method(post, options)
|
22
27
|
add_customer(post, options)
|
23
|
-
|
24
|
-
return
|
28
|
+
result = add_payment_method_token(post, payment_method, options)
|
29
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
25
30
|
|
26
31
|
add_external_three_d_secure_auth_data(post, options)
|
27
32
|
add_metadata(post, options)
|
28
33
|
add_return_url(post, options)
|
29
34
|
add_connected_account(post, options)
|
35
|
+
add_radar_data(post, options)
|
30
36
|
add_shipping_address(post, options)
|
31
37
|
setup_future_usage(post, options)
|
32
38
|
add_exemption(post, options)
|
33
39
|
add_stored_credentials(post, options)
|
40
|
+
add_ntid(post, options)
|
41
|
+
add_claim_without_transaction_id(post, options)
|
34
42
|
add_error_on_requires_action(post, options)
|
43
|
+
add_fulfillment_date(post, options)
|
35
44
|
request_three_d_secure(post, options)
|
36
45
|
|
37
46
|
CREATE_INTENT_ATTRIBUTES.each do |attribute|
|
@@ -47,23 +56,24 @@ module ActiveMerchant #:nodoc:
|
|
47
56
|
|
48
57
|
def confirm_intent(intent_id, payment_method, options = {})
|
49
58
|
post = {}
|
50
|
-
|
51
|
-
return
|
59
|
+
result = add_payment_method_token(post, payment_method, options)
|
60
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
52
61
|
|
53
62
|
CONFIRM_INTENT_ATTRIBUTES.each do |attribute|
|
54
63
|
add_whitelisted_attribute(post, options, attribute)
|
55
64
|
end
|
65
|
+
|
56
66
|
commit(:post, "payment_intents/#{intent_id}/confirm", post, options)
|
57
67
|
end
|
58
68
|
|
59
69
|
def create_payment_method(payment_method, options = {})
|
60
|
-
post_data =
|
70
|
+
post_data = add_payment_method_data(payment_method, options)
|
61
71
|
|
62
72
|
options = format_idempotency_key(options, 'pm')
|
63
73
|
commit(:post, 'payment_methods', post_data, options)
|
64
74
|
end
|
65
75
|
|
66
|
-
def
|
76
|
+
def add_payment_method_data(payment_method, options = {})
|
67
77
|
post_data = {}
|
68
78
|
post_data[:type] = 'card'
|
69
79
|
post_data[:card] = {}
|
@@ -72,6 +82,7 @@ module ActiveMerchant #:nodoc:
|
|
72
82
|
post_data[:card][:exp_year] = payment_method.year
|
73
83
|
post_data[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
|
74
84
|
add_billing_address(post_data, options)
|
85
|
+
add_name_only(post_data, payment_method) if post_data[:billing_details].nil?
|
75
86
|
post_data
|
76
87
|
end
|
77
88
|
|
@@ -79,14 +90,15 @@ module ActiveMerchant #:nodoc:
|
|
79
90
|
post = {}
|
80
91
|
add_amount(post, money, options)
|
81
92
|
|
82
|
-
|
83
|
-
return
|
93
|
+
result = add_payment_method_token(post, payment_method, options)
|
94
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
84
95
|
|
85
96
|
add_payment_method_types(post, options)
|
86
97
|
add_customer(post, options)
|
87
98
|
add_metadata(post, options)
|
88
99
|
add_shipping_address(post, options)
|
89
100
|
add_connected_account(post, options)
|
101
|
+
add_fulfillment_date(post, options)
|
90
102
|
|
91
103
|
UPDATE_INTENT_ATTRIBUTES.each do |attribute|
|
92
104
|
add_whitelisted_attribute(post, options, attribute)
|
@@ -97,11 +109,12 @@ module ActiveMerchant #:nodoc:
|
|
97
109
|
def create_setup_intent(payment_method, options = {})
|
98
110
|
post = {}
|
99
111
|
add_customer(post, options)
|
100
|
-
|
101
|
-
return
|
112
|
+
result = add_payment_method_token(post, payment_method, options)
|
113
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
102
114
|
|
103
115
|
add_metadata(post, options)
|
104
116
|
add_return_url(post, options)
|
117
|
+
add_fulfillment_date(post, options)
|
105
118
|
post[:on_behalf_of] = options[:on_behalf_of] if options[:on_behalf_of]
|
106
119
|
post[:usage] = options[:usage] if %w(on_session off_session).include?(options[:usage])
|
107
120
|
post[:description] = options[:description] if options[:description]
|
@@ -177,8 +190,8 @@ module ActiveMerchant #:nodoc:
|
|
177
190
|
# If customer option is provided, create a payment method and attach to customer id
|
178
191
|
# Otherwise, create a customer, then attach
|
179
192
|
if payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
|
180
|
-
|
181
|
-
return
|
193
|
+
result = add_payment_method_token(params, payment_method, options)
|
194
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
182
195
|
|
183
196
|
if options[:customer]
|
184
197
|
customer_id = options[:customer]
|
@@ -186,6 +199,7 @@ module ActiveMerchant #:nodoc:
|
|
186
199
|
post[:description] = options[:description] if options[:description]
|
187
200
|
post[:email] = options[:email] if options[:email]
|
188
201
|
options = format_idempotency_key(options, 'customer')
|
202
|
+
post[:expand] = [:sources]
|
189
203
|
customer = commit(:post, 'customers', post, options)
|
190
204
|
customer_id = customer.params['id']
|
191
205
|
end
|
@@ -211,6 +225,16 @@ module ActiveMerchant #:nodoc:
|
|
211
225
|
create_setup_intent(payment_method, options.merge!(confirm: true))
|
212
226
|
end
|
213
227
|
|
228
|
+
def setup_purchase(money, options = {})
|
229
|
+
requires!(options, :payment_method_types)
|
230
|
+
post = {}
|
231
|
+
add_currency(post, options, money)
|
232
|
+
add_amount(post, money, options)
|
233
|
+
add_payment_method_types(post, options)
|
234
|
+
add_metadata(post, options)
|
235
|
+
commit(:post, 'payment_intents', post, options)
|
236
|
+
end
|
237
|
+
|
214
238
|
private
|
215
239
|
|
216
240
|
def off_session_request?(options = {})
|
@@ -241,6 +265,16 @@ module ActiveMerchant #:nodoc:
|
|
241
265
|
post[:customer] = customer if customer.start_with?('cus_')
|
242
266
|
end
|
243
267
|
|
268
|
+
def add_fulfillment_date(post, options)
|
269
|
+
post[:fulfillment_date] = options[:fulfillment_date].to_i if options[:fulfillment_date]
|
270
|
+
end
|
271
|
+
|
272
|
+
def add_metadata(post, options = {})
|
273
|
+
super
|
274
|
+
|
275
|
+
post[:metadata][:event_type] = options[:event_type] if options[:event_type]
|
276
|
+
end
|
277
|
+
|
244
278
|
def add_return_url(post, options)
|
245
279
|
return unless options[:confirm]
|
246
280
|
|
@@ -249,35 +283,36 @@ module ActiveMerchant #:nodoc:
|
|
249
283
|
end
|
250
284
|
|
251
285
|
def add_payment_method_token(post, payment_method, options)
|
252
|
-
return if payment_method.nil?
|
253
|
-
|
254
|
-
if payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
|
255
|
-
if off_session_request?(options)
|
256
|
-
post[:payment_method_data] = create_payment_method_data(payment_method, options)
|
257
|
-
return
|
258
|
-
else
|
259
|
-
p = create_payment_method(payment_method, options)
|
260
|
-
return p unless p.success?
|
261
|
-
|
262
|
-
payment_method = p.params['id']
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
286
|
case payment_method
|
267
287
|
when StripePaymentToken
|
268
288
|
post[:payment_method] = payment_method.payment_data['id']
|
269
289
|
when String
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
post[:customer] = customer_id
|
274
|
-
else
|
275
|
-
token = payment_method
|
276
|
-
end
|
277
|
-
post[:payment_method] = token
|
290
|
+
extract_token_from_string_and_maybe_add_customer_id(post, payment_method)
|
291
|
+
when ActiveMerchant::Billing::CreditCard
|
292
|
+
get_payment_method_data_from_card(post, payment_method, options)
|
278
293
|
end
|
294
|
+
end
|
279
295
|
|
280
|
-
|
296
|
+
def extract_token_from_string_and_maybe_add_customer_id(post, payment_method)
|
297
|
+
if payment_method.include?('|')
|
298
|
+
customer_id, payment_method = payment_method.split('|')
|
299
|
+
post[:customer] = customer_id
|
300
|
+
end
|
301
|
+
|
302
|
+
post[:payment_method] = payment_method
|
303
|
+
end
|
304
|
+
|
305
|
+
def get_payment_method_data_from_card(post, payment_method, options)
|
306
|
+
return create_payment_method_and_extract_token(post, payment_method, options) unless off_session_request?(options)
|
307
|
+
|
308
|
+
post[:payment_method_data] = add_payment_method_data(payment_method, options)
|
309
|
+
end
|
310
|
+
|
311
|
+
def create_payment_method_and_extract_token(post, payment_method, options)
|
312
|
+
payment_method_response = create_payment_method(payment_method, options)
|
313
|
+
return payment_method_response if payment_method_response.failure?
|
314
|
+
|
315
|
+
add_payment_method_token(post, payment_method_response.params['id'], options)
|
281
316
|
end
|
282
317
|
|
283
318
|
def add_payment_method_types(post, options)
|
@@ -295,6 +330,11 @@ module ActiveMerchant #:nodoc:
|
|
295
330
|
post[:payment_method_options][:card][:moto] = true if options[:moto]
|
296
331
|
end
|
297
332
|
|
333
|
+
# Stripe Payment Intents does not pass any parameters for cardholder/merchant initiated
|
334
|
+
# it also does not support installments for any country other than Mexico (reason for this is unknown)
|
335
|
+
# The only thing that Stripe PI requires for stored credentials to work currently is the network_transaction_id
|
336
|
+
# network_transaction_id is created when the card is authenticated using the field `setup_for_future_usage` with the value `off_session` see def setup_future_usage below
|
337
|
+
|
298
338
|
def add_stored_credentials(post, options = {})
|
299
339
|
return unless options[:stored_credential] && !options[:stored_credential].values.all?(&:nil?)
|
300
340
|
|
@@ -304,8 +344,33 @@ module ActiveMerchant #:nodoc:
|
|
304
344
|
post[:payment_method_options][:card][:mit_exemption] = {}
|
305
345
|
|
306
346
|
# Stripe PI accepts network_transaction_id and ds_transaction_id via mit field under card.
|
307
|
-
|
347
|
+
# The network_transaction_id can be sent in nested under stored credentials OR as its own field (add_ntid handles when it is sent in on its own)
|
348
|
+
# If it is sent is as its own field AND under stored credentials, the value sent under its own field is what will send.
|
308
349
|
post[:payment_method_options][:card][:mit_exemption][:ds_transaction_id] = stored_credential[:ds_transaction_id] if stored_credential[:ds_transaction_id]
|
350
|
+
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
|
351
|
+
end
|
352
|
+
|
353
|
+
def add_ntid(post, options = {})
|
354
|
+
return unless options[:network_transaction_id]
|
355
|
+
|
356
|
+
post[:payment_method_options] ||= {}
|
357
|
+
post[:payment_method_options][:card] ||= {}
|
358
|
+
post[:payment_method_options][:card][:mit_exemption] = {}
|
359
|
+
|
360
|
+
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = options[:network_transaction_id] if options[:network_transaction_id]
|
361
|
+
end
|
362
|
+
|
363
|
+
def add_claim_without_transaction_id(post, options = {})
|
364
|
+
return if options[:stored_credential] || options[:network_transaction_id] || options[:ds_transaction_id]
|
365
|
+
return unless options[:claim_without_transaction_id]
|
366
|
+
|
367
|
+
post[:payment_method_options] ||= {}
|
368
|
+
post[:payment_method_options][:card] ||= {}
|
369
|
+
post[:payment_method_options][:card][:mit_exemption] = {}
|
370
|
+
|
371
|
+
# Stripe PI accepts claim_without_transaction_id for transactions without transaction ids.
|
372
|
+
# Gateway validation for this field occurs through a different service, before the transaction request is sent to the gateway.
|
373
|
+
post[:payment_method_options][:card][:mit_exemption][:claim_without_transaction_id] = options[:claim_without_transaction_id]
|
309
374
|
end
|
310
375
|
|
311
376
|
def add_error_on_requires_action(post, options = {})
|
@@ -357,6 +422,13 @@ module ActiveMerchant #:nodoc:
|
|
357
422
|
post[:billing_details][:phone] = billing[:phone] if billing[:phone]
|
358
423
|
end
|
359
424
|
|
425
|
+
def add_name_only(post, payment_method)
|
426
|
+
post[:billing_details] = {} unless post[:billing_details]
|
427
|
+
|
428
|
+
name = [payment_method.first_name, payment_method.last_name].compact.join(' ')
|
429
|
+
post[:billing_details][:name] = name
|
430
|
+
end
|
431
|
+
|
360
432
|
def add_shipping_address(post, options = {})
|
361
433
|
return unless shipping = options[:shipping]
|
362
434
|
|
@@ -390,6 +462,10 @@ module ActiveMerchant #:nodoc:
|
|
390
462
|
|
391
463
|
super(response, options)
|
392
464
|
end
|
465
|
+
|
466
|
+
def add_currency(post, options, money)
|
467
|
+
post[:currency] = options[:currency] || currency(money)
|
468
|
+
end
|
393
469
|
end
|
394
470
|
end
|
395
471
|
end
|
@@ -317,7 +317,8 @@ module ActiveMerchant #:nodoc:
|
|
317
317
|
gsub(%r((<[^>]+pan>)[^<]+(<))i, '\1[FILTERED]\2').
|
318
318
|
gsub(%r((<[^>]+sec>)[^<]+(<))i, '\1[FILTERED]\2').
|
319
319
|
gsub(%r((<[^>]+id>)[^<]+(<))i, '\1[FILTERED]\2').
|
320
|
-
gsub(%r((<[^>]+regKey>)[^<]+(<))i, '\1[FILTERED]\2')
|
320
|
+
gsub(%r((<[^>]+regKey>)[^<]+(<))i, '\1[FILTERED]\2').
|
321
|
+
gsub(%r((<[^>]+acctNr>)[^<]+(<))i, '\1[FILTERED]\2')
|
321
322
|
end
|
322
323
|
|
323
324
|
private
|
@@ -331,7 +331,8 @@ module ActiveMerchant #:nodoc:
|
|
331
331
|
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
332
332
|
gsub(%r((&?cc=)\d*(&?)), '\1[FILTERED]\2').
|
333
333
|
gsub(%r((&?password=)[^&]+(&?)), '\1[FILTERED]\2').
|
334
|
-
gsub(%r((&?cvv=)\d*(&?)), '\1[FILTERED]\2')
|
334
|
+
gsub(%r((&?cvv=)\d*(&?)), '\1[FILTERED]\2').
|
335
|
+
gsub(%r((&?account=)\d*(&?)), '\1[FILTERED]\2')
|
335
336
|
end
|
336
337
|
|
337
338
|
private
|
@@ -16,7 +16,8 @@ module ActiveMerchant #:nodoc:
|
|
16
16
|
refund: 'cc:refund',
|
17
17
|
void: 'cc:void',
|
18
18
|
void_release: 'cc:void:release',
|
19
|
-
check_purchase: 'check:sale'
|
19
|
+
check_purchase: 'check:sale',
|
20
|
+
store: 'cc:save'
|
20
21
|
}
|
21
22
|
|
22
23
|
STANDARD_ERROR_CODE_MAPPING = {
|
@@ -43,14 +44,14 @@ module ActiveMerchant #:nodoc:
|
|
43
44
|
super
|
44
45
|
end
|
45
46
|
|
46
|
-
def authorize(money,
|
47
|
+
def authorize(money, payment, options = {})
|
47
48
|
post = {}
|
48
49
|
|
49
50
|
add_amount(post, money)
|
50
51
|
add_invoice(post, options)
|
51
|
-
add_payment(post,
|
52
|
-
unless
|
53
|
-
add_address(post,
|
52
|
+
add_payment(post, payment)
|
53
|
+
unless payment.is_a?(CreditCard) && payment.track_data.present?
|
54
|
+
add_address(post, payment, options)
|
54
55
|
add_customer_data(post, options)
|
55
56
|
end
|
56
57
|
add_split_payments(post, options)
|
@@ -97,6 +98,12 @@ module ActiveMerchant #:nodoc:
|
|
97
98
|
commit(:refund, post)
|
98
99
|
end
|
99
100
|
|
101
|
+
def store(payment, options = {})
|
102
|
+
post = {}
|
103
|
+
add_payment(post, payment, options)
|
104
|
+
commit(:store, post)
|
105
|
+
end
|
106
|
+
|
100
107
|
def verify(creditcard, options = {})
|
101
108
|
MultiResponse.run(:use_first_response) do |r|
|
102
109
|
r.process { authorize(1, creditcard, options) }
|
@@ -213,6 +220,8 @@ module ActiveMerchant #:nodoc:
|
|
213
220
|
elsif payment.respond_to?(:track_data) && payment.track_data.present?
|
214
221
|
post[:magstripe] = payment.track_data
|
215
222
|
post[:cardpresent] = true
|
223
|
+
elsif payment.is_a?(String)
|
224
|
+
post[:card] = payment
|
216
225
|
else
|
217
226
|
post[:card] = payment.number
|
218
227
|
post[:cvv2] = payment.verification_value if payment.verification_value?
|
@@ -299,6 +308,7 @@ module ActiveMerchant #:nodoc:
|
|
299
308
|
status: fields['UMstatus'],
|
300
309
|
auth_code: fields['UMauthCode'],
|
301
310
|
ref_num: fields['UMrefNum'],
|
311
|
+
card_ref: fields['UMcardRef'],
|
302
312
|
batch: fields['UMbatch'],
|
303
313
|
avs_result: fields['UMavsResult'],
|
304
314
|
avs_result_code: fields['UMavsResultCode'],
|
@@ -321,7 +331,7 @@ module ActiveMerchant #:nodoc:
|
|
321
331
|
error_code = (STANDARD_ERROR_CODE_MAPPING[response[:error_code]] || STANDARD_ERROR_CODE[:processing_error]) unless approved
|
322
332
|
Response.new(approved, message_from(response), response,
|
323
333
|
test: test?,
|
324
|
-
authorization: response
|
334
|
+
authorization: authorization_from(action, response),
|
325
335
|
cvv_result: response[:cvv2_result_code],
|
326
336
|
avs_result: { code: response[:avs_result_code] },
|
327
337
|
error_code: error_code)
|
@@ -337,13 +347,17 @@ module ActiveMerchant #:nodoc:
|
|
337
347
|
end
|
338
348
|
end
|
339
349
|
|
350
|
+
def authorization_from(action, response)
|
351
|
+
return (action == :store ? response[:card_ref] : response[:ref_num])
|
352
|
+
end
|
353
|
+
|
340
354
|
def post_data(action, parameters = {})
|
341
355
|
parameters[:command] = TRANSACTIONS[action]
|
342
356
|
parameters[:key] = @options[:login]
|
343
357
|
parameters[:software] = 'Active Merchant'
|
344
358
|
parameters[:testmode] = (@options[:test] ? 1 : 0) unless parameters.has_key?(:testmode)
|
345
359
|
seed = SecureRandom.hex(32).upcase
|
346
|
-
hash = Digest::SHA1.hexdigest("#{parameters[:command]}:#{@options[:password]}:#{parameters[:amount]}:#{parameters[:invoice]}:#{seed}")
|
360
|
+
hash = Digest::SHA1.hexdigest("#{parameters[:command]}:#{@options[:pin] || @options[:password]}:#{parameters[:amount]}:#{parameters[:invoice]}:#{seed}")
|
347
361
|
parameters[:hash] = "s/#{seed}/#{hash}/n"
|
348
362
|
|
349
363
|
parameters.collect { |key, value| "UM#{key}=#{CGI.escape(value.to_s)}" }.join('&')
|
@@ -63,6 +63,42 @@ module ActiveMerchant #:nodoc:
|
|
63
63
|
commit(:pci_buy_rollback, post)
|
64
64
|
end
|
65
65
|
|
66
|
+
def credit(money, payment, options = {})
|
67
|
+
# Not permitted for foreign cards.
|
68
|
+
commerce = options[:commerce] || @options[:commerce]
|
69
|
+
commerce_branch = options[:commerce_branch] || @options[:commerce_branch]
|
70
|
+
|
71
|
+
token = generate_token(@shop_process_id, 'refund', commerce, commerce_branch, amount(money), currency(money))
|
72
|
+
post = {}
|
73
|
+
post[:token] = token
|
74
|
+
post[:commerce] = commerce.to_i
|
75
|
+
post[:commerce_branch] = commerce_branch.to_i
|
76
|
+
post[:shop_process_id] = @shop_process_id
|
77
|
+
add_invoice(post, money, options)
|
78
|
+
add_card_data(post, payment)
|
79
|
+
add_customer_data(post, options)
|
80
|
+
post[:origin_shop_process_id] = options[:original_shop_process_id] if options[:original_shop_process_id]
|
81
|
+
commit(:refund, post)
|
82
|
+
end
|
83
|
+
|
84
|
+
def refund(money, authorization, options = {})
|
85
|
+
commerce = options[:commerce] || @options[:commerce]
|
86
|
+
commerce_branch = options[:commerce_branch] || @options[:commerce_branch]
|
87
|
+
shop_process_id = options[:shop_process_id] || @shop_process_id
|
88
|
+
_, original_shop_process_id = authorization.to_s.split('#')
|
89
|
+
|
90
|
+
token = generate_token(shop_process_id, 'refund', commerce, commerce_branch, amount(money), currency(money))
|
91
|
+
post = {}
|
92
|
+
post[:token] = token
|
93
|
+
post[:commerce] = commerce.to_i
|
94
|
+
post[:commerce_branch] = commerce_branch.to_i
|
95
|
+
post[:shop_process_id] = shop_process_id
|
96
|
+
add_invoice(post, money, options)
|
97
|
+
add_customer_data(post, options)
|
98
|
+
post[:origin_shop_process_id] = original_shop_process_id || options[:original_shop_process_id]
|
99
|
+
commit(:refund, post)
|
100
|
+
end
|
101
|
+
|
66
102
|
def supports_scrubbing?
|
67
103
|
true
|
68
104
|
end
|
@@ -146,15 +182,22 @@ module ActiveMerchant #:nodoc:
|
|
146
182
|
end
|
147
183
|
|
148
184
|
def message_from(response)
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
185
|
+
%w(confirmation refund).each do |m|
|
186
|
+
message =
|
187
|
+
response.dig(m, 'extended_response_description') ||
|
188
|
+
response.dig(m, 'response_description') ||
|
189
|
+
response.dig(m, 'response_details')
|
190
|
+
return message if message
|
191
|
+
end
|
192
|
+
[response.dig('messages', 0, 'key'), response.dig('messages', 0, 'dsc')].join(':')
|
153
193
|
end
|
154
194
|
|
155
195
|
def authorization_from(response)
|
156
|
-
|
157
|
-
|
196
|
+
response_body = response.dig('confirmation') || response.dig('refund')
|
197
|
+
return unless response_body
|
198
|
+
|
199
|
+
authorization_number = response_body.dig('authorization_number') || response_body.dig('authorization_code')
|
200
|
+
shop_process_id = response_body.dig('shop_process_id')
|
158
201
|
|
159
202
|
"#{authorization_number}##{shop_process_id}"
|
160
203
|
end
|