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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +85 -0
  3. data/lib/active_merchant/billing/check.rb +5 -8
  4. data/lib/active_merchant/billing/credit_card.rb +10 -0
  5. data/lib/active_merchant/billing/gateway.rb +1 -1
  6. data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
  7. data/lib/active_merchant/billing/gateways/checkout_v2.rb +33 -4
  8. data/lib/active_merchant/billing/gateways/cyber_source.rb +11 -3
  9. data/lib/active_merchant/billing/gateways/d_local.rb +4 -5
  10. data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
  11. data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
  12. data/lib/active_merchant/billing/gateways/elavon.rb +6 -3
  13. data/lib/active_merchant/billing/gateways/element.rb +20 -2
  14. data/lib/active_merchant/billing/gateways/global_collect.rb +106 -16
  15. data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
  16. data/lib/active_merchant/billing/gateways/kushki.rb +7 -0
  17. data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -1
  18. data/lib/active_merchant/billing/gateways/mundipagg.rb +8 -6
  19. data/lib/active_merchant/billing/gateways/nmi.rb +2 -1
  20. data/lib/active_merchant/billing/gateways/orbital.rb +17 -2
  21. data/lib/active_merchant/billing/gateways/pay_trace.rb +1 -1
  22. data/lib/active_merchant/billing/gateways/payflow.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/paymentez.rb +9 -2
  24. data/lib/active_merchant/billing/gateways/paysafe.rb +41 -5
  25. data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -1
  26. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  27. data/lib/active_merchant/billing/gateways/pin.rb +31 -4
  28. data/lib/active_merchant/billing/gateways/priority.rb +347 -0
  29. data/lib/active_merchant/billing/gateways/safe_charge.rb +1 -0
  30. data/lib/active_merchant/billing/gateways/stripe.rb +20 -10
  31. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +37 -3
  32. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +20 -6
  33. data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
  34. data/lib/active_merchant/billing/gateways/worldpay.rb +181 -64
  35. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  36. data/lib/active_merchant/version.rb +1 -1
  37. 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(100, creditcard, options) }
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 redact(customer_id)
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
- end
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 redact(pm_profile_id)
96
- commit_for_redact(:delete, "profiles/#{pm_profile_id}", nil, nil)
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.brand != 'mastercard'
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 commit_for_redact(method, action, parameters, options)
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' => "Basic #{Base64.strict_encode64(@options[:api_key].to_s)}"
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://devedgilpayway.net/PaywayWS/Payment/CreditCard'
5
- self.live_url = 'https://edgilpayway.com/PaywayWS/Payment/CreditCard'
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'] + '-' + response['paywayMessage']
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 = ['AU']
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['response']
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 = {})