activemerchant 1.94.0 → 1.99.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +120 -1
  3. data/README.md +3 -0
  4. data/lib/active_merchant/billing/avs_result.rb +4 -5
  5. data/lib/active_merchant/billing/credit_card.rb +6 -0
  6. data/lib/active_merchant/billing/credit_card_methods.rb +65 -2
  7. data/lib/active_merchant/billing/gateway.rb +10 -0
  8. data/lib/active_merchant/billing/gateways/adyen.rb +119 -34
  9. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -10
  10. data/lib/active_merchant/billing/gateways/beanstream.rb +11 -6
  11. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +3 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -2
  13. data/lib/active_merchant/billing/gateways/bpoint.rb +4 -4
  14. data/lib/active_merchant/billing/gateways/braintree_blue.rb +56 -9
  15. data/lib/active_merchant/billing/gateways/card_connect.rb +2 -1
  16. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -7
  17. data/lib/active_merchant/billing/gateways/checkout_v2.rb +37 -27
  18. data/lib/active_merchant/billing/gateways/credorax.rb +69 -4
  19. data/lib/active_merchant/billing/gateways/cyber_source.rb +51 -11
  20. data/lib/active_merchant/billing/gateways/d_local.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/decidir.rb +245 -0
  22. data/lib/active_merchant/billing/gateways/epay.rb +13 -2
  23. data/lib/active_merchant/billing/gateways/eway_rapid.rb +42 -12
  24. data/lib/active_merchant/billing/gateways/fat_zebra.rb +6 -0
  25. data/lib/active_merchant/billing/gateways/global_collect.rb +3 -7
  26. data/lib/active_merchant/billing/gateways/hps.rb +46 -1
  27. data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/mastercard.rb +30 -5
  29. data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
  30. data/lib/active_merchant/billing/gateways/migs.rb +8 -0
  31. data/lib/active_merchant/billing/gateways/monei.rb +31 -0
  32. data/lib/active_merchant/billing/gateways/mundipagg.rb +33 -6
  33. data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
  34. data/lib/active_merchant/billing/gateways/nmi.rb +39 -1
  35. data/lib/active_merchant/billing/gateways/opp.rb +20 -1
  36. data/lib/active_merchant/billing/gateways/orbital.rb +60 -10
  37. data/lib/active_merchant/billing/gateways/payflow.rb +64 -14
  38. data/lib/active_merchant/billing/gateways/paymill.rb +5 -0
  39. data/lib/active_merchant/billing/gateways/paypal.rb +14 -1
  40. data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -2
  41. data/lib/active_merchant/billing/gateways/qvalent.rb +43 -1
  42. data/lib/active_merchant/billing/gateways/realex.rb +32 -9
  43. data/lib/active_merchant/billing/gateways/redsys.rb +113 -30
  44. data/lib/active_merchant/billing/gateways/spreedly_core.rb +43 -29
  45. data/lib/active_merchant/billing/gateways/stripe.rb +38 -9
  46. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +271 -0
  47. data/lib/active_merchant/billing/gateways/tns.rb +10 -5
  48. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -2
  49. data/lib/active_merchant/billing/gateways/trust_commerce.rb +45 -6
  50. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -5
  51. data/lib/active_merchant/billing/gateways/worldpay.rb +177 -39
  52. data/lib/active_merchant/country.rb +1 -0
  53. data/lib/active_merchant/version.rb +1 -1
  54. metadata +19 -4
@@ -63,6 +63,7 @@ module ActiveMerchant #:nodoc:
63
63
  add_invoice(post, options)
64
64
  add_creditcard_or_reference(post, credit_card_or_reference)
65
65
  add_instant_capture(post, false)
66
+ add_3ds_auth(post, options)
66
67
 
67
68
  commit(:authorize, post)
68
69
  end
@@ -74,6 +75,7 @@ module ActiveMerchant #:nodoc:
74
75
  add_creditcard_or_reference(post, credit_card_or_reference)
75
76
  add_invoice(post, options)
76
77
  add_instant_capture(post, true)
78
+ add_3ds_auth(post, options)
77
79
 
78
80
  commit(:authorize, post)
79
81
  end
@@ -158,6 +160,16 @@ module ActiveMerchant #:nodoc:
158
160
  post[:instantcapture] = option ? 1 : 0
159
161
  end
160
162
 
