activemerchant 1.117.0 → 1.123.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +217 -0
- data/README.md +5 -3
- data/lib/active_merchant/billing/check.rb +19 -12
- data/lib/active_merchant/billing/credit_card.rb +6 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +96 -22
- data/lib/active_merchant/billing/gateways/adyen.rb +38 -21
- data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +4 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -3
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -8
- data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +31 -0
- data/lib/active_merchant/billing/gateways/credorax.rb +16 -9
- data/lib/active_merchant/billing/gateways/cyber_source.rb +67 -9
- data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
- data/lib/active_merchant/billing/gateways/decidir.rb +29 -3
- data/lib/active_merchant/billing/gateways/elavon.rb +110 -26
- data/lib/active_merchant/billing/gateways/element.rb +2 -0
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +13 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +17 -6
- data/lib/active_merchant/billing/gateways/forte.rb +12 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +25 -16
- data/lib/active_merchant/billing/gateways/hps.rb +65 -2
- data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
- data/lib/active_merchant/billing/gateways/litle.rb +9 -4
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
- data/lib/active_merchant/billing/gateways/moka.rb +277 -0
- data/lib/active_merchant/billing/gateways/monei.rb +228 -144
- data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
- data/lib/active_merchant/billing/gateways/netbanx.rb +37 -2
- data/lib/active_merchant/billing/gateways/nmi.rb +14 -9
- data/lib/active_merchant/billing/gateways/orbital.rb +202 -47
- data/lib/active_merchant/billing/gateways/pay_arc.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +57 -11
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +9 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +10 -5
- data/lib/active_merchant/billing/gateways/paymentez.rb +26 -1
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +10 -2
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +291 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
- data/lib/active_merchant/billing/gateways/pin.rb +11 -0
- data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
- data/lib/active_merchant/billing/gateways/redsys.rb +78 -30
- data/lib/active_merchant/billing/gateways/safe_charge.rb +19 -8
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -8
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +86 -25
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
- data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +68 -20
- data/lib/active_merchant/billing/response.rb +2 -1
- data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- data/lib/certs/cacert.pem +1582 -2431
- metadata +10 -3
@@ -5,39 +5,36 @@ module ActiveMerchant #:nodoc:
|
|
5
5
|
#
|
6
6
|
# == Monei gateway
|
7
7
|
# This class implements Monei gateway for Active Merchant. For more information about Monei
|
8
|
-
# gateway please go to http://www.monei.
|
8
|
+
# gateway please go to http://www.monei.com
|
9
9
|
#
|
10
10
|
# === Setup
|
11
|
-
# In order to set-up the gateway you need
|
11
|
+
# In order to set-up the gateway you need only one paramater: the api_key
|
12
12
|
# Request that data to Monei.
|
13
13
|
class MoneiGateway < Gateway
|
14
|
-
self.test_url = 'https://
|
15
|
-
self.live_url = 'https://monei-api.net/payment/ctpe'
|
14
|
+
self.live_url = self.test_url = 'https://api.monei.com/v1/payments'
|
16
15
|
|
17
16
|
self.supported_countries = %w[AD AT BE BG CA CH CY CZ DE DK EE ES FI FO FR GB GI GR HU IE IL IS IT LI LT LU LV MT NL NO PL PT RO SE SI SK TR US VA]
|
18
17
|
self.default_currency = 'EUR'
|
18
|
+
self.money_format = :cents
|
19
19
|
self.supported_cardtypes = %i[visa master maestro jcb american_express]
|
20
20
|
|
21
|
-
self.homepage_url = '
|
22
|
-
self.display_name = '
|
21
|
+
self.homepage_url = 'https://monei.com/'
|
22
|
+
self.display_name = 'MONEI'
|
23
23
|
|
24
24
|
# Constructor
|
25
25
|
#
|
26
26
|
# options - Hash containing the gateway credentials, ALL MANDATORY
|
27
|
-
# :
|
28
|
-
# :channel_id Channel ID
|
29
|
-
# :login User login
|
30
|
-
# :pwd User password
|
27
|
+
# :api_key Account's API KEY
|
31
28
|
#
|
32
29
|
def initialize(options = {})
|
33
|
-
requires!(options, :
|
30
|
+
requires!(options, :api_key)
|
34
31
|
super
|
35
32
|
end
|
36
33
|
|
37
34
|
# Public: Performs purchase operation
|
38
35
|
#
|
39
36
|
# money - Amount of purchase
|
40
|
-
#
|
37
|
+
# payment_method - Credit card
|
41
38
|
# options - Hash containing purchase options
|
42
39
|
# :order_id Merchant created id for the purchase
|
43
40
|
# :billing_address Hash with billing address information
|
@@ -45,14 +42,14 @@ module ActiveMerchant #:nodoc:
|
|
45
42
|
# :currency Sale currency to override money object or default (optional)
|
46
43
|
#
|
47
44
|
# Returns Active Merchant response object
|
48
|
-
def purchase(money,
|
49
|
-
execute_new_order(:purchase, money,
|
45
|
+
def purchase(money, payment_method, options = {})
|
46
|
+
execute_new_order(:purchase, money, payment_method, options)
|
50
47
|
end
|
51
48
|
|
52
49
|
# Public: Performs authorization operation
|
53
50
|
#
|
54
51
|
# money - Amount to authorize
|
55
|
-
#
|
52
|
+
# payment_method - Credit card
|
56
53
|
# options - Hash containing authorization options
|
57
54
|
# :order_id Merchant created id for the authorization
|
58
55
|
# :billing_address Hash with billing address information
|
@@ -60,8 +57,8 @@ module ActiveMerchant #:nodoc:
|
|
60
57
|
# :currency Sale currency to override money object or default (optional)
|
61
58
|
#
|
62
59
|
# Returns Active Merchant response object
|
63
|
-
def authorize(money,
|
64
|
-
execute_new_order(:authorize, money,
|
60
|
+
def authorize(money, payment_method, options = {})
|
61
|
+
execute_new_order(:authorize, money, payment_method, options)
|
65
62
|
end
|
66
63
|
|
67
64
|
# Public: Performs capture operation on previous authorization
|
@@ -109,7 +106,7 @@ module ActiveMerchant #:nodoc:
|
|
109
106
|
|
110
107
|
# Public: Verifies credit card. Does this by doing a authorization of 1.00 Euro and then voiding it.
|
111
108
|
#
|
112
|
-
#
|
109
|
+
# payment_method - Credit card
|
113
110
|
# options - Hash containing authorization options
|
114
111
|
# :order_id Merchant created id for the authorization
|
115
112
|
# :billing_address Hash with billing address information
|
@@ -117,113 +114,122 @@ module ActiveMerchant #:nodoc:
|
|
117
114
|
# :currency Sale currency to override money object or default (optional)
|
118
115
|
#
|
119
116
|
# Returns Active Merchant response object of Authorization operation
|
120
|
-
def verify(
|
117
|
+
def verify(payment_method, options = {})
|
121
118
|
MultiResponse.run(:use_first_response) do |r|
|
122
|
-
r.process { authorize(100,
|
119
|
+
r.process { authorize(100, payment_method, options) }
|
123
120
|
r.process(:ignore_result) { void(r.authorization, options) }
|
124
121
|
end
|
125
122
|
end
|
126
123
|
|
124
|
+
def store(payment_method, options = {})
|
125
|
+
execute_new_order(:store, 0, payment_method, options)
|
126
|
+
end
|
127
|
+
|
128
|
+
def supports_scrubbing?
|
129
|
+
true
|
130
|
+
end
|
131
|
+
|
132
|
+
def scrub(transcript)
|
133
|
+
transcript.
|
134
|
+
gsub(%r((Authorization: )\w+), '\1[FILTERED]').
|
135
|
+
gsub(%r(("number\\?":\\?")[^"]*)i, '\1[FILTERED]').
|
136
|
+
gsub(%r(("cvc\\?":\\?")[^"]*)i, '\1[FILTERED]').
|
137
|
+
gsub(%r(("cavv\\?":\\?")[^"]*)i, '\1[FILTERED]')
|
138
|
+
end
|
139
|
+
|
127
140
|
private
|
128
141
|
|
129
142
|
# Private: Execute purchase or authorize operation
|
130
|
-
def execute_new_order(action, money,
|
131
|
-
request = build_request
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
commit(request)
|
143
|
+
def execute_new_order(action, money, payment_method, options)
|
144
|
+
request = build_request
|
145
|
+
add_identification_new_order(request, options)
|
146
|
+
add_transaction(request, action, money, options)
|
147
|
+
add_payment(request, payment_method)
|
148
|
+
add_customer(request, payment_method, options)
|
149
|
+
add_3ds_authenticated_data(request, options)
|
150
|
+
add_browser_info(request, options)
|
151
|
+
commit(request, action, options)
|
140
152
|
end
|
141
153
|
|
142
154
|
# Private: Execute operation that depends on authorization code from previous purchase or authorize operation
|
143
155
|
def execute_dependant(action, money, authorization, options)
|
144
|
-
request = build_request
|
145
|
-
add_identification_authorization(xml, authorization, options)
|
146
|
-
add_payment(xml, action, money, options)
|
147
|
-
end
|
156
|
+
request = build_request
|
148
157
|
|
149
|
-
|
158
|
+
add_identification_authorization(request, authorization, options)
|
159
|
+
add_transaction(request, action, money, options)
|
160
|
+
|
161
|
+
commit(request, action, options)
|
150
162
|
end
|
151
163
|
|
152
|
-
# Private: Build
|
164
|
+
# Private: Build request object
|
153
165
|
def build_request
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
xml.Transaction(mode: test? ? 'CONNECTOR_TEST' : 'LIVE', response: 'SYNC', channel: @options[:channel_id]) do
|
158
|
-
xml.User(login: @options[:login], pwd: @options[:pwd])
|
159
|
-
yield xml
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
builder.to_xml
|
166
|
+
request = {}
|
167
|
+
request[:livemode] = test? ? 'false' : 'true'
|
168
|
+
request
|
164
169
|
end
|
165
170
|
|
166
|
-
# Private: Add identification part to
|
167
|
-
def add_identification_new_order(
|
171
|
+
# Private: Add identification part to request for new orders
|
172
|
+
def add_identification_new_order(request, options)
|
168
173
|
requires!(options, :order_id)
|
169
|
-
|
170
|
-
xml.TransactionID options[:order_id]
|
171
|
-
end
|
174
|
+
request[:orderId] = options[:order_id]
|
172
175
|
end
|
173
176
|
|
174
|
-
# Private: Add identification part to
|
175
|
-
def add_identification_authorization(
|
176
|
-
|
177
|
-
|
178
|
-
xml.TransactionID options[:order_id]
|
179
|
-
end
|
177
|
+
# Private: Add identification part to request for orders that depend on authorization from previous operation
|
178
|
+
def add_identification_authorization(request, authorization, options)
|
179
|
+
options[:paymentId] = authorization
|
180
|
+
request[:orderId] = options[:order_id] if options[:order_id]
|
180
181
|
end
|
181
182
|
|
182
|
-
# Private: Add payment part to
|
183
|
-
def
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
xml.Currency options[:currency] || currency(money)
|
190
|
-
xml.Usage options[:description] || options[:order_id]
|
191
|
-
end unless money.nil?
|
183
|
+
# Private: Add payment part to request
|
184
|
+
def add_transaction(request, action, money, options)
|
185
|
+
request[:transactionType] = translate_payment_code(action)
|
186
|
+
request[:description] = options[:description] || options[:order_id]
|
187
|
+
unless money.nil?
|
188
|
+
request[:amount] = amount(money).to_i
|
189
|
+
request[:currency] = options[:currency] || currency(money)
|
192
190
|
end
|
193
191
|
end
|
194
192
|
|
195
|
-
# Private: Add
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
193
|
+
# Private: Add payment method to request
|
194
|
+
def add_payment(request, payment_method)
|
195
|
+
if payment_method.is_a? String
|
196
|
+
request[:paymentToken] = payment_method
|
197
|
+
else
|
198
|
+
request[:paymentMethod] = {}
|
199
|
+
request[:paymentMethod][:card] = {}
|
200
|
+
request[:paymentMethod][:card][:number] = payment_method.number
|
201
|
+
request[:paymentMethod][:card][:expMonth] = format(payment_method.month, :two_digits)
|
202
|
+
request[:paymentMethod][:card][:expYear] = format(payment_method.year, :two_digits)
|
203
|
+
request[:paymentMethod][:card][:cvc] = payment_method.verification_value.to_s
|
203
204
|
end
|
204
205
|
end
|
205
206
|
|
206
|
-
# Private: Add customer part to
|
207
|
-
def add_customer(
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
207
|
+
# Private: Add customer part to request
|
208
|
+
def add_customer(request, payment_method, options)
|
209
|
+
address = options[:billing_address] || options[:address]
|
210
|
+
|
211
|
+
request[:customer] = {}
|
212
|
+
request[:customer][:email] = options[:email] || 'support@monei.net'
|
213
|
+
|
214
|
+
if address
|
215
|
+
request[:customer][:name] = address[:name].to_s if address[:name]
|
216
|
+
|
217
|
+
request[:billingDetails] = {}
|
218
|
+
request[:billingDetails][:email] = options[:email] if options[:email]
|
219
|
+
request[:billingDetails][:name] = address[:name] if address[:name]
|
220
|
+
request[:billingDetails][:company] = address[:company] if address[:company]
|
221
|
+
request[:billingDetails][:phone] = address[:phone] if address[:phone]
|
222
|
+
request[:billingDetails][:address] = {}
|
223
|
+
request[:billingDetails][:address][:line1] = address[:address1] if address[:address1]
|
224
|
+
request[:billingDetails][:address][:line2] = address[:address2] if address[:address2]
|
225
|
+
request[:billingDetails][:address][:city] = address[:city] if address[:city]
|
226
|
+
request[:billingDetails][:address][:state] = address[:state] if address[:state].present?
|
227
|
+
request[:billingDetails][:address][:zip] = address[:zip].to_s if address[:zip]
|
228
|
+
request[:billingDetails][:address][:country] = address[:country] if address[:country]
|
226
229
|
end
|
230
|
+
|
231
|
+
request[:sessionDetails] = {}
|
232
|
+
request[:sessionDetails][:ip] = options[:ip] if options[:ip]
|
227
233
|
end
|
228
234
|
|
229
235
|
# Private : Convert ECI to ResultIndicator
|
@@ -245,92 +251,170 @@ module ActiveMerchant #:nodoc:
|
|
245
251
|
end
|
246
252
|
end
|
247
253
|
|
248
|
-
# Private
|
249
|
-
def
|
250
|
-
if options[:three_d_secure]
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
xml.Parameter(name: 'XID') { xml.text options[:three_d_secure][:xid] }
|
255
|
-
end
|
254
|
+
# Private: add the already validated 3DSecure info to request
|
255
|
+
def add_3ds_authenticated_data(request, options)
|
256
|
+
if options[:three_d_secure] && options[:three_d_secure][:eci] && options[:three_d_secure][:xid]
|
257
|
+
add_3ds1_authenticated_data(request, options)
|
258
|
+
elsif options[:three_d_secure]
|
259
|
+
add_3ds2_authenticated_data(request, options)
|
256
260
|
end
|
257
261
|
end
|
258
262
|
|
259
|
-
|
263
|
+
def add_3ds1_authenticated_data(request, options)
|
264
|
+
three_d_secure_options = options[:three_d_secure]
|
265
|
+
request[:paymentMethod][:card][:auth] = {
|
266
|
+
cavv: three_d_secure_options[:cavv],
|
267
|
+
cavvAlgorithm: three_d_secure_options[:cavv_algorithm],
|
268
|
+
eci: three_d_secure_options[:eci],
|
269
|
+
xid: three_d_secure_options[:xid],
|
270
|
+
directoryResponse: three_d_secure_options[:enrolled],
|
271
|
+
authenticationResponse: three_d_secure_options[:authentication_response_status]
|
272
|
+
}
|
273
|
+
end
|
274
|
+
|
275
|
+
def add_3ds2_authenticated_data(request, options)
|
276
|
+
three_d_secure_options = options[:three_d_secure]
|
277
|
+
# If the transaction was authenticated in a frictionless flow, send the transStatus from the ARes.
|
278
|
+
if three_d_secure_options[:authentication_response_status].nil?
|
279
|
+
authentication_response = three_d_secure_options[:directory_response_status]
|
280
|
+
else
|
281
|
+
authentication_response = three_d_secure_options[:authentication_response_status]
|
282
|
+
end
|
283
|
+
request[:paymentMethod][:card][:auth] = {
|
284
|
+
threeDSVersion: three_d_secure_options[:version],
|
285
|
+
eci: three_d_secure_options[:eci],
|
286
|
+
cavv: three_d_secure_options[:cavv],
|
287
|
+
dsTransID: three_d_secure_options[:ds_transaction_id],
|
288
|
+
directoryResponse: three_d_secure_options[:directory_response_status],
|
289
|
+
authenticationResponse: authentication_response
|
290
|
+
}
|
291
|
+
end
|
292
|
+
|
293
|
+
def add_browser_info(request, options)
|
294
|
+
request[:sessionDetails][:ip] = options[:ip] if options[:ip]
|
295
|
+
request[:sessionDetails][:userAgent] = options[:user_agent] if options[:user_agent]
|
296
|
+
end
|
297
|
+
|
298
|
+
# Private: Parse JSON response from Monei servers
|
260
299
|
def parse(body)
|
261
|
-
|
300
|
+
JSON.parse(body)
|
301
|
+
end
|
302
|
+
|
303
|
+
def json_error(raw_response)
|
304
|
+
msg = 'Invalid response received from the MONEI API. Please contact support@monei.net if you continue to receive this message.'
|
305
|
+
msg += " (The raw response returned by the API was #{raw_response.inspect})"
|
262
306
|
{
|
263
|
-
|
264
|
-
|
265
|
-
reason: translate_status_code(xml.xpath('//Response/Transaction/Processing/Reason/@code').text),
|
266
|
-
message: xml.xpath('//Response/Transaction/Processing/Return').text
|
307
|
+
'status' => 'error',
|
308
|
+
'message' => msg
|
267
309
|
}
|
268
310
|
end
|
269
311
|
|
270
|
-
|
271
|
-
|
312
|
+
def response_error(raw_response)
|
313
|
+
parse(raw_response)
|
314
|
+
rescue JSON::ParserError
|
315
|
+
json_error(raw_response)
|
316
|
+
end
|
317
|
+
|
318
|
+
def api_request(url, parameters, options = {})
|
319
|
+
raw_response = response = nil
|
320
|
+
begin
|
321
|
+
raw_response = ssl_post(url, post_data(parameters), options)
|
322
|
+
response = parse(raw_response)
|
323
|
+
rescue ResponseError => e
|
324
|
+
raw_response = e.response.body
|
325
|
+
response = response_error(raw_response)
|
326
|
+
rescue JSON::ParserError
|
327
|
+
response = json_error(raw_response)
|
328
|
+
end
|
329
|
+
response
|
330
|
+
end
|
331
|
+
|
332
|
+
# Private: Send transaction to Monei servers and create AM response
|
333
|
+
def commit(request, action, options)
|
272
334
|
url = (test? ? test_url : live_url)
|
335
|
+
endpoint = translate_action_endpoint(action, options)
|
336
|
+
headers = {
|
337
|
+
'Content-Type': 'application/json;charset=UTF-8',
|
338
|
+
'Authorization': @options[:api_key],
|
339
|
+
'User-Agent': 'MONEI/Shopify/0.1.0'
|
340
|
+
}
|
273
341
|
|
274
|
-
response =
|
342
|
+
response = api_request(url + endpoint, params(request, action), headers)
|
343
|
+
success = success_from(response)
|
275
344
|
|
276
345
|
Response.new(
|
277
|
-
|
278
|
-
message_from(response),
|
346
|
+
success,
|
347
|
+
message_from(response, success),
|
279
348
|
response,
|
280
|
-
authorization: authorization_from(response),
|
349
|
+
authorization: authorization_from(response, action),
|
281
350
|
test: test?,
|
282
|
-
error_code: error_code_from(response)
|
351
|
+
error_code: error_code_from(response, success)
|
283
352
|
)
|
284
353
|
end
|
285
354
|
|
286
355
|
# Private: Decide success from servers response
|
287
356
|
def success_from(response)
|
288
|
-
|
357
|
+
%w[
|
358
|
+
SUCCEEDED
|
359
|
+
AUTHORIZED
|
360
|
+
REFUNDED
|
361
|
+
PARTIALLY_REFUNDED
|
362
|
+
CANCELED
|
363
|
+
].include? response['status']
|
289
364
|
end
|
290
365
|
|
291
366
|
# Private: Get message from servers response
|
292
|
-
def message_from(response)
|
293
|
-
response
|
367
|
+
def message_from(response, success)
|
368
|
+
success ? 'Transaction approved' : response.fetch('statusMessage', response.fetch('message', 'No error details'))
|
294
369
|
end
|
295
370
|
|
296
371
|
# Private: Get error code from servers response
|
297
|
-
def error_code_from(response)
|
298
|
-
|
372
|
+
def error_code_from(response, success)
|
373
|
+
success ? nil : STANDARD_ERROR_CODE[:card_declined]
|
299
374
|
end
|
300
375
|
|
301
376
|
# Private: Get authorization code from servers response
|
302
|
-
def authorization_from(response)
|
303
|
-
|
377
|
+
def authorization_from(response, action)
|
378
|
+
case action
|
379
|
+
when :store
|
380
|
+
return response['paymentToken']
|
381
|
+
else
|
382
|
+
return response['id']
|
383
|
+
end
|
304
384
|
end
|
305
385
|
|
306
386
|
# Private: Encode POST parameters
|
307
|
-
def post_data(
|
308
|
-
|
387
|
+
def post_data(params)
|
388
|
+
params.clone.to_json
|
309
389
|
end
|
310
390
|
|
311
|
-
# Private:
|
312
|
-
def
|
313
|
-
|
314
|
-
|
315
|
-
'40' => :neutral,
|
316
|
-
'59' => :waiting_bank,
|
317
|
-
'60' => :rejected_bank,
|
318
|
-
'64' => :waiting_risk,
|
319
|
-
'65' => :rejected_risk,
|
320
|
-
'70' => :rejected_validation,
|
321
|
-
'80' => :waiting,
|
322
|
-
'90' => :new
|
323
|
-
}[code]
|
391
|
+
# Private: generate request params depending on action
|
392
|
+
def params(request, action)
|
393
|
+
request[:generatePaymentToken] = true if action == :store
|
394
|
+
request
|
324
395
|
end
|
325
396
|
|
326
397
|
# Private: Translate AM operations to Monei operations codes
|
327
|
-
def
|
398
|
+
def translate_payment_code(action)
|
399
|
+
{
|
400
|
+
purchase: 'SALE',
|
401
|
+
store: 'SALE',
|
402
|
+
authorize: 'AUTH',
|
403
|
+
capture: 'CAPTURE',
|
404
|
+
refund: 'REFUND',
|
405
|
+
void: 'CANCEL'
|
406
|
+
}[action]
|
407
|
+
end
|
408
|
+
|
409
|
+
# Private: Translate AM operations to Monei endpoints
|
410
|
+
def translate_action_endpoint(action, options)
|
328
411
|
{
|
329
|
-
purchase: '
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
412
|
+
purchase: '',
|
413
|
+
store: '',
|
414
|
+
authorize: '',
|
415
|
+
capture: "/#{options[:paymentId]}/capture",
|
416
|
+
refund: "/#{options[:paymentId]}/refund",
|
417
|
+
void: "/#{options[:paymentId]}/cancel"
|
334
418
|
}[action]
|
335
419
|
end
|
336
420
|
end
|
@@ -40,7 +40,7 @@ module ActiveMerchant #:nodoc:
|
|
40
40
|
add_shipping_address(post, options)
|
41
41
|
add_payment(post, payment, options)
|
42
42
|
add_submerchant(post, options)
|
43
|
-
|
43
|
+
add_auth_key(post, options)
|
44
44
|
commit('sale', post)
|
45
45
|
end
|
46
46
|
|
@@ -52,6 +52,7 @@ module ActiveMerchant #:nodoc:
|
|
52
52
|
add_payment(post, payment, options)
|
53
53
|
add_capture_flag(post, payment)
|
54
54
|
add_submerchant(post, options)
|
55
|
+
add_auth_key(post, options)
|
55
56
|
commit('authonly', post)
|
56
57
|
end
|
57
58
|
|
@@ -229,9 +230,16 @@ module ActiveMerchant #:nodoc:
|
|
229
230
|
end
|
230
231
|
end
|
231
232
|
|
232
|
-
def
|
233
|
+
def add_auth_key(post, options)
|
234
|
+
if authorization_secret_key = options[:authorization_secret_key]
|
235
|
+
post[:authorization_secret_key] = authorization_secret_key
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def headers(authorization_secret_key = nil)
|
240
|
+
basic_token = authorization_secret_key || @options[:api_key]
|
233
241
|
{
|
234
|
-
'Authorization' => 'Basic ' + Base64.strict_encode64("#{
|
242
|
+
'Authorization' => 'Basic ' + Base64.strict_encode64("#{basic_token}:"),
|
235
243
|
'Content-Type' => 'application/json',
|
236
244
|
'Accept' => 'application/json'
|
237
245
|
}
|
@@ -259,11 +267,12 @@ module ActiveMerchant #:nodoc:
|
|
259
267
|
|
260
268
|
def commit(action, parameters, auth = nil)
|
261
269
|
url = url_for(action, auth)
|
270
|
+
authorization_secret_key = parameters[:authorization_secret_key] if parameters
|
262
271
|
parameters.merge!(parameters[:payment][:credit_card].delete(:card)).delete(:payment) if action == 'store'
|
263
272
|
response = if %w[refund void].include? action
|
264
|
-
parse(ssl_request(:delete, url, post_data(parameters), headers))
|
273
|
+
parse(ssl_request(:delete, url, post_data(parameters), headers(authorization_secret_key)))
|
265
274
|
else
|
266
|
-
parse(ssl_post(url, post_data(parameters), headers))
|
275
|
+
parse(ssl_post(url, post_data(parameters), headers(authorization_secret_key)))
|
267
276
|
end
|
268
277
|
|
269
278
|
Response.new(
|
@@ -22,6 +22,22 @@ module ActiveMerchant #:nodoc:
|
|
22
22
|
self.homepage_url = 'https://processing.paysafe.com/'
|
23
23
|
self.display_name = 'Netbanx by PaySafe'
|
24
24
|
|
25
|
+
AVS_CODE_CONVERTER = {
|
26
|
+
'MATCH' => 'X',
|
27
|
+
'MATCH_ADDRESS_ONLY' => 'A',
|
28
|
+
'MATCH_ZIP_ONLY' => 'Z',
|
29
|
+
'NO_MATCH' => 'N',
|
30
|
+
'NOT_PROCESSED' => 'U',
|
31
|
+
'UNKNOWN' => 'Q'
|
32
|
+
}
|
33
|
+
|
34
|
+
CVV_CODE_CONVERTER = {
|
35
|
+
'MATCH' => 'M',
|
36
|
+
'NO_MATCH' => 'N',
|
37
|
+
'NOT_PROCESSED' => 'P',
|
38
|
+
'UNKNOWN' => 'U'
|
39
|
+
}
|
40
|
+
|
25
41
|
def initialize(options = {})
|
26
42
|
requires!(options, :account_number, :api_key)
|
27
43
|
super
|
@@ -36,6 +52,7 @@ module ActiveMerchant #:nodoc:
|
|
36
52
|
add_invoice(post, money, options)
|
37
53
|
add_settle_with_auth(post)
|
38
54
|
add_payment(post, payment, options)
|
55
|
+
add_customer_detail_data(post, options)
|
39
56
|
|
40
57
|
commit(:post, 'auths', post)
|
41
58
|
end
|
@@ -48,6 +65,7 @@ module ActiveMerchant #:nodoc:
|
|
48
65
|
post = {}
|
49
66
|
add_invoice(post, money, options)
|
50
67
|
add_payment(post, payment, options)
|
68
|
+
add_customer_detail_data(post, options)
|
51
69
|
|
52
70
|
commit(:post, 'auths', post)
|
53
71
|
end
|
@@ -147,6 +165,15 @@ module ActiveMerchant #:nodoc:
|
|
147
165
|
post[:locale] = options[:locale]
|
148
166
|
end
|
149
167
|
|
168
|
+
def add_customer_detail_data(post, options)
|
169
|
+
post[:profile] ||= {}
|
170
|
+
post[:profile][:email] = options[:email] if options[:email]
|
171
|
+
post[:customerIp] = options[:ip] if options[:ip]
|
172
|
+
if (billing_address = options[:billing_address])
|
173
|
+
post[:profile][:firstName], post[:profile][:lastName] = split_names(billing_address[:name])
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
150
177
|
def add_credit_card(post, credit_card, options = {})
|
151
178
|
post[:card] ||= {}
|
152
179
|
post[:card][:cardNum] = credit_card.number
|
@@ -245,11 +272,19 @@ module ActiveMerchant #:nodoc:
|
|
245
272
|
test: test?,
|
246
273
|
error_code: error_code_from(response),
|
247
274
|
authorization: authorization_from(success, get_url(uri), method, response),
|
248
|
-
avs_result:
|
249
|
-
cvv_result:
|
275
|
+
avs_result: avs_result(response),
|
276
|
+
cvv_result: cvv_result(response)
|
250
277
|
)
|
251
278
|
end
|
252
279
|
|
280
|
+
def avs_result(response)
|
281
|
+
AVSResult.new(code: AVS_CODE_CONVERTER[response['avsResponse']])
|
282
|
+
end
|
283
|
+
|
284
|
+
def cvv_result(response)
|
285
|
+
CVVResult.new(CVV_CODE_CONVERTER[response['cvvVerification']])
|
286
|
+
end
|
287
|
+
|
253
288
|
def get_url(uri)
|
254
289
|
url = (test? ? test_url : live_url)
|
255
290
|
if /^customervault/.match?(uri)
|
@@ -251,15 +251,20 @@ module ActiveMerchant #:nodoc:
|
|
251
251
|
end
|
252
252
|
|
253
253
|
def add_three_d_secure(post, options)
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
254
|
+
three_d_secure = options[:three_d_secure]
|
255
|
+
return unless three_d_secure
|
256
|
+
|
257
|
+
post[:cardholder_auth] = cardholder_auth(three_d_secure[:authentication_response_status])
|
258
|
+
post[:cavv] = three_d_secure[:cavv]
|
259
|
+
post[:xid] = three_d_secure[:xid]
|
260
|
+
post[:three_ds_version] = three_d_secure[:version]
|
261
|
+
post[:directory_server_id] = three_d_secure[:ds_transaction_id]
|
262
|
+
end
|
263
|
+
|
264
|
+
def cardholder_auth(trans_status)
|
265
|
+
return nil if trans_status.nil?
|
266
|
+
|
267
|
+
trans_status == 'Y' ? 'verified' : 'attempted'
|
263
268
|
end
|
264
269
|
|
265
270
|
def add_reference(post, authorization)
|