activemerchant 1.120.0 → 1.125.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +227 -1
  3. data/README.md +1 -1
  4. data/lib/active_merchant/billing/check.rb +13 -19
  5. data/lib/active_merchant/billing/credit_card.rb +13 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +24 -12
  8. data/lib/active_merchant/billing/gateway.rb +1 -1
  9. data/lib/active_merchant/billing/gateways/adyen.rb +81 -26
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +9 -5
  14. data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
  15. data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
  16. data/lib/active_merchant/billing/gateways/checkout_v2.rb +43 -4
  17. data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
  18. data/lib/active_merchant/billing/gateways/cyber_source.rb +41 -6
  19. data/lib/active_merchant/billing/gateways/d_local.rb +12 -6
  20. data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
  21. data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
  22. data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
  23. data/lib/active_merchant/billing/gateways/elavon.rb +65 -30
  24. data/lib/active_merchant/billing/gateways/element.rb +22 -2
  25. data/lib/active_merchant/billing/gateways/global_collect.rb +130 -26
  26. data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
  27. data/lib/active_merchant/billing/gateways/kushki.rb +30 -0
  28. data/lib/active_merchant/billing/gateways/mercado_pago.rb +6 -3
  29. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  30. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  31. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  32. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  33. data/lib/active_merchant/billing/gateways/mundipagg.rb +22 -11
  34. data/lib/active_merchant/billing/gateways/nmi.rb +29 -10
  35. data/lib/active_merchant/billing/gateways/orbital.rb +55 -9
  36. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  37. data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
  38. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  39. data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
  40. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  41. data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
  42. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  43. data/lib/active_merchant/billing/gateways/paymentez.rb +14 -2
  44. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  45. data/lib/active_merchant/billing/gateways/paysafe.rb +412 -0
  46. data/lib/active_merchant/billing/gateways/payu_latam.rb +9 -4
  47. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  48. data/lib/active_merchant/billing/gateways/pin.rb +31 -4
  49. data/lib/active_merchant/billing/gateways/priority.rb +347 -0
  50. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  51. data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
  52. data/lib/active_merchant/billing/gateways/safe_charge.rb +8 -2
  53. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  54. data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
  55. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +115 -39
  56. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  57. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  58. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +21 -7
  59. data/lib/active_merchant/billing/gateways/vpos.rb +58 -10
  60. data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
  61. data/lib/active_merchant/billing/gateways/worldpay.rb +226 -62
  62. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  63. data/lib/active_merchant/billing/response.rb +4 -0
  64. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  65. data/lib/active_merchant/billing.rb +1 -0
  66. data/lib/active_merchant/version.rb +1 -1
  67. metadata +13 -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.net
8
+ # gateway please go to http://www.monei.com
9
9
  #
10
10
  # === Setup
11
- # In order to set-up the gateway you need four paramaters: sender_id, channel_id, login and pwd.
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://test.monei-api.net/payment/ctpe'
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 = 'http://www.monei.net/'
22
- self.display_name = 'Monei'
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
- # :sender_id Sender ID
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, :sender_id, :channel_id, :login, :pwd)
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
- # credit_card - Credit card
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, credit_card, options = {})
49
- execute_new_order(:purchase, money, credit_card, options)
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
- # credit_card - Credit card
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, credit_card, options = {})
64
- execute_new_order(:authorize, money, credit_card, options)
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
- # credit_card - Credit card
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(credit_card, options = {})
117
+ def verify(payment_method, options = {})
121
118
  MultiResponse.run(:use_first_response) do |r|
122
- r.process { authorize(100, credit_card, options) }
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, credit_card, options)
131
- request = build_request do |xml|
132
- add_identification_new_order(xml, options)
133
- add_payment(xml, action, money, options)
134
- add_account(xml, credit_card)
135
- add_customer(xml, credit_card, options)
136
- add_three_d_secure(xml, options)
137
- end
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 do |xml|
145
- add_identification_authorization(xml, authorization, options)
146
- add_payment(xml, action, money, options)
147
- end
156
+ request = build_request
148
157
 