163
+ def add_3ds_auth(post, options)
164
+ if options[:three_d_secure]
165
+ post[:eci] = options.dig(:three_d_secure, :eci)
166
+ post[:xid] = options.dig(:three_d_secure, :xid)
167
+ post[:cavv] = options.dig(:three_d_secure, :cavv)
168
+ post[:threeds_version] = options.dig(:three_d_secure, :version)
169
+ post[:ds_transaction_id] = options.dig(:three_d_secure, :ds_transaction_id)
170
+ end
171
+ end
172
+
161
173
  def commit(action, params)
162
174
  response = send("do_#{action}", params)
163
175
 
@@ -193,7 +205,6 @@ module ActiveMerchant #:nodoc:
193
205
  headers['Referer'] = (options[:password] || 'activemerchant.org')
194
206
 
195
207
  response = raw_ssl_request(:post, live_url + 'auth/default.aspx', authorize_post_data(params), headers)
196
-
197
208
  # Authorize gives the response back by redirecting with the values in
198
209
  # the URL query
199
210
  if location = response['Location']
@@ -268,7 +279,7 @@ module ActiveMerchant #:nodoc:
268
279
 
269
280
  def authorize_post_data(params = {})
270
281
  params[:language] = '2'
271
- params[:cms] = 'activemerchant'
282
+ params[:cms] = 'activemerchant_3ds'
272
283
  params[:accepturl] = live_url + 'auth/default.aspx?accept=1'
273
284
  params[:declineurl] = live_url + 'auth/default.aspx?decline=1'
274
285
  params[:merchantnumber] = @options[:login]
@@ -51,7 +51,7 @@ module ActiveMerchant #:nodoc:
51
51
  params = {}
52
52
  add_metadata(params, options)
53
53
  add_invoice(params, amount, options)
54
- add_customer_data(params, options)
54
+ add_customer_data(params, options, payment_method)
55
55
  add_credit_card(params, payment_method, options)
56
56
  params['Method'] = payment_method.respond_to?(:number) ? 'ProcessPayment' : 'TokenPayment'
57
57
  commit(url_for('Transaction'), params)
@@ -61,7 +61,7 @@ module ActiveMerchant #:nodoc:
61
61
  params = {}
62
62
  add_metadata(params, options)
63
63
  add_invoice(params, amount, options)
64
- add_customer_data(params, options)
64
+ add_customer_data(params, options, payment_method)
65
65
  add_credit_card(params, payment_method, options)
66
66
  params['Method'] = 'Authorise'
67
67
  commit(url_for('Authorisation'), params)
@@ -137,7 +137,7 @@ module ActiveMerchant #:nodoc:
137
137
  params = {}
138
138
  add_metadata(params, options)
139
139
  add_invoice(params, 0, options)
140
- add_customer_data(params, options)
140
+ add_customer_data(params, options, payment_method)
141
141
  add_credit_card(params, payment_method, options)
142
142
  params['Method'] = 'CreateTokenCustomer'
143
143
  commit(url_for('Transaction'), params)
@@ -166,7 +166,7 @@ module ActiveMerchant #:nodoc:
166
166
  params = {}
167
167
  add_metadata(params, options)
168
168
  add_invoice(params, 0, options)
169
- add_customer_data(params, options)
169
+ add_customer_data(params, options, payment_method)
170
170
  add_credit_card(params, payment_method, options)
171
171
  add_customer_token(params, customer_token)
172
172
  params['Method'] = 'UpdateTokenCustomer'
@@ -212,17 +212,48 @@ module ActiveMerchant #:nodoc:
212
212
  params['TransactionID'] = reference
213
213
  end
214
214
 
