activemerchant 1.124.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 +85 -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/gateway.rb +1 -1
- 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/cyber_source.rb +11 -3
- data/lib/active_merchant/billing/gateways/d_local.rb +4 -5
- 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 +6 -3
- data/lib/active_merchant/billing/gateways/element.rb +20 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +106 -16
- data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
- data/lib/active_merchant/billing/gateways/kushki.rb +7 -0
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -1
- data/lib/active_merchant/billing/gateways/mundipagg.rb +8 -6
- data/lib/active_merchant/billing/gateways/nmi.rb +2 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +17 -2
- data/lib/active_merchant/billing/gateways/pay_trace.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +1 -1
- data/lib/active_merchant/billing/gateways/paymentez.rb +9 -2
- data/lib/active_merchant/billing/gateways/paysafe.rb +41 -5
- data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -1
- 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/safe_charge.rb +1 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +20 -10
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +37 -3
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +20 -6
- data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +181 -64
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +6 -2
@@ -220,8 +220,9 @@ module ActiveMerchant #:nodoc:
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def verify(creditcard, options = {})
|
223
|
+
amount = allow_0_auth?(creditcard) ? 0 : 100
|
223
224
|
MultiResponse.run(:use_first_response) do |r|
|
224
|
-
r.process { authorize(
|
225
|
+
r.process { authorize(amount, creditcard, options) }
|
225
226
|
r.process(:ignore_result) { void(r.authorization) }
|
226
227
|
end
|
227
228
|
end
|
@@ -276,6 +277,11 @@ module ActiveMerchant #:nodoc:
|
|
276
277
|
commit(order, :void, options[:retry_logic], options[:trace_number])
|
277
278
|
end
|
278
279
|
|
280
|
+
def allow_0_auth?(credit_card)
|
281
|
+
# Discover does not support a $0.00 authorization instead use $1.00
|
282
|
+
%w(visa master american_express diners_club jcb).include?(credit_card.brand)
|
283
|
+
end
|
284
|
+
|
279
285
|
# ==== Customer Profiles
|
280
286
|
# :customer_ref_num should be set unless you're happy with Orbital providing one
|
281
287
|
#
|
@@ -570,7 +576,7 @@ module ActiveMerchant #:nodoc:
|
|
570
576
|
# - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
|
571
577
|
unless creditcard.nil?
|
572
578
|
if creditcard.verification_value?
|
573
|
-
xml.tag! :CardSecValInd, '1' if %w(visa discover).include?(creditcard.brand)
|
579
|
+
xml.tag! :CardSecValInd, '1' if %w(visa master discover).include?(creditcard.brand)
|
574
580
|
xml.tag! :CardSecVal, creditcard.verification_value
|
575
581
|
end
|
576
582
|
end
|
@@ -632,6 +638,14 @@ module ActiveMerchant #:nodoc:
|
|
632
638
|
xml.tag!(:SCARecurringPayment, parameters[:sca_recurring]) if valid_eci
|
633
639
|
end
|
634
640
|
|
641
|
+
def add_mc_sca_merchant_initiated(xml, creditcard, parameters, three_d_secure)
|
642
|
+
return unless parameters && parameters[:sca_merchant_initiated] && creditcard.brand == 'master'
|
643
|
+
|
644
|
+
valid_eci = three_d_secure && three_d_secure[:eci] && three_d_secure[:eci] == '7'
|
645
|
+
|
646
|
+
xml.tag!(:SCAMerchantInitiatedTransaction, parameters[:sca_merchant_initiated]) if valid_eci
|
647
|
+
end
|
648
|
+
|
635
649
|
def add_dpanind(xml, creditcard)
|
636
650
|
return unless creditcard.is_a?(NetworkTokenizationCreditCard)
|
637
651
|
|
@@ -900,6 +914,7 @@ module ActiveMerchant #:nodoc:
|
|
900
914
|
add_card_indicators(xml, parameters)
|
901
915
|
add_stored_credentials(xml, parameters)
|
902
916
|
add_pymt_brand_program_code(xml, payment_source, three_d_secure)
|
917
|
+
add_mc_sca_merchant_initiated(xml, payment_source, parameters, three_d_secure)
|
903
918
|
add_mc_scarecurring(xml, payment_source, parameters, three_d_secure)
|
904
919
|
add_mc_program_protocol(xml, payment_source, three_d_secure)
|
905
920
|
add_mc_directory_trans_id(xml, payment_source, three_d_secure)
|
@@ -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)
|
@@ -300,7 +300,7 @@ module ActiveMerchant #:nodoc:
|
|
300
300
|
three_d_secure[:authentication_response_status]
|
301
301
|
elsif three_d_secure[:directory_response_status].present?
|
302
302
|
three_d_secure[:directory_response_status]
|
303
|
-
|
303
|
+
end
|
304
304
|
if status.present?
|
305
305
|
xml.tag! 'Status', status
|
306
306
|
xml.tag! 'AuthenticationStatus', status if version_2_or_newer?(three_d_secure)
|
@@ -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'
|
@@ -39,7 +39,14 @@ module ActiveMerchant #:nodoc:
|
|
39
39
|
'master' => 'mc',
|
40
40
|
'american_express' => 'ax',
|
41
41
|
'diners_club' => 'di',
|
42
|
-
'elo' => 'el'
|
42
|
+
'elo' => 'el',
|
43
|
+
'discover' => 'dc',
|
44
|
+
'maestro' => 'ms',
|
45
|
+
'sodexo' => 'sx',
|
46
|
+
'olimpica' => 'ol',
|
47
|
+
'carnet' => 'ct',
|
48
|
+
'unionpay' => 'up',
|
49
|
+
'jcb' => 'jc'
|
43
50
|
}.freeze
|
44
51
|
|
45
52
|
def initialize(options = {})
|
@@ -24,6 +24,7 @@ module ActiveMerchant #:nodoc:
|
|
24
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]
|
27
28
|
add_split_pay_details(post, options)
|
28
29
|
post[:settleWithAuth] = true
|
29
30
|
|
@@ -38,6 +39,7 @@ module ActiveMerchant #:nodoc:
|
|
38
39
|
add_merchant_details(post, options)
|
39
40
|
add_customer_data(post, payment, options) unless payment.is_a?(String)
|
40
41
|
add_three_d_secure(post, payment, options) if options[:three_d_secure]
|
42
|
+
add_stored_credential(post, options) if options[:stored_credential]
|
41
43
|
|
42
44
|
commit(:post, 'auths', post, options)
|
43
45
|
end
|
@@ -92,8 +94,8 @@ module ActiveMerchant #:nodoc:
|
|
92
94
|
commit(:post, 'profiles', post, options)
|
93
95
|
end
|
94
96
|
|
95
|
-
def
|
96
|
-
|
97
|
+
def unstore(pm_profile_id)
|
98
|
+
commit_for_unstore(:delete, "profiles/#{pm_profile_id}", nil, nil)
|
97
99
|
end
|
98
100
|
|
99
101
|
def supports_scrubbing?
|
@@ -203,7 +205,7 @@ module ActiveMerchant #:nodoc:
|
|
203
205
|
post[:authentication][:cavv] = three_d_secure[:cavv]
|
204
206
|
post[:authentication][:xid] = three_d_secure[:xid] if three_d_secure[:xid]
|
205
207
|
post[:authentication][:threeDSecureVersion] = three_d_secure[:version]
|
206
|
-
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)
|
207
209
|
end
|
208
210
|
|
209
211
|
def add_airline_travel_details(post, options)
|
@@ -284,6 +286,40 @@ module ActiveMerchant #:nodoc:
|
|
284
286
|
post[:splitpay] = split_pay
|
285
287
|
end
|
286
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'
|
321
|
+
end
|
322
|
+
|
287
323
|
def parse(body)
|
288
324
|
JSON.parse(body)
|
289
325
|
end
|
@@ -306,7 +342,7 @@ module ActiveMerchant #:nodoc:
|
|
306
342
|
)
|
307
343
|
end
|
308
344
|
|
309
|
-
def
|
345
|
+
def commit_for_unstore(method, action, parameters, options)
|
310
346
|
url = url(action)
|
311
347
|
response = raw_ssl_request(method, url, post_data(parameters, options), headers)
|
312
348
|
success = true if response.code == '200'
|
@@ -320,7 +356,7 @@ module ActiveMerchant #:nodoc:
|
|
320
356
|
def headers
|
321
357
|
{
|
322
358
|
'Content-Type' => 'application/json',
|
323
|
-
'Authorization' =>
|
359
|
+
'Authorization' => 'Basic ' + Base64.strict_encode64("#{@options[:username]}:#{@options[:password]}")
|
324
360
|
}
|
325
361
|
end
|
326
362
|
|
@@ -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
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class PaywayDotComGateway < Gateway
|
4
|
-
self.test_url = 'https://
|
5
|
-
self.live_url = 'https://
|
4
|
+
self.test_url = 'https://paywaywsdev.com/PaywayWS/Payment/CreditCard'
|
5
|
+
self.live_url = 'https://paywayws.com/PaywayWS/Payment/CreditCard'
|
6
6
|
|
7
7
|
self.supported_countries = %w[US CA]
|
8
8
|
self.default_currency = 'USD'
|
@@ -233,7 +233,7 @@ module ActiveMerchant #:nodoc:
|
|
233
233
|
|
234
234
|
return response['paywayCode'] + '-' + 'success' if success
|
235
235
|
|
236
|
-
response['paywayCode']
|
236
|
+
response['paywayCode']
|
237
237
|
end
|
238
238
|
|
239
239
|
def authorization_from(response)
|
@@ -6,8 +6,8 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
|
7
7
|
self.default_currency = 'AUD'
|
8
8
|
self.money_format = :cents
|
9
|
-
self.supported_countries =
|
10
|
-
self.supported_cardtypes = %i[visa master american_express]
|
9
|
+
self.supported_countries = %w(AU NZ)
|
10
|
+
self.supported_cardtypes = %i[visa master american_express diners_club discover jcb]
|
11
11
|
self.homepage_url = 'http://www.pinpayments.com/'
|
12
12
|
self.display_name = 'Pin Payments'
|
13
13
|
|
@@ -46,6 +46,17 @@ module ActiveMerchant #:nodoc:
|
|
46
46
|
commit(:post, 'customers', post, options)
|
47
47
|
end
|
48
48
|
|
49
|
+
# Unstore a customer and associated credit card.
|
50
|
+
def unstore(token)
|
51
|
+
customer_token =
|
52
|
+
if /cus_/.match?(token)
|
53
|
+
get_customer_token(token)
|
54
|
+
else
|
55
|
+
token
|
56
|
+
end
|
57
|
+
commit(:delete, "customers/#{CGI.escape(customer_token)}", {}, {})
|
58
|
+
end
|
59
|
+
|
49
60
|
# Refund a transaction
|
50
61
|
def refund(money, token, options = {})
|
51
62
|
commit(:post, "charges/#{CGI.escape(token)}/refunds", { amount: amount(money) }, options)
|
@@ -65,6 +76,11 @@ module ActiveMerchant #:nodoc:
|
|
65
76
|
commit(:put, "charges/#{CGI.escape(token)}/capture", { amount: amount(money) }, options)
|
66
77
|
end
|
67
78
|
|
79
|
+
# Voids a previously authorized charge.
|
80
|
+
def void(token, options = {})
|
81
|
+
commit(:put, "charges/#{CGI.escape(token)}/void", {}, options)
|
82
|
+
end
|
83
|
+
|
68
84
|
# Updates the credit card for the customer.
|
69
85
|
def update(token, creditcard, options = {})
|
70
86
|
post = {}
|
@@ -190,7 +206,9 @@ module ActiveMerchant #:nodoc:
|
|
190
206
|
body = parse(e.response.body)
|
191
207
|
end
|
192
208
|
|
193
|
-
if body
|
209
|
+
if body.nil?
|
210
|
+
no_content_response
|
211
|
+
elsif body['response']
|
194
212
|
success_response(body)
|
195
213
|
elsif body['error']
|
196
214
|
error_response(body)
|
@@ -220,6 +238,15 @@ module ActiveMerchant #:nodoc:
|
|
220
238
|
)
|
221
239
|
end
|
222
240
|
|
241
|
+
def no_content_response
|
242
|
+
Response.new(
|
243
|
+
true,
|
244
|
+
nil,
|
245
|
+
{},
|
246
|
+
test: test?
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
223
250
|
def unparsable_response(raw_response)
|
224
251
|
message = 'Invalid JSON response received from Pin Payments. Please contact support@pinpayments.com if you continue to receive this message.'
|
225
252
|
message += " (The raw response returned by the API was #{raw_response.inspect})"
|
@@ -235,7 +262,7 @@ module ActiveMerchant #:nodoc:
|
|
235
262
|
end
|
236
263
|
|
237
264
|
def parse(body)
|
238
|
-
JSON.parse(body)
|
265
|
+
JSON.parse(body) unless body.nil? || body.length == 0
|
239
266
|
end
|
240
267
|
|
241
268
|
def post_data(parameters = {})
|
@@ -0,0 +1,347 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PriorityGateway < Gateway
|
4
|
+
# Sandbox and Production
|
5
|
+
self.test_url = 'https://sandbox.api.mxmerchant.com/checkout/v3/payment'
|
6
|
+
self.live_url = 'https://api.mxmerchant.com/checkout/v3/payment'
|
7
|
+
|
8
|
+
class_attribute :test_url_verify, :live_url_verify, :test_auth, :live_auth, :test_env_verify, :live_env_verify, :test_url_batch, :live_url_batch, :test_url_jwt, :live_url_jwt, :merchant
|
9
|
+
|
10
|
+
# Sandbox and Production - verify card
|
11
|
+
self.test_url_verify = 'https://sandbox-api2.mxmerchant.com/merchant/v1/bin'
|
12
|
+
self.live_url_verify = 'https://api2.mxmerchant.com/merchant/v1/bin'
|
13
|
+
|
14
|
+
# Sandbox and Production - check batch status
|
15
|
+
self.test_url_batch = 'https://sandbox.api.mxmerchant.com/checkout/v3/batch'
|
16
|
+
self.live_url_batch = 'https://api.mxmerchant.com/checkout/v3/batch'
|
17
|
+
|
18
|
+
# Sandbox and Production - generate jwt for verify card url
|
19
|
+
self.test_url_jwt = 'https://sandbox-api2.mxmerchant.com/security/v1/application/merchantId'
|
20
|
+
self.live_url_jwt = 'https://api2.mxmerchant.com/security/v1/application/merchantId'
|
21
|
+
|
22
|
+
self.supported_countries = ['US']
|
23
|
+
self.default_currency = 'USD'
|
24
|
+
self.supported_cardtypes = %i[visa master american_express discover]
|
25
|
+
|
26
|
+
self.homepage_url = 'https://mxmerchant.com/'
|
27
|
+
self.display_name = 'Priority'
|
28
|
+
|
29
|
+
def initialize(options = {})
|
30
|
+
requires!(options, :merchant_id, :key, :secret)
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def basic_auth
|
35
|
+
Base64.strict_encode64("#{@options[:key]}:#{@options[:secret]}")
|
36
|
+
end
|
37
|
+
|
38
|
+
def request_headers
|
39
|
+
{
|
40
|
+
'Content-Type' => 'application/json',
|
41
|
+
'Authorization' => "Basic #{basic_auth}"
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def request_verify_headers(jwt)
|
46
|
+
{
|
47
|
+
'Authorization' => "Bearer #{jwt}"
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def purchase(amount, credit_card, options = {})
|
52
|
+
params = {}
|
53
|
+
params['amount'] = localized_amount(amount.to_f, options[:currency])
|
54
|
+
params['authOnly'] = false
|
55
|
+
|
56
|
+
add_credit_card(params, credit_card, 'purchase', options)
|
57
|
+
add_type_merchant_purchase(params, @options[:merchant_id], true, options)
|
58
|
+
commit('purchase', params: params, jwt: options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def authorize(amount, credit_card, options = {})
|
62
|
+
params = {}
|
63
|
+
params['amount'] = localized_amount(amount.to_f, options[:currency])
|
64
|
+
params['authOnly'] = true
|
65
|
+
|
66
|
+
add_credit_card(params, credit_card, 'purchase', options)
|
67
|
+
add_type_merchant_purchase(params, @options[:merchant_id], false, options)
|
68
|
+
commit('purchase', params: params, jwt: options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def refund(amount, authorization, options = {})
|
72
|
+
params = {}
|
73
|
+
params['merchantId'] = @options[:merchant_id]
|
74
|
+
params['paymentToken'] = get_hash(authorization)['payment_token'] || options[:payment_token]
|
75
|
+
# refund amounts must be negative
|
76
|
+
params['amount'] = ('-' + localized_amount(amount.to_f, options[:currency])).to_f
|
77
|
+
commit('refund', params: params, jwt: options)
|
78
|
+
end
|
79
|
+
|
80
|
+
def capture(amount, authorization, options = {})
|
81
|
+
params = {}
|
82
|
+
params['amount'] = localized_amount(amount.to_f, options[:currency])
|
83
|
+
params['authCode'] = options[:authCode]
|
84
|
+
params['merchantId'] = @options[:merchant_id]
|
85
|
+
params['paymentToken'] = get_hash(authorization)['payment_token']
|
86
|
+
params['shouldGetCreditCardLevel'] = true
|
87
|
+
params['source'] = options[:source]
|
88
|
+
params['tenderType'] = 'Card'
|
89
|
+
|
90
|
+
commit('capture', params: params, jwt: options)
|
91
|
+
end
|
92
|
+
|
93
|
+
def void(authorization, options = {})
|
94
|
+
commit('void', iid: get_hash(authorization)['id'], jwt: options)
|
95
|
+
end
|
96
|
+
|
97
|
+
def verify(credit_card, options)
|
98
|
+
jwt = options[:jwt_token]
|
99
|
+
commit('verify', card_number: credit_card.number, jwt: jwt)
|
100
|
+
end
|
101
|
+
|
102
|
+
def supports_scrubbing?
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_payment_status(batch_id, options)
|
107
|
+
commit('get_payment_status', params: batch_id, jwt: options)
|
108
|
+
end
|
109
|
+
|
110
|
+
def close_batch(batch_id, options)
|
111
|
+
commit('close_batch', params: batch_id, jwt: options)
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_jwt(options)
|
115
|
+
commit('create_jwt', params: @options[:merchant_id], jwt: options)
|
116
|
+
end
|
117
|
+
|
118
|
+
def scrub(transcript)
|
119
|
+
transcript.
|
120
|
+
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
|
121
|
+
gsub(%r((number\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
122
|
+
gsub(%r((cvv\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]')
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_credit_card(params, credit_card, action, options)
|
126
|
+
return unless credit_card&.is_a?(CreditCard)
|
127
|
+
|
128
|
+
card_details = {}
|
129
|
+
|
130
|
+
card_details['expiryMonth'] = format(credit_card.month, :two_digits).to_s
|
131
|
+
card_details['expiryYear'] = format(credit_card.year, :two_digits).to_s
|
132
|
+
card_details['expiryDate'] = exp_date(credit_card)
|
133
|
+
card_details['cardType'] = credit_card.brand
|
134
|
+
card_details['last4'] = credit_card.last_digits
|
135
|
+
card_details['cvv'] = credit_card.verification_value
|
136
|
+
card_details['number'] = credit_card.number
|
137
|
+
|
138
|
+
card_details['entryMode'] = options['entryMode'].blank? ? 'Keyed' : options['entryMode']
|
139
|
+
|
140
|
+
case action
|
141
|
+
when 'purchase'
|
142
|
+
card_details['avsStreet'] = options[:billing_address][:address1] if options[:billing_address]
|
143
|
+
card_details['avsZip'] = options[:billing_address][:zip] if options[:billing_address]
|
144
|
+
when 'refund'
|
145
|
+
card_details['cardId'] = options[:card_id]
|
146
|
+
card_details['cardPresent'] = options[:card_present]
|
147
|
+
card_details['hasContract'] = options[:has_contract]
|
148
|
+
card_details['isCorp'] = options[:is_corp]
|
149
|
+
card_details['isDebit'] = options[:is_debit]
|
150
|
+
card_details['token'] = options[:token]
|
151
|
+
else
|
152
|
+
card_details
|
153
|
+
end
|
154
|
+
|
155
|
+
params['cardAccount'] = card_details
|
156
|
+
end
|
157
|
+
|
158
|
+
def exp_date(credit_card)
|
159
|
+
"#{format(credit_card.month, :two_digits)}/#{format(credit_card.year, :two_digits)}"
|
160
|
+
end
|
161
|
+
|
162
|
+
def purchases
|
163
|
+
[{ taxRate: '0.0000', additionalTaxRate: nil, discountRate: nil }]
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_type_merchant_purchase(params, merchant, is_settle_funds, options)
|
167
|
+
params['cardPresent'] = false
|
168
|
+
params['cardPresentType'] = 'CardNotPresent'
|
169
|
+
params['isAuth'] = true
|
170
|
+
params['isSettleFunds'] = is_settle_funds
|
171
|
+
params['isTicket'] = false
|
172
|
+
|
173
|
+
params['merchantId'] = merchant
|
174
|
+
params['mxAdvantageEnabled'] = false
|
175
|
+
params['paymentType'] = 'Sale'
|
176
|
+
|
177
|
+
params['purchases'] = purchases
|
178
|
+
|
179
|
+
params['shouldGetCreditCardLevel'] = true
|
180
|
+
params['shouldVaultCard'] = true
|
181
|
+
params['source'] = options[:source]
|
182
|
+
params['sourceZip'] = options[:billing_address][:zip] if options[:billing_address]
|
183
|
+
params['taxExempt'] = false
|
184
|
+
params['tenderType'] = 'Card'
|
185
|
+
end
|
186
|
+
|
187
|
+
def commit(action, params: '', iid: '', card_number: nil, jwt: '')
|
188
|
+
response =
|
189
|
+
begin
|
190
|
+
case action
|
191
|
+
when 'void'
|
192
|
+
parse(ssl_request(:delete, url(action, params, ref_number: iid), nil, request_headers))
|
193
|
+
when 'verify'
|
194
|
+
parse(ssl_get(url(action, params, credit_card_number: card_number), request_verify_headers(jwt)))
|
195
|
+
when 'get_payment_status', 'create_jwt'
|
196
|
+
parse(ssl_get(url(action, params, ref_number: iid), request_headers))
|
197
|
+
when 'close_batch'
|
198
|
+
parse(ssl_request(:put, url(action, params, ref_number: iid), nil, request_headers))
|
199
|
+
else
|
200
|
+
parse(ssl_post(url(action, params), post_data(params), request_headers))
|
201
|
+
end
|
202
|
+
rescue ResponseError => e
|
203
|
+
parse(e.response.body)
|
204
|
+
end
|
205
|
+
success = success_from(response, action)
|
206
|
+
response = { 'code' => '204' } if response == ''
|
207
|
+
Response.new(
|
208
|
+
success,
|
209
|
+
message_from(response),
|
210
|
+
response,
|
211
|
+
authorization: success ? authorization_from(response) : nil,
|
212
|
+
error_code: success || response == '' ? nil : error_from(response),
|
213
|
+
test: test?
|
214
|
+
)
|
215
|
+
end
|
216
|
+
|
217
|
+
def handle_response(response)
|
218
|
+
if response.code != '204' && (200...300).cover?(response.code.to_i)
|
219
|
+
response.body
|
220
|
+
elsif response.code == '204' || response == ''
|
221
|
+
response.body = { 'code' => '204' }
|
222
|
+
else
|
223
|
+
raise ResponseError.new(response)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def url(action, params, ref_number: '', credit_card_number: nil)
|
228
|
+
case action
|
229
|
+
when 'void'
|
230
|
+
base_url + "/#{ref_number}?force=true"
|
231
|
+
when 'verify'
|
232
|
+
(verify_url + '?search=') + credit_card_number.to_s[0..6]
|
233
|
+
when 'get_payment_status', 'close_batch'
|
234
|
+
batch_url + "/#{params}"
|
235
|
+
when 'create_jwt'
|
236
|
+
jwt_url + "/#{params}/token"
|
237
|
+
else
|
238
|
+
base_url + '?includeCustomerMatches=false&echo=true'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def base_url
|
243
|
+
test? ? test_url : live_url
|
244
|
+
end
|
245
|
+
|
246
|
+
def verify_url
|
247
|
+
test? ? self.test_url_verify : self.live_url_verify
|
248
|
+
end
|
249
|
+
|
250
|
+
def jwt_url
|
251
|
+
test? ? self.test_url_jwt : self.live_url_jwt
|
252
|
+
end
|
253
|
+
|
254
|
+
def batch_url
|
255
|
+
test? ? self.test_url_batch : self.live_url_batch
|
256
|
+
end
|
257
|
+
|
258
|
+
def parse(body)
|
259
|
+
return body if body['code'] == '204'
|
260
|
+
|
261
|
+
JSON.parse(body)
|
262
|
+
rescue JSON::ParserError
|
263
|
+
message = 'Invalid JSON response received from Priority Gateway. Please contact Priority Gateway if you continue to receive this message.'
|
264
|
+
message += " (The raw response returned by the API was #{body.inspect})"
|
265
|
+
{
|
266
|
+
'message' => message
|
267
|
+
}
|
268
|
+
end
|
269
|
+
|
270
|
+
def success_from(response, action)
|
271
|
+
success = response['status'] == 'Approved' || response['status'] == 'Open' if response['status']
|
272
|
+
success = response['code'] == '204' if action == 'void'
|
273
|
+
success = !response['bank'].empty? if action == 'verify' && response['bank']
|
274
|
+
success
|
275
|
+
end
|
276
|
+
|
277
|
+
def message_from(response)
|
278
|
+
return response['details'][0] if response['details'] && response['details'][0]
|
279
|
+
|
280
|
+
response['authMessage'] || response['message'] || response['status']
|
281
|
+
end
|
282
|
+
|
283
|
+
def authorization_from(response)
|
284
|
+
{
|
285
|
+
'payment_token' => response['paymentToken'],
|
286
|
+
'id' => response['id']
|
287
|
+
}
|
288
|
+
end
|
289
|
+
|
290
|
+
def error_from(response)
|
291
|
+
response['errorCode'] || response['status']
|
292
|
+
end
|
293
|
+
|
294
|
+
def post_data(params)
|
295
|
+
params.to_json
|
296
|
+
end
|
297
|
+
|
298
|
+
def add_pos_data(options)
|
299
|
+
pos_options = {}
|
300
|
+
pos_options['panCaptureMethod'] = options[:pan_capture_method]
|
301
|
+
|
302
|
+
pos_options
|
303
|
+
end
|
304
|
+
|
305
|
+
def add_purchases_data(options)
|
306
|
+
purchases = {}
|
307
|
+
|
308
|
+
purchases['dateCreated'] = options[:date_created]
|
309
|
+
purchases['iId'] = options[:i_id]
|
310
|
+
purchases['transactionIId'] = options[:transaction_i_id]
|
311
|
+
purchases['transactionId'] = options[:transaction_id]
|
312
|
+
purchases['name'] = options[:name]
|
313
|
+
purchases['description'] = options[:description]
|
314
|
+
purchases['code'] = options[:code]
|
315
|
+
purchases['unitOfMeasure'] = options[:unit_of_measure]
|
316
|
+
purchases['unitPrice'] = options[:unit_price]
|
317
|
+
purchases['quantity'] = options[:quantity]
|
318
|
+
purchases['taxRate'] = options[:tax_rate]
|
319
|
+
purchases['taxAmount'] = options[:tax_amount]
|
320
|
+
purchases['discountRate'] = options[:discount_rate]
|
321
|
+
purchases['discountAmount'] = options[:discount_amt]
|
322
|
+
purchases['extendedAmount'] = options[:extended_amt]
|
323
|
+
purchases['lineItemId'] = options[:line_item_id]
|
324
|
+
|
325
|
+
purchase_arr = []
|
326
|
+
purchase_arr[0] = purchases
|
327
|
+
purchase_arr
|
328
|
+
end
|
329
|
+
|
330
|
+
def add_risk_data(options)
|
331
|
+
risk = {}
|
332
|
+
risk['cvvResponseCode'] = options[:cvv_response_code]
|
333
|
+
risk['cvvResponse'] = options[:cvv_response]
|
334
|
+
risk['cvvMatch'] = options[:cvv_match]
|
335
|
+
risk['avsResponse'] = options[:avs_response]
|
336
|
+
risk['avsAddressMatch'] = options[:avs_address_match]
|
337
|
+
risk['avsZipMatch'] = options[:avs_zip_match]
|
338
|
+
|
339
|
+
risk
|
340
|
+
end
|
341
|
+
|
342
|
+
def get_hash(string)
|
343
|
+
JSON.parse(string.gsub('=>', ':'))
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
@@ -147,6 +147,7 @@ module ActiveMerchant #:nodoc:
|
|
147
147
|
post[:sg_MerchantPhoneNumber] = options[:merchant_phone_number] if options[:merchant_phone_number]
|
148
148
|
post[:sg_MerchantName] = options[:merchant_name] if options[:merchant_name]
|
149
149
|
post[:sg_ProductID] = options[:product_id] if options[:product_id]
|
150
|
+
post[:sg_NotUseCVV] = options[:not_use_cvv].to_s == 'true' ? 1 : 0 unless options[:not_use_cvv].nil?
|
150
151
|
end
|
151
152
|
|
152
153
|
def add_payment(post, payment, options = {})
|