activemerchant 1.130.0 → 1.137.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +268 -0
- data/lib/active_merchant/billing/check.rb +2 -2
- data/lib/active_merchant/billing/compatibility.rb +4 -4
- data/lib/active_merchant/billing/credit_card.rb +13 -8
- data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +64 -7
- data/lib/active_merchant/billing/gateway.rb +9 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +240 -41
- data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
- data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
- data/lib/active_merchant/billing/gateways/authorize_net.rb +44 -36
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
- data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
- data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
- data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
- data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
- data/lib/active_merchant/billing/gateways/borgun.rb +6 -4
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
- data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
- data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +252 -41
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +69 -8
- data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
- data/lib/active_merchant/billing/gateways/cyber_source.rb +192 -41
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
- data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
- data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
- data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
- data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
- data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
- data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
- data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
- data/lib/active_merchant/billing/gateways/element.rb +36 -7
- data/lib/active_merchant/billing/gateways/epay.rb +6 -2
- data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
- data/lib/active_merchant/billing/gateways/eway.rb +4 -2
- data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
- data/lib/active_merchant/billing/gateways/exact.rb +6 -2
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
- data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
- data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
- data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
- data/lib/active_merchant/billing/gateways/hps.rb +1 -1
- data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
- data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
- data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
- data/lib/active_merchant/billing/gateways/ipg.rb +10 -6
- data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
- data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
- data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
- data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
- data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
- data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
- data/lib/active_merchant/billing/gateways/kushki.rb +73 -13
- data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
- data/lib/active_merchant/billing/gateways/litle.rb +33 -50
- data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
- data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
- data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
- data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
- data/lib/active_merchant/billing/gateways/migs.rb +6 -2
- data/lib/active_merchant/billing/gateways/mit.rb +25 -20
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
- data/lib/active_merchant/billing/gateways/monei.rb +1 -1
- data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
- data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
- data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
- data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
- data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
- data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
- data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
- data/lib/active_merchant/billing/gateways/nmi.rb +23 -6
- data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
- data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
- data/lib/active_merchant/billing/gateways/opp.rb +1 -2
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
- data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
- data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
- data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
- data/lib/active_merchant/billing/gateways/payex.rb +4 -2
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
- data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
- data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
- data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
- data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
- data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
- data/lib/active_merchant/billing/gateways/payway.rb +6 -2
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
- data/lib/active_merchant/billing/gateways/pin.rb +22 -4
- data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
- data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
- data/lib/active_merchant/billing/gateways/priority.rb +6 -5
- data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
- data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
- data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
- data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
- data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
- data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
- data/lib/active_merchant/billing/gateways/reach.rb +11 -4
- data/lib/active_merchant/billing/gateways/redsys.rb +3 -11
- data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
- data/lib/active_merchant/billing/gateways/s5.rb +3 -3
- data/lib/active_merchant/billing/gateways/safe_charge.rb +38 -17
- data/lib/active_merchant/billing/gateways/sage.rb +12 -4
- data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
- data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
- data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
- data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
- data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
- data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
- data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
- data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
- data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +63 -19
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +280 -88
- data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
- data/lib/active_merchant/billing/gateways/telr.rb +3 -4
- data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
- data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
- data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
- data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
- data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
- data/lib/active_merchant/billing/gateways/vpos.rb +4 -4
- data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
- data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +147 -93
- data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
- data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/billing/response.rb +2 -2
- data/lib/active_merchant/connection.rb +3 -17
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/errors.rb +10 -0
- data/lib/active_merchant/version.rb +1 -1
- data/lib/support/gateway_support.rb +2 -2
- data/lib/support/ssl_verify.rb +4 -4
- data/lib/support/ssl_version.rb +6 -6
- metadata +30 -9
@@ -6,8 +6,8 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
|
7
7
|
class_attribute :simulator_url
|
8
8
|
|
9
|
-
self.test_url = 'https://
|
10
|
-
self.live_url = 'https://live.
|
9
|
+
self.test_url = 'https://sandbox.opayo.eu.elavon.com/gateway/service'
|
10
|
+
self.live_url = 'https://live.opayo.eu.elavon.com/gateway/service'
|
11
11
|
self.simulator_url = 'https://test.sagepay.com/Simulator'
|
12
12
|
|
13
13
|
APPROVED = 'OK'
|
@@ -78,6 +78,7 @@ module ActiveMerchant #:nodoc:
|
|
78
78
|
|
79
79
|
def initialize(options = {})
|
80
80
|
requires!(options, :login)
|
81
|
+
@protocol_version = options.fetch(:protocol_version, '3.00')
|
81
82
|
super
|
82
83
|
end
|
83
84
|
|
@@ -86,6 +87,9 @@ module ActiveMerchant #:nodoc:
|
|
86
87
|
|
87
88
|
post = {}
|
88
89
|
|
90
|
+
add_override_protocol_version(options)
|
91
|
+
add_three_ds_data(post, options)
|
92
|
+
add_stored_credentials_data(post, options)
|
89
93
|
add_amount(post, money, options)
|
90
94
|
add_invoice(post, options)
|
91
95
|
add_payment_method(post, payment_method, options)
|
@@ -101,6 +105,9 @@ module ActiveMerchant #:nodoc:
|
|
101
105
|
|
102
106
|
post = {}
|
103
107
|
|
108
|
+
add_three_ds_data(post, options)
|
109
|
+
add_stored_credentials_data(post, options)
|
110
|
+
add_override_protocol_version(options)
|
104
111
|
add_amount(post, money, options)
|
105
112
|
add_invoice(post, options)
|
106
113
|
add_payment_method(post, payment_method, options)
|
@@ -115,6 +122,7 @@ module ActiveMerchant #:nodoc:
|
|
115
122
|
def capture(money, identification, options = {})
|
116
123
|
post = {}
|
117
124
|
|
125
|
+
add_override_protocol_version(options)
|
118
126
|
add_reference(post, identification)
|
119
127
|
add_release_amount(post, money, options)
|
120
128
|
|
@@ -124,6 +132,7 @@ module ActiveMerchant #:nodoc:
|
|
124
132
|
def void(identification, options = {})
|
125
133
|
post = {}
|
126
134
|
|
135
|
+
add_override_protocol_version(options)
|
127
136
|
add_reference(post, identification)
|
128
137
|
action = abort_or_void_from(identification)
|
129
138
|
|
@@ -136,6 +145,7 @@ module ActiveMerchant #:nodoc:
|
|
136
145
|
|
137
146
|
post = {}
|
138
147
|
|
148
|
+
add_override_protocol_version(options)
|
139
149
|
add_related_reference(post, identification)
|
140
150
|
add_amount(post, money, options)
|
141
151
|
add_invoice(post, options)
|
@@ -150,6 +160,7 @@ module ActiveMerchant #:nodoc:
|
|
150
160
|
|
151
161
|
def store(credit_card, options = {})
|
152
162
|
post = {}
|
163
|
+
add_override_protocol_version(options)
|
153
164
|
add_credit_card(post, credit_card)
|
154
165
|
add_currency(post, 0, options)
|
155
166
|
|
@@ -158,6 +169,7 @@ module ActiveMerchant #:nodoc:
|
|
158
169
|
|
159
170
|
def unstore(token, options = {})
|
160
171
|
post = {}
|
172
|
+
add_override_protocol_version(options)
|
161
173
|
add_token(post, token)
|
162
174
|
commit(:unstore, post)
|
163
175
|
end
|
@@ -182,6 +194,58 @@ module ActiveMerchant #:nodoc:
|
|
182
194
|
|
183
195
|
private
|
184
196
|
|
197
|
+
def add_override_protocol_version(options)
|
198
|
+
@protocol_version = options[:protocol_version] if options[:protocol_version]
|
199
|
+
end
|
200
|
+
|
201
|
+
def add_three_ds_data(post, options)
|
202
|
+
return unless @protocol_version == '4.00'
|
203
|
+
return unless three_ds_2_options = options[:three_ds_2]
|
204
|
+
|
205
|
+
add_pair(post, :ThreeDSNotificationURL, three_ds_2_options[:notification_url])
|
206
|
+
return unless three_ds_2_options[:browser_info]
|
207
|
+
|
208
|
+
add_browser_info(post, three_ds_2_options[:browser_info])
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_browser_info(post, browser_info)
|
212
|
+
add_pair(post, :BrowserAcceptHeader, browser_info[:accept_header])
|
213
|
+
add_pair(post, :BrowserColorDepth, browser_info[:depth])
|
214
|
+
add_pair(post, :BrowserJavascriptEnabled, format_boolean(browser_info[:java]))
|
215
|
+
add_pair(post, :BrowserJavaEnabled, format_boolean(browser_info[:java]))
|
216
|
+
add_pair(post, :BrowserLanguage, browser_info[:language])
|
217
|
+
add_pair(post, :BrowserScreenHeight, browser_info[:height])
|
218
|
+
add_pair(post, :BrowserScreenWidth, browser_info[:width])
|
219
|
+
add_pair(post, :BrowserTZ, browser_info[:timezone])
|
220
|
+
add_pair(post, :BrowserUserAgent, browser_info[:user_agent])
|
221
|
+
add_pair(post, :ChallengeWindowSize, browser_info[:browser_size])
|
222
|
+
end
|
223
|
+
|
224
|
+
def add_stored_credentials_data(post, options)
|
225
|
+
return unless @protocol_version == '4.00'
|
226
|
+
return unless stored_credential = options[:stored_credential]
|
227
|
+
|
228
|
+
initiator = stored_credential[:initiator] == 'cardholder' ? 'CIT' : 'MIT'
|
229
|
+
cof_usage = if stored_credential[:initial_transaction] && initiator == 'CIT'
|
230
|
+
'FIRST'
|
231
|
+
elsif !stored_credential[:initial_transaction] && initiator == 'MIT'
|
232
|
+
'SUBSEQUENT'
|
233
|
+
end
|
234
|
+
|
235
|
+
add_pair(post, :COFUsage, cof_usage) if cof_usage
|
236
|
+
add_pair(post, :InitiatedTYPE, initiator)
|
237
|
+
add_pair(post, :SchemeTraceID, stored_credential[:network_transaction_id]) if stored_credential[:network_transaction_id]
|
238
|
+
|
239
|
+
reasoning = stored_credential[:reason_type] == 'installment' ? 'instalment' : stored_credential[:reason_type]
|
240
|
+
add_pair(post, :MITType, reasoning.upcase)
|
241
|
+
|
242
|
+
if %w(instalment recurring).any?(reasoning)
|
243
|
+
add_pair(post, :RecurringExpiry, options[:recurring_expiry])
|
244
|
+
add_pair(post, :RecurringFrequency, options[:recurring_frequency])
|
245
|
+
add_pair(post, :PurchaseInstalData, options[:installment_data])
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
185
249
|
def truncate(value, max_size)
|
186
250
|
return nil unless value
|
187
251
|
return value.to_s if CGI.escape(value.to_s).length <= max_size
|
@@ -346,14 +410,18 @@ module ActiveMerchant #:nodoc:
|
|
346
410
|
def commit(action, parameters)
|
347
411
|
response = parse(ssl_post(url_for(action), post_data(action, parameters)))
|
348
412
|
|
349
|
-
Response.new(
|
413
|
+
Response.new(
|
414
|
+
response['Status'] == APPROVED,
|
415
|
+
message_from(response),
|
416
|
+
response,
|
350
417
|
test: test?,
|
351
418
|
authorization: authorization_from(response, parameters, action),
|
352
419
|
avs_result: {
|
353
420
|
street_match: AVS_CODE[response['AddressResult']],
|
354
421
|
postal_match: AVS_CODE[response['PostCodeResult']]
|
355
422
|
},
|
356
|
-
cvv_result: CVV_CODE[response['CV2Result']]
|
423
|
+
cvv_result: CVV_CODE[response['CV2Result']]
|
424
|
+
)
|
357
425
|
end
|
358
426
|
|
359
427
|
def authorization_from(response, params, action)
|
@@ -401,7 +469,7 @@ module ActiveMerchant #:nodoc:
|
|
401
469
|
parameters.update(
|
402
470
|
Vendor: @options[:login],
|
403
471
|
TxType: TRANSACTIONS[action],
|
404
|
-
VPSProtocol: @
|
472
|
+
VPSProtocol: @protocol_version
|
405
473
|
)
|
406
474
|
|
407
475
|
parameters.update(ReferrerID: application_id) if application_id && (application_id != Gateway.application_id)
|
@@ -409,6 +477,12 @@ module ActiveMerchant #:nodoc:
|
|
409
477
|
parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
|
410
478
|
end
|
411
479
|
|
480
|
+
def format_boolean(value)
|
481
|
+
return if value.nil?
|
482
|
+
|
483
|
+
value ? '1' : '0'
|
484
|
+
end
|
485
|
+
|
412
486
|
# SagePay returns data in the following format
|
413
487
|
# Key1=value1
|
414
488
|
# Key2=value2
|
@@ -120,9 +120,13 @@ module ActiveMerchant #:nodoc:
|
|
120
120
|
end
|
121
121
|
|
122
122
|
response = parse(ssl_post(self.live_url, parameters.to_post_data) || '')
|
123
|
-
Response.new(
|
123
|
+
Response.new(
|
124
|
+
successful?(response),
|
125
|
+
message_from(response),
|
126
|
+
response,
|
124
127
|
test: test?,
|
125
|
-
authorization: response['refcode']
|
128
|
+
authorization: response['refcode']
|
129
|
+
)
|
126
130
|
end
|
127
131
|
|
128
132
|
def successful?(response)
|
@@ -79,11 +79,15 @@ module ActiveMerchant #:nodoc:
|
|
79
79
|
data = ssl_post(url, xml, 'Content-Type' => 'text/xml')
|
80
80
|
response = parse(data)
|
81
81
|
|
82
|
-
Response.new(
|
82
|
+
Response.new(
|
83
|
+
success?(response),
|
84
|
+
message_from(response),
|
85
|
+
response,
|
83
86
|
test: test?,
|
84
87
|
authorization: build_authorization(response),
|
85
88
|
avs_result: { code: response[:avs_result_code] },
|
86
|
-
cvv_result: response[:card_code_response_code]
|
89
|
+
cvv_result: response[:card_code_response_code]
|
90
|
+
)
|
87
91
|
end
|
88
92
|
|
89
93
|
def build_request(request)
|
@@ -56,12 +56,16 @@ module ActiveMerchant #:nodoc:
|
|
56
56
|
|
57
57
|
message = message_from(response)
|
58
58
|
|
59
|
-
Response.new(
|
59
|
+
Response.new(
|
60
|
+
success?(response),
|
61
|
+
message,
|
62
|
+
response,
|
60
63
|
test: test?,
|
61
64
|
authorization: response[:transaction_id],
|
62
65
|
fraud_review: fraud_review?(response),
|
63
66
|
avs_result: { code: response[:avs_result_code] },
|
64
|
-
cvv_result: response[:card_code]
|
67
|
+
cvv_result: response[:card_code]
|
68
|
+
)
|
65
69
|
end
|
66
70
|
|
67
71
|
def success?(response)
|
@@ -75,7 +79,7 @@ module ActiveMerchant #:nodoc:
|
|
75
79
|
def parse(body)
|
76
80
|
fields = split(body)
|
77
81
|
|
78
|
-
|
82
|
+
{
|
79
83
|
response_code: fields[RESPONSE_CODE].to_i,
|
80
84
|
response_reason_code: fields[RESPONSE_REASON_CODE],
|
81
85
|
response_reason_text: fields[RESPONSE_REASON_TEXT],
|
@@ -85,7 +89,6 @@ module ActiveMerchant #:nodoc:
|
|
85
89
|
authorization_code: fields[AUTHORIZATION_CODE],
|
86
90
|
cardholder_authentication_code: fields[CARDHOLDER_AUTH_CODE]
|
87
91
|
}
|
88
|
-
results
|
89
92
|
end
|
90
93
|
|
91
94
|
def post_data(action, parameters = {})
|
@@ -101,8 +104,7 @@ module ActiveMerchant #:nodoc:
|
|
101
104
|
post[:encap_char] = '$'
|
102
105
|
post[:solution_ID] = application_id if application_id
|
103
106
|
|
104
|
-
|
105
|
-
request
|
107
|
+
post.merge(parameters).collect { |key, value| "x_#{key}=#{CGI.escape(value.to_s)}" }.join('&')
|
106
108
|
end
|
107
109
|
|
108
110
|
def add_currency_code(post, money, options)
|
@@ -183,9 +183,13 @@ module ActiveMerchant #:nodoc:
|
|
183
183
|
def commit(action, request)
|
184
184
|
response = parse(ssl_post(test? ? self.test_url : self.live_url, build_request(action, request)))
|
185
185
|
|
186
|
-
Response.new(
|
186
|
+
Response.new(
|
187
|
+
success?(response),
|
188
|
+
message_from(response),
|
189
|
+
response,
|
187
190
|
test: test?,
|
188
|
-
authorization: authorization_from(response)
|
191
|
+
authorization: authorization_from(response)
|
192
|
+
)
|
189
193
|
end
|
190
194
|
|
191
195
|
def build_periodic_item(action, money, credit_card, options)
|
@@ -239,9 +243,13 @@ module ActiveMerchant #:nodoc:
|
|
239
243
|
my_request = build_periodic_request(request)
|
240
244
|
response = parse(ssl_post(test? ? self.test_periodic_url : self.live_periodic_url, my_request))
|
241
245
|
|
242
|
-
Response.new(
|
246
|
+
Response.new(
|
247
|
+
success?(response),
|
248
|
+
message_from(response),
|
249
|
+
response,
|
243
250
|
test: test?,
|
244
|
-
authorization: authorization_from(response)
|
251
|
+
authorization: authorization_from(response)
|
252
|
+
)
|
245
253
|
end
|
246
254
|
|
247
255
|
def success?(response)
|
@@ -84,9 +84,13 @@ module ActiveMerchant #:nodoc:
|
|
84
84
|
def commit(action, post)
|
85
85
|
response = parse(ssl_post(self.live_url, post_data(action, post)))
|
86
86
|
|
87
|
-
Response.new(
|
87
|
+
Response.new(
|
88
|
+
response[:result_code] == 1,
|
89
|
+
message_from(response),
|
90
|
+
response,
|
88
91
|
test: test?,
|
89
|
-
authorization: response[:merchant_transaction_reference]
|
92
|
+
authorization: response[:merchant_transaction_reference]
|
93
|
+
)
|
90
94
|
end
|
91
95
|
|
92
96
|
def message_from(result)
|
@@ -193,7 +193,8 @@ module ActiveMerchant #:nodoc:
|
|
193
193
|
post[:card] = card
|
194
194
|
add_address(post, options)
|
195
195
|
elsif creditcard.kind_of?(String)
|
196
|
-
|
196
|
+
key = creditcard.match(/^pm_/) ? :paymentMethod : :card
|
197
|
+
post[key] = creditcard
|
197
198
|
else
|
198
199
|
raise ArgumentError.new("Unhandled payment method #{creditcard.class}.")
|
199
200
|
end
|
@@ -223,24 +224,37 @@ module ActiveMerchant #:nodoc:
|
|
223
224
|
end
|
224
225
|
|
225
226
|
response = api_request(url, parameters, options, method)
|
226
|
-
success =
|
227
|
+
success = success?(response)
|
227
228
|
|
228
|
-
Response.new(
|
229
|
+
Response.new(
|
230
|
+
success,
|
229
231
|
(success ? 'Transaction approved' : response['error']['message']),
|
230
232
|
response,
|
231
233
|
test: test?,
|
232
|
-
authorization: (
|
233
|
-
error_code: (success ? nil : STANDARD_ERROR_CODE_MAPPING[response['error']['code']])
|
234
|
+
authorization: authorization_from(url, response),
|
235
|
+
error_code: (success ? nil : STANDARD_ERROR_CODE_MAPPING[response['error']['code']])
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
def authorization_from(action, response)
|
240
|
+
if action == 'customers' && success?(response) && response['cards'].present?
|
241
|
+
response['cards'].first['id']
|
242
|
+
else
|
243
|
+
success?(response) ? response['id'] : (response.dig('error', 'charge') || response.dig('error', 'chargeId'))
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def success?(response)
|
248
|
+
!response.key?('error')
|
234
249
|
end
|
235
250
|
|
236
251
|
def headers(options = {})
|
237
252
|
secret_key = options[:secret_key] || @options[:secret_key]
|
238
253
|
|
239
|
-
|
254
|
+
{
|
240
255
|
'Authorization' => 'Basic ' + Base64.encode64(secret_key.to_s + ':').strip,
|
241
256
|
'User-Agent' => "SecurionPay/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}"
|
242
257
|
}
|
243
|
-
headers
|
244
258
|
end
|
245
259
|
|
246
260
|
def response_error(raw_response)
|
@@ -287,8 +301,8 @@ module ActiveMerchant #:nodoc:
|
|
287
301
|
response
|
288
302
|
end
|
289
303
|
|
290
|
-
def json_error(raw_response)
|
291
|
-
msg =
|
304
|
+
def json_error(raw_response, gateway_name = 'SecurionPay')
|
305
|
+
msg = "Invalid response received from the #{gateway_name} API."
|
292
306
|
msg += " (The raw response returned by the API was #{raw_response.inspect})"
|
293
307
|
{
|
294
308
|
'error' => {
|
@@ -298,7 +312,7 @@ module ActiveMerchant #:nodoc:
|
|
298
312
|
end
|
299
313
|
|
300
314
|
def test?
|
301
|
-
|
315
|
+
@options[:secret_key]&.include?('_test_')
|
302
316
|
end
|
303
317
|
end
|
304
318
|
end
|
@@ -20,22 +20,6 @@ module ActiveMerchant #:nodoc:
|
|
20
20
|
'add' => 'tokens',
|
21
21
|
'verify' => 'cards'
|
22
22
|
}
|
23
|
-
STANDARD_ERROR_CODE_MAPPING = {
|
24
|
-
'incorrect_number' => STANDARD_ERROR_CODE[:incorrect_number],
|
25
|
-
'invalid_number' => STANDARD_ERROR_CODE[:invalid_number],
|
26
|
-
'invalid_expiry_month' => STANDARD_ERROR_CODE[:invalid_expiry_date],
|
27
|
-
'invalid_expiry_year' => STANDARD_ERROR_CODE[:invalid_expiry_date],
|
28
|
-
'invalid_cvc' => STANDARD_ERROR_CODE[:invalid_cvc],
|
29
|
-
'expired_card' => STANDARD_ERROR_CODE[:expired_card],
|
30
|
-
'insufficient_funds' => STANDARD_ERROR_CODE[:card_declined],
|
31
|
-
'incorrect_cvc' => STANDARD_ERROR_CODE[:incorrect_cvc],
|
32
|
-
'incorrect_zip' => STANDARD_ERROR_CODE[:incorrect_zip],
|
33
|
-
'card_declined' => STANDARD_ERROR_CODE[:card_declined],
|
34
|
-
'processing_error' => STANDARD_ERROR_CODE[:processing_error],
|
35
|
-
'lost_or_stolen' => STANDARD_ERROR_CODE[:card_declined],
|
36
|
-
'suspected_fraud' => STANDARD_ERROR_CODE[:card_declined],
|
37
|
-
'expired_token' => STANDARD_ERROR_CODE[:card_declined]
|
38
|
-
}
|
39
23
|
|
40
24
|
def initialize(options = {})
|
41
25
|
requires!(options, :client_guid, :auth_token)
|
@@ -147,7 +131,7 @@ module ActiveMerchant #:nodoc:
|
|
147
131
|
gsub(%r(("expirationDate\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
148
132
|
gsub(%r(("FirstName\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
149
133
|
gsub(%r(("LastName\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
|
150
|
-
gsub(%r(("securityCode\\?":{\\?"
|
134
|
+
gsub(%r(("securityCode\\?":{\\?"\w+\\?":\d+,\\?"value\\?":\\?")\d*)i, '\1[FILTERED]')
|
151
135
|
end
|
152
136
|
|
153
137
|
def setup_access_token
|
@@ -263,6 +247,7 @@ module ActiveMerchant #:nodoc:
|
|
263
247
|
message_from(action, response),
|
264
248
|
response,
|
265
249
|
authorization: authorization_from(action, response),
|
250
|
+
avs_result: avs_result_from(response),
|
266
251
|
test: test?,
|
267
252
|
error_code: error_code_from(action, response)
|
268
253
|
)
|
@@ -284,13 +269,25 @@ module ActiveMerchant #:nodoc:
|
|
284
269
|
end
|
285
270
|
|
286
271
|
def message_from(action, response)
|
287
|
-
success_from(action, response) ? 'Transaction successful' : (error(response)&.dig('longText') || 'Transaction declined')
|
272
|
+
success_from(action, response) ? 'Transaction successful' : (error(response)&.dig('longText') || response['result'].first&.dig('transaction', 'hostResponse', 'reasonDescription') || 'Transaction declined')
|
288
273
|
end
|
289
274
|
|
290
275
|
def error_code_from(action, response)
|
291
|
-
|
276
|
+
code = response['result'].first&.dig('transaction', 'responseCode')
|
277
|
+
primary_code = response['result'].first['error'].present?
|
278
|
+
return unless code == 'D' || primary_code == true || success_from(action, response)
|
279
|
+
|
280
|
+
if response['result'].first&.dig('transaction', 'hostResponse')
|
281
|
+
response['result'].first&.dig('transaction', 'hostResponse', 'reasonCode')
|
282
|
+
elsif response['result'].first['error']
|
283
|
+
response['result'].first&.dig('error', 'primaryCode')
|
284
|
+
else
|
285
|
+
response['result'].first&.dig('transaction', 'responseCode')
|
286
|
+
end
|
287
|
+
end
|
292
288
|
|
293
|
-
|
289
|
+
def avs_result_from(response)
|
290
|
+
AVSResult.new(code: response['result'].first&.dig('transaction', 'avs', 'result')) if response['result'].first&.dig('transaction', 'avs')
|
294
291
|
end
|
295
292
|
|
296
293
|
def authorization_from(action, response)
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class Shift4V2Gateway < SecurionPayGateway
|
4
|
+
# same endpont for testing
|
5
|
+
self.live_url = 'https://api.shift4.com/'
|
6
|
+
self.display_name = 'Shift4'
|
7
|
+
self.homepage_url = 'https://dev.shift4.com/us/'
|
8
|
+
|
9
|
+
def credit(money, payment, options = {})
|
10
|
+
post = create_post_for_auth_or_purchase(money, payment, options)
|
11
|
+
commit('credits', post, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def store(payment_method, options = {})
|
15
|
+
post = case payment_method
|
16
|
+
when CreditCard
|
17
|
+
cc = {}.tap { |card| add_creditcard(card, payment_method, options) }[:card]
|
18
|
+
options[:customer_id].blank? ? { email: options[:email], card: cc } : cc
|
19
|
+
when Check
|
20
|
+
bank_account_object(payment_method, options)
|
21
|
+
else
|
22
|
+
raise ArgumentError.new("Unhandled payment method #{payment_method.class}.")
|
23
|
+
end
|
24
|
+
|
25
|
+
commit url_for_store(payment_method, options), post, options
|
26
|
+
end
|
27
|
+
|
28
|
+
def url_for_store(payment_method, options = {})
|
29
|
+
case payment_method
|
30
|
+
when CreditCard
|
31
|
+
options[:customer_id].blank? ? 'customers' : "customers/#{options[:customer_id]}/cards"
|
32
|
+
when Check then 'payment-methods'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def unstore(reference, options = {})
|
37
|
+
commit("customers/#{options[:customer_id]}/cards/#{reference}", nil, options, :delete)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_post_for_auth_or_purchase(money, payment, options)
|
41
|
+
super.tap do |post|
|
42
|
+
add_stored_credentials(post, options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_stored_credentials(post, options)
|
47
|
+
return unless options[:stored_credential].present?
|
48
|
+
|
49
|
+
initiator = options.dig(:stored_credential, :initiator)
|
50
|
+
reason_type = options.dig(:stored_credential, :reason_type)
|
51
|
+
|
52
|
+
post_type = {
|
53
|
+
%w[cardholder recurring] => 'first_recurring',
|
54
|
+
%w[merchant recurring] => 'subsequent_recurring',
|
55
|
+
%w[cardholder unscheduled] => 'customer_initiated',
|
56
|
+
%w[merchant installment] => 'merchant_initiated'
|
57
|
+
}[[initiator, reason_type]]
|
58
|
+
post[:type] = post_type if post_type
|
59
|
+
end
|
60
|
+
|
61
|
+
def headers(options = {})
|
62
|
+
super.tap do |headers|
|
63
|
+
headers['User-Agent'] = "Shift4/v2 ActiveMerchantBindings/#{ActiveMerchant::VERSION}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def scrub(transcript)
|
68
|
+
super.
|
69
|
+
gsub(%r((card\[expMonth\]=)\d+), '\1[FILTERED]').
|
70
|
+
gsub(%r((card\[expYear\]=)\d+), '\1[FILTERED]').
|
71
|
+
gsub(%r((card\[cardholderName\]=)\w+[^ ]\w+), '\1[FILTERED]')
|
72
|
+
end
|
73
|
+
|
74
|
+
def json_error(raw_response)
|
75
|
+
super(raw_response, 'Shift4 V2')
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_amount(post, money, options, include_currency = false)
|
79
|
+
super
|
80
|
+
post[:currency]&.upcase!
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_creditcard(post, payment_method, options)
|
84
|
+
return super unless payment_method.is_a?(Check)
|
85
|
+
|
86
|
+
post[:paymentMethod] = bank_account_object(payment_method, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def bank_account_object(payment_method, options)
|
90
|
+
{
|
91
|
+
type: :ach,
|
92
|
+
fraudCheckData: {
|
93
|
+
ipAddress: options[:ip],
|
94
|
+
email: options[:email]
|
95
|
+
}.compact,
|
96
|
+
billing: {
|
97
|
+
name: payment_method.name,
|
98
|
+
address: { country: options.dig(:billing_address, :country) }
|
99
|
+
}.compact,
|
100
|
+
ach: {
|
101
|
+
account: {
|
102
|
+
routingNumber: payment_method.routing_number,
|
103
|
+
accountNumber: payment_method.account_number,
|
104
|
+
accountType: get_account_type(payment_method)
|
105
|
+
},
|
106
|
+
verificationProvider: :external
|
107
|
+
}
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_account_type(check)
|
112
|
+
holder = (check.account_holder_type || '').match(/business/i) ? :corporate : :personal
|
113
|
+
"#{holder}_#{check.account_type}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -44,7 +44,7 @@ module ActiveMerchant #:nodoc:
|
|
44
44
|
def initialize(options = {})
|
45
45
|
requires!(options, :client_id, :client_secret)
|
46
46
|
super
|
47
|
-
@access_token = {}
|
47
|
+
@access_token = options[:access_token] || {}
|
48
48
|
sign_access_token()
|
49
49
|
end
|
50
50
|
|
@@ -280,12 +280,12 @@ module ActiveMerchant #:nodoc:
|
|
280
280
|
def commit(action, parameters, url_params = {})
|
281
281
|
begin
|
282
282
|
response = JSON.parse ssl_post(url(action, url_params), post_data(parameters), authorized_headers())
|
283
|
-
rescue ResponseError =>
|
284
|
-
case
|
283
|
+
rescue ResponseError => e
|
284
|
+
case e.response.code.to_i
|
285
285
|
when 400...499
|
286
|
-
response = JSON.parse
|
286
|
+
response = JSON.parse e.response.body
|
287
287
|
else
|
288
|
-
raise
|
288
|
+
raise e
|
289
289
|
end
|
290
290
|
end
|
291
291
|
|
@@ -318,7 +318,7 @@ module ActiveMerchant #:nodoc:
|
|
318
318
|
end
|
319
319
|
|
320
320
|
def url(action, url_params)
|
321
|
-
"#{
|
321
|
+
"#{test? ? test_url : live_url}/#{url_params[:token_acquirer]}/#{action}"
|
322
322
|
end
|
323
323
|
|
324
324
|
def post_data(data = {})
|
@@ -356,12 +356,18 @@ module ActiveMerchant #:nodoc:
|
|
356
356
|
login_info[:client_secret] = @options[:client_secret]
|
357
357
|
login_info[:audience] = test? ? test_audience : live_audience
|
358
358
|
login_info[:grant_type] = 'client_credentials'
|
359
|
-
response = parse(ssl_post(auth_url(), login_info.to_json, {
|
360
|
-
'content-Type' => 'application/json'
|
361
|
-
}))
|
362
359
|
|
363
|
-
|
364
|
-
|
360
|
+
begin
|
361
|
+
raw_response = ssl_post(auth_url(), login_info.to_json, {
|
362
|
+
'content-Type' => 'application/json'
|
363
|
+
})
|
364
|
+
rescue ResponseError => e
|
365
|
+
raise OAuthResponseError.new(e)
|
366
|
+
else
|
367
|
+
response = parse(raw_response)
|
368
|
+
@access_token[:access_token] = response['access_token']
|
369
|
+
@access_token[:expires_at] = Time.new.to_i + response['expires_in']
|
370
|
+
end
|
365
371
|
end
|
366
372
|
end
|
367
373
|
end
|
@@ -263,11 +263,15 @@ module ActiveMerchant #:nodoc:
|
|
263
263
|
response = parse(ssl_post(url_for(action), post_data(action, money, parameters)), action)
|
264
264
|
|
265
265
|
# Pass along the original transaction id in the case an update transaction
|
266
|
-
Response.new(
|
266
|
+
Response.new(
|
267
|
+
response[:success],
|
268
|
+
message_from(response, action),
|
269
|
+
response,
|
267
270
|
test: test?,
|
268
271
|
authorization: response[:szTransactionFileName] || parameters[:szTransactionId],
|
269
272
|
avs_result: { code: response[:szAVSResponseCode] },
|
270
|
-
cvv_result: response[:szCVV2ResponseCode]
|
273
|
+
cvv_result: response[:szCVV2ResponseCode]
|
274
|
+
)
|
271
275
|
end
|
272
276
|
|
273
277
|
def url_for(action)
|
@@ -226,11 +226,15 @@ module ActiveMerchant #:nodoc:
|
|
226
226
|
def commit(action, money, parameters)
|
227
227
|
parameters[:amount] = localized_amount(money, parameters[:currency] || default_currency) if money
|
228
228
|
response = parse(ssl_post(self.live_url, post_data(action, parameters)))
|
229
|
-
Response.new(
|
229
|
+
Response.new(
|
230
|
+
response['response'] == '1',
|
231
|
+
message_from(response),
|
232
|
+
response,
|
230
233
|
authorization: (response['transactionid'] || response['customer_vault_id']),
|
231
234
|
test: test?,
|
232
235
|
cvv_result: response['cvvresponse'],
|
233
|
-
avs_result: { code: response['avsresponse'] }
|
236
|
+
avs_result: { code: response['avsresponse'] }
|
237
|
+
)
|
234
238
|
end
|
235
239
|
|
236
240
|
def expdate(creditcard)
|
@@ -257,8 +261,7 @@ module ActiveMerchant #:nodoc:
|
|
257
261
|
post[:password] = @options[:password]
|
258
262
|
post[:type] = action if action
|
259
263
|
|
260
|
-
|
261
|
-
request
|
264
|
+
post.merge(parameters).map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
|
262
265
|
end
|
263
266
|
|
264
267
|
def determine_funding_source(source)
|