215
- def add_customer_data(params, options)
216
- params['Customer'] ||= {}
217
- add_address(params['Customer'], (options[:billing_address] || options[:address]), {:email => options[:email]})
218
- params['ShippingAddress'] = {}
219
- add_address(params['ShippingAddress'], options[:shipping_address], {:skip_company => true})
215
+ def add_customer_data(params, options, payment_method = nil)
216
+ add_customer_fields(params, options, payment_method)
217
+ add_shipping_fields(params, options)
218
+ end
219
+
220
+ def add_customer_fields(params, options, payment_method)
221
+ key = 'Customer'
222
+ params[key] ||= {}
223
+
224
+ customer_address = options[:billing_address] || options[:address]
225
+
226
+ add_name_and_email(params[key], customer_address, options[:email], payment_method)
227
+ add_address(params[key], customer_address)
228
+ end
229
+
230
+ def add_shipping_fields(params, options)
231
+ key = 'ShippingAddress'
232
+ params[key] = {}
233
+
234
+ add_name_and_email(params[key], options[:shipping_address], options[:email])
235
+ add_address(params[key], options[:shipping_address], {:skip_company => true})
236
+ end
237
+
238
+ def add_name_and_email(params, address, email, payment_method = nil)
239
+ if address.present?
240
+ params['FirstName'], params['LastName'] = split_names(address[:name])
241
+ elsif payment_method_name_available?(payment_method)
242
+ params['FirstName'] = payment_method.first_name
243
+ params['LastName'] = payment_method.last_name
244
+ end
245
+
246
+ params['Email'] = email
247
+ end
248
+
249
+ def payment_method_name_available?(payment_method)
250
+ payment_method.respond_to?(:first_name) && payment_method.respond_to?(:last_name) &&
251
+ payment_method.first_name.present? && payment_method.last_name.present?
220
252
  end
221
253
 
222
254
  def add_address(params, address, options={})
223
255
  return unless address
224
256
 
225
- params['FirstName'], params['LastName'] = split_names(address[:name])
226
257
  params['Title'] = address[:title]
227
258
  params['CompanyName'] = address[:company] unless options[:skip_company]
228
259
  params['Street1'] = truncate(address[:address1], 50)
@@ -231,9 +262,8 @@ module ActiveMerchant #:nodoc:
231
262
  params['State'] = address[:state]
232
263
  params['PostalCode'] = address[:zip]
233
264
  params['Country'] = address[:country].to_s.downcase
234
- params['Phone'] = address[:phone]
265
+ params['Phone'] = address[:phone] || address[:phone_number]
235
266
  params['Fax'] = address[:fax]
236
- params['Email'] = options[:email]
237
267
  end
238
268
 
239
269
  def add_credit_card(params, credit_card, options)
@@ -27,6 +27,7 @@ module ActiveMerchant #:nodoc:
27
27
  add_extra_options(post, options)
28
28
  add_order_id(post, options)
29
29
  add_ip(post, options)
30
+ add_metadata(post, options)
30
31
 
31
32
  commit(:post, 'purchases', post)
32
33
  end
@@ -39,6 +40,7 @@ module ActiveMerchant #:nodoc:
39
40
  add_extra_options(post, options)
40
41
  add_order_id(post, options)
41
42
  add_ip(post, options)
43
+ add_metadata(post, options)
42
44
 
43
45
  post[:capture] = false
44
46
 
@@ -138,6 +140,10 @@ module ActiveMerchant #:nodoc:
138
140
  post[:customer_ip] = options[:ip] || '127.0.0.1'
139
141
  end
140
142
 
143
+ def add_metadata(post, options)
144
+ post[:metadata] = options.fetch(:metadata, {})
145
+ end
146
+
141
147
  def commit(method, uri, parameters=nil)
142
148
  response = begin
143
149
  parse(ssl_request(method, get_url(uri), parameters.to_json, headers))
@@ -10,7 +10,7 @@ module ActiveMerchant #:nodoc:
10
10
  self.supported_countries = ['AD', 'AE', 'AG', 'AI', 'AL', 'AM', 'AO', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IS', 'IT', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PL', 'PN', 'PS', 'PT', 'PW', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SR', 'ST', 'SV', 'SZ', 'TC', 'TD', 'TG', 'TH', 'TJ', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'US', 'UY', 'UZ', 'VC', 'VE', 'VG', 'VI', 'VN', 'WF', 'WS', 'ZA', 'ZM', 'ZW']
11
11
  self.default_currency = 'USD'
12
12
  self.money_format = :cents
13
- self.supported_cardtypes = [:visa, :master, :american_express, :discover]
13
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :naranja, :cabal]
14
14
 
15
15
  def initialize(options={})
16
16
  requires!(options, :merchant_id, :api_key_id, :secret_api_key)
@@ -142,12 +142,8 @@ module ActiveMerchant #:nodoc:
142
142
 
143
143
  def add_customer_data(post, options, payment = nil)
144
144
  if payment
145
- post['order']['customer']['personalInformation'] = {
146
- 'name' => {
147
- 'firstName' => payment.first_name[0..14],
148
- 'surname' => payment.last_name[0..69]
149
- }
150
- }
145
+ post['order']['customer']['personalInformation']['name']['firstName'] = payment.first_name[0..14] if payment.first_name
146
+ post['order']['customer']['personalInformation']['name']['surname'] = payment.last_name[0..69] if payment.last_name
151
147
  end
