activemerchant 1.133.0 → 1.137.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 +240 -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 +11 -8
- data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
- data/lib/active_merchant/billing/gateway.rb +9 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
- 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 +43 -35
- 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/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 +238 -34
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
- data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
- data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
- 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 +9 -5
- 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 +72 -12
- 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 +8 -3
- 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 +18 -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 +2 -2
- 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 +2 -10
- 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 +36 -16
- 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 +53 -21
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
- 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 +3 -3
- 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 +140 -73
- 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)
|