149
- commit(request)
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 XML wrapping code yielding to code to fill the transaction information
164
+ # Private: Build request object
153
165
  def build_request
154
- builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
155
- xml.Request(version: '1.0') do
156
- xml.Header { xml.Security(sender: @options[:sender_id]) }
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 XML for new orders
167
- def add_identification_new_order(xml, options)
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
- xml.Identification do
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 XML for orders that depend on authorization from previous operation
175
- def add_identification_authorization(xml, authorization, options)
176
- xml.Identification do
177
- xml.ReferenceID authorization
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 XML
183
- def add_payment(xml, action, money, options)
184
- code = tanslate_payment_code(action)
185
-
186
- xml.Payment(code: code) do
187
- xml.Presentation do
188
- xml.Amount amount(money)
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 account part to XML
196
- def add_account(xml, credit_card)
197
- xml.Account do
198
- xml.Holder credit_card.name
199
- xml.Number credit_card.number
200
- xml.Brand credit_card.brand.upcase
201
- xml.Expiry(month: credit_card.month, year: credit_card.year)
202
- xml.Verification credit_card.verification_value
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 XML
207
- def add_customer(xml, credit_card, options)
208
- requires!(options, :billing_address)
209
- address = options[:billing_address]
210
- xml.Customer do
211
- xml.Name do
212
- xml.Given credit_card.first_name
213
- xml.Family credit_card.last_name
214
- end
215
- xml.Address do
216
- xml.Street address[:address1].to_s
217
- xml.Zip address[:zip].to_s
218
- xml.City address[:city].to_s
219
- xml.State address[:state].to_s if address.has_key? :state
220
- xml.Country address[:country].to_s
221
- end
222
- xml.Contact do
223
- xml.Email options[:email] || 'noemail@monei.net'
224
- xml.Ip options[:ip] || '0.0.0.0'
225
- end
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 : Add the 3DSecure infos to XML
249
- def add_three_d_secure(xml, options)
250
- if options[:three_d_secure]
251
- xml.Authentication(type: '3DSecure') do
252
- xml.ResultIndicator eci_to_result_indicator options[:three_d_secure][:eci]
253
- xml.Parameter(name: 'VERIFICATION_ID') { xml.text options[:three_d_secure][:cavv] }
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
- # Private: Parse XML response from Monei servers
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
- xml = Nokogiri::XML(body)
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
- unique_id: xml.xpath('//Response/Transaction/Identification/UniqueID').text,
264
- status: translate_status_code(xml.xpath('//Response/Transaction/Processing/Status/@code').text),
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
- # Private: Send XML transaction to Monei servers and create AM response
271
- def commit(xml)
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 = parse(ssl_post(url, post_data(xml), 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'))
342
+ response = api_request(url + endpoint, params(request, action), headers)
343
+ success = success_from(response)
275
344
 
276
345
  Response.new(
277
- success_from(response),
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
- response[:status] == :success || response[:status] == :new
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[:message]
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
- success_from(response) ? nil : STANDARD_ERROR_CODE[:card_declined]
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
- response[:unique_id]
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(xml)
308
- "load=#{CGI.escape(xml)}"
387
+ def post_data(params)
388
+ params.clone.to_json
309
389
  end
310
390
 
311
- # Private: Translate Monei status code to native ruby symbols
312
- def translate_status_code(code)
313
- {
314
- '00' => :success,
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 tanslate_payment_code(action)
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: 'CC.DB',
330
- authorize: 'CC.PA',
331
- capture: 'CC.CP',
332
- refund: 'CC.RF',
333
- void: 'CC.RV'
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 headers
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("#{@options[:api_key]}:"),
242
+ 'Authorization' => 'Basic ' + Base64.strict_encode64("#{basic_token}:"),
235
243
  'Content-Type' => 'application/json',
236
244
  'Accept' => 'application/json'
237
245
  }
@@ -259,22 +267,23 @@ 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(
270
- success_from(response),
279
+ success_from(response, action),
271
280
  message_from(response),
272
281
  response,
273
282
  authorization: authorization_from(response, action),
274
283
  avs_result: AVSResult.new(code: response['some_avs_response_key']),
275
284
  cvv_result: CVVResult.new(response['some_cvv_response_key']),
276
285
  test: test?,
277
- error_code: error_code_from(response)
286
+ error_code: error_code_from(response, action)
278
287
  )
279
288
  rescue ResponseError => e
280
289
  message = get_error_messages(e)
@@ -288,8 +297,10 @@ module ActiveMerchant #:nodoc:
288
297
  )
289
298
  end
290
299
 
291
- def success_from(response)
292
- %w[pending paid processing canceled active].include? response['status']
300
+ def success_from(response, action)
301
+ success = response.try(:[], 'last_transaction').try(:[], 'success') unless action == 'store'
302
+ success = !response.try(:[], 'id').nil? if action == 'store'
303
+ success
293
304
  end
294
305
 
295
306
  def message_from(response)
@@ -341,8 +352,8 @@ module ActiveMerchant #:nodoc:
341
352
  parameters.to_json
342
353
  end
343
354
 
344
- def error_code_from(response)
345
- return if success_from(response)
355
+ def error_code_from(response, action)
356
+ return if success_from(response, action)
346
357
  return response['last_transaction']['acquirer_return_code'] if response['last_transaction']
347
358
 
348
359
  STANDARD_ERROR_CODE[:processing_error]
@@ -206,7 +206,8 @@ module ActiveMerchant #:nodoc:
206
206
  post[:stored_credential_indicator] = 'stored'
207
207
  else
208
208
  post[:stored_credential_indicator] = 'used'
209
- post[:initial_transaction_id] = stored_credential[:network_transaction_id]
209
+ # should only send :initial_transaction_id if it is a MIT
210
+ post[:initial_transaction_id] = stored_credential[:network_transaction_id] if post[:initiated_by] == 'merchant'
210
211
  end
211
212
  end
212
213
 
@@ -236,6 +237,19 @@ module ActiveMerchant #:nodoc:
236
237
  post[:shipping_zip] = shipping_address[:zip]
237
238
  post[:shipping_phone] = shipping_address[:phone]
238
239
  end
240
+
241
+ if (descriptor = options[:descriptors])
242
+ post[:descriptor] = descriptor[:descriptor]
243
+ post[:descriptor_phone] = descriptor[:descriptor_phone]
244
+ post[:descriptor_address] = descriptor[:descriptor_address]
245
+ post[:descriptor_city] = descriptor[:descriptor_city]
246
+ post[:descriptor_state] = descriptor[:descriptor_state]
247
+ post[:descriptor_postal] = descriptor[:descriptor_postal]
248
+ post[:descriptor_country] = descriptor[:descriptor_country]
249
+ post[:descriptor_mcc] = descriptor[:descriptor_mcc]
250
+ post[:descriptor_merchant_id] = descriptor[:descriptor_merchant_id]
251
+ post[:descriptor_url] = descriptor[:descriptor_url]
252
+ end
239
253
  end
240
254
 
241
255
  def add_vendor_data(post, options)
@@ -251,15 +265,20 @@ module ActiveMerchant #:nodoc:
251
265
  end
252
266
 
253
267
  def add_three_d_secure(post, options)
254
- return unless options[:three_d_secure]
255
-
256
- if (three_d_secure = options[:three_d_secure])
257
- post[:eci] = three_d_secure[:eci]
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
268
+ three_d_secure = options[:three_d_secure]
269
+ return unless three_d_secure
270
+
271
+ post[:cardholder_auth] = cardholder_auth(three_d_secure[:authentication_response_status])
272
+ post[:cavv] = three_d_secure[:cavv]
273
+ post[:xid] = three_d_secure[:xid]
274
+ post[:three_ds_version] = three_d_secure[:version]
275
+ post[:directory_server_id] = three_d_secure[:ds_transaction_id]
276
+ end
277
+
278
+ def cardholder_auth(trans_status)
279
+ return nil if trans_status.nil?
280
+
281
+ trans_status == 'Y' ? 'verified' : 'attempted'
263
282
  end
264
283
 
265
284
  def add_reference(post, authorization)