152
148
  post['order']['customer']['merchantCustomerId'] = options[:customer] if options[:customer]
153
149
  post['order']['customer']['companyInformation']['name'] = options[:company] if options[:company]
@@ -15,6 +15,14 @@ module ActiveMerchant #:nodoc:
15
15
 
16
16
  self.money_format = :dollars
17
17
 
18
+ PAYMENT_DATA_SOURCE_MAPPING = {
19
+ apple_pay: 'ApplePay',
20
+ master: 'MasterCard 3DSecure',
21
+ visa: 'Visa 3DSecure',
22
+ american_express: 'AMEX 3DSecure',
23
+ discover: 'Discover 3DSecure',
24
+ }
25
+
18
26
  def initialize(options={})
19
27
  requires!(options, :secret_api_key)
20
28
  super
@@ -28,6 +36,7 @@ module ActiveMerchant #:nodoc:
28
36
  add_details(xml, options)
29
37
  add_descriptor_name(xml, options)
30
38
  add_payment(xml, card_or_token, options)
39
+ add_three_d_secure(xml, card_or_token, options)
31
40
  end
32
41
  end
33
42
 
@@ -46,6 +55,7 @@ module ActiveMerchant #:nodoc:
46
55
  add_details(xml, options)
47
56
  add_descriptor_name(xml, options)
48
57
  add_payment(xml, card_or_token, options)
58
+ add_three_d_secure(xml, card_or_token, options)
49
59
  end
50
60
  end
51
61
 
@@ -81,7 +91,8 @@ module ActiveMerchant #:nodoc:
81
91
  transcript.
82
92
  gsub(%r((<hps:CardNbr>)[^<]*(<\/hps:CardNbr>))i, '\1[FILTERED]\2').
83
93
  gsub(%r((<hps:CVV2>)[^<]*(<\/hps:CVV2>))i, '\1[FILTERED]\2').
84
- gsub(%r((<hps:SecretAPIKey>)[^<]*(<\/hps:SecretAPIKey>))i, '\1[FILTERED]\2')
94
+ gsub(%r((<hps:SecretAPIKey>)[^<]*(<\/hps:SecretAPIKey>))i, '\1[FILTERED]\2').
95
+ gsub(%r((<hps:PaymentData>)[^<]*(<\/hps:PaymentData>))i, '\1[FILTERED]\2')
85
96
  end
86
97
 
87
98
  private
@@ -164,6 +175,40 @@ module ActiveMerchant #:nodoc:
164
175
  xml.hps :TxnDescriptor, options[:descriptor_name] if options[:descriptor_name]
165
176
  end
166
177
 
178
+ def add_three_d_secure(xml, card_or_token, options)
179
+ if card_or_token.is_a?(NetworkTokenizationCreditCard)
180
+ build_three_d_secure(xml, {
181
+ source: card_or_token.source,
182
+ cavv: card_or_token.payment_cryptogram,
183
+ eci: card_or_token.eci,
184
+ xid: card_or_token.transaction_id,
185
+ })
186
+ elsif options[:three_d_secure]
187
+ options[:three_d_secure][:source] ||= card_brand(card_or_token)
188
+ build_three_d_secure(xml, options[:three_d_secure])
189
+ end
190
+ end
191
+
192
+ def build_three_d_secure(xml, three_d_secure)
193
+ # PaymentDataSource is required when supplying the SecureECommerce data group,
194
+ # and the gateway currently only allows the values within the mapping
195
+ return unless PAYMENT_DATA_SOURCE_MAPPING[three_d_secure[:source].to_sym]
196
+
197
+ xml.hps :SecureECommerce do
198
+ xml.hps :PaymentDataSource, PAYMENT_DATA_SOURCE_MAPPING[three_d_secure[:source].to_sym]
199
+ xml.hps :TypeOfPaymentData, '3DSecure' # Only type currently supported
200
+ xml.hps :PaymentData, three_d_secure[:cavv] if three_d_secure[:cavv]
201
+ # the gateway only allows a single character for the ECI
202
+ xml.hps :ECommerceIndicator, strip_leading_zero(three_d_secure[:eci]) if three_d_secure[:eci]
203
+ xml.hps :XID, three_d_secure[:xid] if three_d_secure[:xid]
204
+ end
205
+ end
206
+
207
+ def strip_leading_zero(value)
208
+ return value unless value[0] == '0'
209
+ value[1, 1]
210
+ end
211
+
167
212
  def build_request(action)
168
213
  xml = Builder::XmlMarkup.new(encoding: 'UTF-8')
169
214
  xml.instruct!(:xml, encoding: 'UTF-8')
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
7
7
  self.test_url = 'https://api-uat.kushkipagos.com/v1/'
8
8
  self.live_url = 'https://api.kushkipagos.com/v1/'
9
9
 
10
- self.supported_countries = ['CO', 'EC']
10
+ self.supported_countries = ['CL', 'CO', 'EC', 'MX', 'PE']
11
11
  self.default_currency = 'USD'
12
12
  self.money_format = :dollars
13
13
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club]
@@ -7,9 +7,20 @@ module ActiveMerchant
7
7
  end
8
8
 
9
9
  def purchase(amount, payment_method, options={})
10
- MultiResponse.run do |r|
11
- r.process { authorize(amount, payment_method, options) }
12
- r.process { capture(amount, r.authorization, options) }
10
+ if options[:pay_mode]
11
+ post = new_post
12
+ add_invoice(post, amount, options)
13
+ add_reference(post, *new_authorization)
14
+ add_payment_method(post, payment_method)
15
+ add_customer_data(post, payment_method, options)
16
+ add_3dsecure_id(post, options)
17
+
18
+ commit('pay', post)
19
+ else
20
+ MultiResponse.run do |r|
21
+ r.process { authorize(amount, payment_method, options) }
22
+ r.process { capture(amount, r.authorization, options) }
23
+ end
13
24
  end
14
25
  end
15
26
 
@@ -206,9 +217,23 @@ module ActiveMerchant
206
217
 
207
218
  def base_url
208
219
  if test?
209
- @options[:region] == 'asia_pacific' ? test_ap_url : test_na_url
220
+ case @options[:region]
221
+ when 'asia_pacific'
222
+ test_ap_url
223
+ when 'europe'
224
+ test_eu_url
225
+ when 'north_america', nil
226
+ test_na_url
227
+ end
210
228
  else
211
- @options[:region] == 'asia_pacific' ? live_ap_url : live_na_url
229
+ case @options[:region]
230
+ when 'asia_pacific'
231
+ live_ap_url
232
+ when 'europe'
233
+ live_eu_url
234
+ when 'north_america', nil
235
+ live_na_url
236
+ end
212
237
  end
213
238
  end
214
239
 
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
4
4
  self.live_url = self.test_url = 'https://api.mercadopago.com/v1'
5
5
 
6
6
  self.supported_countries = ['AR', 'BR', 'CL', 'CO', 'MX', 'PE', 'UY']
7
- self.supported_cardtypes = [:visa, :master, :american_express, :elo]
7
+ self.supported_cardtypes = [:visa, :master, :american_express, :elo, :cabal, :naranja]
8
8
 
9
9
  self.homepage_url = 'https://www.mercadopago.com/'
10
10
  self.display_name = 'Mercado Pago'
@@ -63,6 +63,7 @@ module ActiveMerchant #:nodoc:
63
63
  add_creditcard(post, creditcard)
64
64
  add_standard_parameters('pay', post, options[:unique_id])
65
65
  add_3ds(post, options)
66
+ add_tx_source(post, options)
66
67
 
67
68
  commit(post)
68
69
  end
@@ -83,6 +84,7 @@ module ActiveMerchant #:nodoc:
83
84
  add_amount(post, money, options)
84
85
  add_advanced_user(post)
85
86
  add_standard_parameters('capture', post, options[:unique_id])
87
+ add_tx_source(post, options)
86
88
 
87
89
  commit(post)
88
90
  end
@@ -99,6 +101,7 @@ module ActiveMerchant #:nodoc:
99
101
  add_amount(post, money, options)
100
102
  add_advanced_user(post)
101
103
  add_standard_parameters('refund', post, options[:unique_id])
104
+ add_tx_source(post, options)
102
105
 
103
106
  commit(post)
104
107
  end
@@ -110,6 +113,7 @@ module ActiveMerchant #:nodoc:
110
113
 
111
114
  add_advanced_user(post)
112
115
  add_standard_parameters('voidAuthorisation', post, options[:unique_id])
116
+ add_tx_source(post, options)
113
117
 
114
118
  commit(post)
115
119
  end
@@ -241,6 +245,10 @@ module ActiveMerchant #:nodoc:
241
245
  post['3DSstatus'] = options[:three_ds_status] if options[:three_ds_status]
242
246
  end
243
247
 
248
+ def add_tx_source(post, options)
249
+ post[:TxSource] = options[:tx_source] if options[:tx_source]
250
+ end
251
+
244
252
  def add_creditcard(post, creditcard)
245
253
  post[:CardNum] = creditcard.number
246
254
  post[:CardSecurityCode] = creditcard.verification_value if creditcard.verification_value?
@@ -133,6 +133,7 @@ module ActiveMerchant #:nodoc:
133
133
  add_payment(xml, action, money, options)
134
134
  add_account(xml, credit_card)
135
135
  add_customer(xml, credit_card, options)
136
+ add_three_d_secure(xml, options)
136
137
  end
137
138
 
138
139
  commit(request)
@@ -225,6 +226,36 @@ module ActiveMerchant #:nodoc:
225
226
  end
226
227
  end
227
228
 
229
+ # Private : Convert ECI to ResultIndicator
230
+ # Possible ECI values:
231
+ # 02 or 05 - Fully Authenticated Transaction
232
+ # 00 or 07 - Non 3D Secure Transaction
233
+ # Possible ResultIndicator values:
234
+ # 01 = MASTER_3D_ATTEMPT
235
+ # 02 = MASTER_3D_SUCCESS
236
+ # 05 = VISA_3D_SUCCESS
237
+ # 06 = VISA_3D_ATTEMPT
238
+ # 07 = DEFAULT_E_COMMERCE
239
+ def eci_to_result_indicator(eci)
240
+ case eci
241
+ when '02', '05'
242
+ return eci
243
+ else
244
+ return '07'
245
+ end
246
+ end
247
+
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
256
+ end
257
+ end
258
+
228
259
  # Private: Parse XML response from Monei servers
229
260
  def parse(body)
230
261
  xml = Nokogiri::XML(body)
@@ -5,7 +5,7 @@ module ActiveMerchant #:nodoc:
5
5
 
6
6
  self.supported_countries = ['US']
7
7
  self.default_currency = 'USD'
8
- self.supported_cardtypes = [:visa, :master, :american_express, :discover]
8
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :alelo]
9
9
 
10
10
  self.homepage_url = 'https://www.mundipagg.com/'
11
11
  self.display_name = 'Mundipagg'
@@ -249,7 +249,8 @@ module ActiveMerchant #:nodoc:
249
249
  error_code: error_code_from(response)
250
250
  )
251
251
  rescue ResponseError => e
252
- message = get_error_message(e)
252
+ message = get_error_messages(e)
253
+
253
254
  return Response.new(
254
255
  false,
255
256
  "#{STANDARD_ERROR_MESSAGE_MAPPING[e.response.code]} #{message}",
@@ -263,15 +264,41 @@ module ActiveMerchant #:nodoc:
263
264
  %w[pending paid processing canceled active].include? response['status']
264
265
  end
265
266
 
266
- def get_error_message(error)
267
- JSON.parse(error.response.body)['message']
268
- end
269
-
270
267
  def message_from(response)
268
+ return gateway_response_errors(response) if gateway_response_errors?(response)
271
269
  return response['message'] if response['message']
272
270
  return response['last_transaction']['acquirer_message'] if response['last_transaction']
273
271
  end
274
272
 
273
+ def get_error_messages(error)
274
+ parsed_response_body = parse(error.response.body)
275
+ message = parsed_response_body['message']
276
+
277
+ parsed_response_body['errors']&.each do |type, descriptions|
278
+ message += ' | '
279
+ message += descriptions.join(', ')
280
+ end
281
+
282
+ message
283
+ end
284
+
285
+ def gateway_response_errors?(response)
286
+ response.try(:[], 'last_transaction').try(:[], 'gateway_response').try(:[], 'errors').present?
287
+ end
288
+
289
+ def gateway_response_errors(response)
290
+ error_string = ''
291
+
292
+ response['last_transaction']['gateway_response']['errors']&.each do |error|
293
+ error.each do |key, value|
294
+ error_string += ' | ' unless error_string.blank?
295
+ error_string += value
296
+ end
297
+ end
298
+
299
+ error_string
300
+ end
301
+
275
302
  def authorization_from(response, action)
276
303
  return "#{response['customer']['id']}|#{response['id']}" if action == 'store'
277
304
  response['id']