activemerchant 1.96.0 → 1.97.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e6a20c62ca88a52c155c0d8f3f33e7a6469e93b8bfb1734dcca624d65277143
4
- data.tar.gz: b715b562b0d1d59cc77379fd288ee88fe7756df860f2d8e28337b023ecf46f30
3
+ metadata.gz: 5d0f7d776b87d565598558755d845eb264dbee972e2076cb73bca68c4ee33c78
4
+ data.tar.gz: d08dd14ebabb954845e8a8b951b1ebb66c6d92e1148f4b4187cbe5e47b8cbd36
5
5
  SHA512:
6
- metadata.gz: b2853c5308ce93417b2efd259bf34a73d31055d52569bc64549306895b985cb80e2585de6941a51170f071b1057ec4265b54da13d25666ec260f72ace494881f
7
- data.tar.gz: 248707f263ef74d7c6847d656de2413dd20f8d235cbb94aa9cad25a9d94f51df0eeb055e3ba28af1499822fa2302f7137097fd4addf8d07b14e341aea38b330f
6
+ metadata.gz: 879f72d1da257d47280e668b29238481031287c534868458029f31ffc8bf9498c3385cc90794e2f9391f3c74854b29a4a6d52ce43bb7b51e1d2b1d6f08379ccc
7
+ data.tar.gz: 70d1898a7869e96841d29d102a44e5b9b5da34c5685185f8a6e57901123af3e81a26f7889a75d942553b8dd8eb83b70c4ac4515e96ad6f7460ccb816d9801394
data/CHANGELOG CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  == HEAD
4
4
 
5
+ == Version 1.97.0 (Aug 15, 2019)
6
+ * CyberSource: Add issuer `additionalData` gateway-specific field [jasonxp] #3296
7
+ * PayU Latam: Add Naranja card type [hdeters] #3299
8
+ * Adyen: Add app based 3DS requests for auth and purchase [jeremywrowe] #3298
9
+ * MercadoPago: Add Cabal card type [leila-alderman] #3295
10
+ * MONEI: Add external MPI 3DS 1 support [jimmyn] #3292
11
+ * Bambora formerly Beanstream: Pass card owner when storing tokenized cards [alexdunae] #3006
12
+ * Realex: Prevent error calculating `refund_hash` or `credit_hash` when the secret is nil [jasonxp] #3291
13
+ * Orbital: Add external MPI support for 3DS1 [pi3r] #3261
14
+ * Paymill: Add currency and amount to store requests [jasonxp] #3289
15
+ * Realex: Re-implement credit as general credit [leila-alderman] #3280
16
+ * Braintree Blue: Support for stored credentials [hdeters] #3286
17
+ * CardConnect: Move domain from gateway specific to gateway field [hdeters] #3283
18
+
5
19
  == Version 1.96.0 (Jul 26, 2019)
6
20
  * Bluesnap: Omit state codes for unsupported countries [therufs] #3229
7
21
  * Adyen: Pass updateShopperStatement, industryUsage [curiousepic] #3233
@@ -192,7 +206,6 @@
192
206
  * Forte: Allow void on capture [nfarve] #3059
193
207
 
194
208
  == Version 1.86.0 (October 26, 2018)
195
- * UsaEpayTransaction: Support UMcheckformat option for echecks [dtykocki] #3002
196
209
  * Global Collect: handle internal server errors [molbrown] #3005
197
210
  * Barclaycard Smartpay: allow third-party payouts for credits [bpollack] #3009
198
211
  * RuboCop: AlignHash [nfarve] #3004
@@ -20,6 +20,8 @@ module ActiveMerchant #:nodoc:
20
20
  # * Forbrugsforeningen
21
21
  # * Elo
22
22
  # * Alelo
23
+ # * Cabal
24
+ # * Naranja
23
25
  #
24
26
  # For testing purposes, use the 'bogus' credit card brand. This skips the vast majority of
25
27
  # validations, allowing you to focus on your core concerns until you're ready to be more concerned
@@ -92,6 +94,8 @@ module ActiveMerchant #:nodoc:
92
94
  # * +'forbrugsforeningen'+
93
95
  # * +'elo'+
94
96
  # * +'alelo'+
97
+ # * +'cabal'+
98
+ # * +'naranja'+
95
99
  #
96
100
  # Or, if you wish to test your implementation, +'bogus'+.
97
101
  #
@@ -9,6 +9,7 @@ module ActiveMerchant #:nodoc:
9
9
  'alelo' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), ALELO_RANGES) },
10
10
  'discover' => ->(num) { num =~ /^(6011|65\d{2}|64[4-9]\d)\d{12,15}|(62\d{14,17})$/ },
11
11
  'american_express' => ->(num) { num =~ /^3[47]\d{13}$/ },
12
+ 'naranja' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 6), NARANJA_RANGES) },
12
13
  'diners_club' => ->(num) { num =~ /^3(0[0-5]|[68]\d)\d{11}$/ },
13
14
  'jcb' => ->(num) { num =~ /^35(28|29|[3-8]\d)\d{12}$/ },
14
15
  'dankort' => ->(num) { num =~ /^5019\d{12}$/ },
@@ -16,6 +17,7 @@ module ActiveMerchant #:nodoc:
16
17
  'forbrugsforeningen' => ->(num) { num =~ /^600722\d{10}$/ },
17
18
  'sodexo' => ->(num) { num =~ /^(606071|603389|606070|606069|606068|600818)\d{10}$/ },
18
19
  'vr' => ->(num) { num =~ /^(627416|637036)\d{10}$/ },
20
+ 'cabal' => ->(num) { num&.size == 16 && in_bin_range?(num.slice(0, 8), CABAL_RANGES) },
19
21
  'carnet' => lambda { |num|
20
22
  num&.size == 16 && (
21
23
  in_bin_range?(num.slice(0, 6), CARNET_RANGES) ||
@@ -93,6 +95,16 @@ module ActiveMerchant #:nodoc:
93
95
  506770..506771, 509015..509019, 509880..509882, 509884..509885, 509987..509988
94
96
  ]
95
97
 
98
+ CABAL_RANGES = [
99
+ 60420100..60440099,
100
+ 58965700..58965799,
101
+ 60352200..60352299
102
+ ]
103
+
104
+ NARANJA_RANGES = [
105
+ 589562..589562
106
+ ]
107
+
96
108
  def self.included(base)
97
109
  base.extend(ClassMethods)
98
110
  end
@@ -168,7 +180,7 @@ module ActiveMerchant #:nodoc:
168
180
  valid_test_mode_card_number?(number) ||
169
181
  valid_card_number_length?(number) &&
170
182
  valid_card_number_characters?(number) &&
171
- valid_checksum?(number)
183
+ valid_by_algorithm?(brand?(number), number)
172
184
  end
173
185
 
174
186
  def card_companies
@@ -242,6 +254,15 @@ module ActiveMerchant #:nodoc:
242
254
  %w[1 2 3 success failure error].include?(number)
243
255
  end
244
256
 
257
+ def valid_by_algorithm?(brand, numbers) #:nodoc:
258
+ case brand
259
+ when 'naranja'
260
+ valid_naranja_algo?(numbers)
261
+ else
262
+ valid_luhn?(numbers)
263
+ end
264
+ end
265
+
245
266
  ODD_LUHN_VALUE = {
246
267
  48 => 0,
247
268
  49 => 1,
@@ -272,7 +293,7 @@ module ActiveMerchant #:nodoc:
272
293
  # Checks the validity of a card number by use of the Luhn Algorithm.
273
294
  # Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
274
295
  # This implementation is from the luhn_checksum gem, https://github.com/zendesk/luhn_checksum.
275
- def valid_checksum?(numbers) #:nodoc:
296
+ def valid_luhn?(numbers) #:nodoc:
276
297
  sum = 0
277
298
 
278
299
  odd = true
@@ -288,6 +309,16 @@ module ActiveMerchant #:nodoc:
288
309
 
289
310
  sum % 10 == 0
290
311
  end
312
+
313
+ # Checks the validity of a card number by use of Naranja's specific algorithm.
314
+ def valid_naranja_algo?(numbers) #:nodoc:
315
+ num_array = numbers.to_s.chars.map(&:to_i)
316
+ multipliers = [4, 3, 2, 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
317
+ num_sum = num_array[0..14].zip(multipliers).map { |a, b| a*b }.reduce(:+)
318
+ intermediate = 11 - (num_sum % 11)
319
+ final_num = intermediate > 9 ? 0 : intermediate
320
+ final_num == num_array[15]
321
+ end
291
322
  end
292
323
  end
293
324
  end
@@ -10,7 +10,7 @@ module ActiveMerchant #:nodoc:
10
10
  self.supported_countries = ['AT', 'AU', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GI', 'GR', 'HK', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SG', 'SK', 'SI', 'US']
11
11
  self.default_currency = 'USD'
12
12
  self.currencies_without_fractions = %w(CVE DJF GNF IDR JPY KMF KRW PYG RWF UGX VND VUV XAF XOF XPF)
13
- self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover, :elo]
13
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover, :elo, :naranja]
14
14
 
15
15
  self.money_format = :cents
16
16
 
@@ -328,24 +328,12 @@ module ActiveMerchant #:nodoc:
328
328
 
329
329
  def add_3ds(post, options)
330
330
  if three_ds_2_options = options[:three_ds_2]
331
- if browser_info = three_ds_2_options[:browser_info]
332
- post[:browserInfo] = {
333
- acceptHeader: browser_info[:accept_header],
334
- colorDepth: browser_info[:depth],
335
- javaEnabled: browser_info[:java],
336
- language: browser_info[:language],
337
- screenHeight: browser_info[:height],
338
- screenWidth: browser_info[:width],
339
- timeZoneOffset: browser_info[:timezone],
340
- userAgent: browser_info[:user_agent]
341
- }
342
-
343
- if device_channel = three_ds_2_options[:channel]
344
- post[:threeDS2RequestData] = {
345
- deviceChannel: device_channel,
346
- notificationURL: three_ds_2_options[:notification_url] || 'https://example.com/notification'
347
- }
348
- end
331
+ device_channel = three_ds_2_options[:channel]
332
+ if device_channel == 'app'
333
+ post[:threeDS2RequestData] = { deviceChannel: device_channel }
334
+ else
335
+ add_browser_info(three_ds_2_options[:browser_info], post)
336
+ post[:threeDS2RequestData] = { deviceChannel: device_channel, notificationURL: three_ds_2_options[:notification_url] }
349
337
  end
350
338
  else
351
339
  return unless options[:execute_threed] || options[:threed_dynamic]
@@ -457,6 +445,20 @@ module ActiveMerchant #:nodoc:
457
445
  def error_code_from(response)
458
446
  STANDARD_ERROR_CODE_MAPPING[response['errorCode']]
459
447
  end
448
+
449
+ def add_browser_info(browser_info, post)
450
+ return unless browser_info
451
+ post[:browserInfo] = {
452
+ acceptHeader: browser_info[:accept_header],
453
+ colorDepth: browser_info[:depth],
454
+ javaEnabled: browser_info[:java],
455
+ language: browser_info[:language],
456
+ screenHeight: browser_info[:height],
457
+ screenWidth: browser_info[:width],
458
+ timeZoneOffset: browser_info[:timezone],
459
+ userAgent: browser_info[:user_agent]
460
+ }
461
+ end
460
462
  end
461
463
  end
462
464
  end
@@ -153,6 +153,8 @@ module ActiveMerchant #:nodoc:
153
153
 
154
154
  # To match the other stored-value gateways, like TrustCommerce,
155
155
  # store and unstore need to be defined
156
+ #
157
+ # When passing a single-use token the :name option is required
156
158
  def store(payment_method, options = {})
157
159
  post = {}
158
160
  add_address(post, options)
@@ -315,6 +315,9 @@ module ActiveMerchant #:nodoc:
315
315
  post[:operationType] = options[:operationType] || options[:operation] || secure_profile_action(:new)
316
316
  post[:customerCode] = options[:billing_id] || options[:vault_id] || false
317
317
  post[:status] = options[:status]
318
+
319
+ billing_address = options[:billing_address] || options[:address]
320
+ post[:trnCardOwner] = billing_address[:name]
318
321
  end
319
322
 
320
323
  def add_recurring_amount(post, money)
@@ -8,7 +8,7 @@ module ActiveMerchant
8
8
  self.supported_countries = %w(US CA GB AT BE BG HR CY CZ DK EE FI FR DE GR HU IE IT LV LT LU MT NL PL PT RO SK SI ES SE AR BO BR BZ CL CO CR DO EC GF GP GT HN HT MF MQ MX NI PA PE PR PY SV UY VE)
9
9
 
10
10
  self.default_currency = 'USD'
11
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro, :naranja]
12
12
 
13
13
  self.homepage_url = 'https://home.bluesnap.com/'
14
14
  self.display_name = 'BlueSnap'
@@ -447,7 +447,6 @@ module ActiveMerchant #:nodoc:
447
447
 
448
448
  def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
449
449
  transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
450
-
451
450
  commit do
452
451
  result = @braintree_gateway.transaction.send(transaction_type, transaction_params)
453
452
  response = Response.new(result.success?, message_from_transaction_result(result), response_params(result), response_options(result))
@@ -567,6 +566,7 @@ module ActiveMerchant #:nodoc:
567
566
  'vault_customer' => vault_customer,
568
567
  'merchant_account_id' => transaction.merchant_account_id,
569
568
  'risk_data' => risk_data,
569
+ 'network_transaction_id' => transaction.network_transaction_id || nil,
570
570
  'processor_response_code' => response_code_from_result(result)
571
571
  }
572
572
  end
@@ -614,6 +614,7 @@ module ActiveMerchant #:nodoc:
614
614
  end
615
615
 
616
616
  add_payment_method(parameters, credit_card_or_vault_id, options)
617
+ add_stored_credential_data(parameters, credit_card_or_vault_id, options)
617
618
 
618
619
  parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
619
620
  parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
@@ -650,6 +651,26 @@ module ActiveMerchant #:nodoc:
650
651
  parameters
651
652
  end
652
653
 
654
+ def add_stored_credential_data(parameters, credit_card_or_vault_id, options)
655
+ return unless (stored_credential = options[:stored_credential])
656
+ parameters[:external_vault] = {}
657
+ if stored_credential[:initial_transaction]
658
+ parameters[:external_vault][:status] = 'will_vault'
659
+ else
660
+ parameters[:external_vault][:status] = 'vaulted'
661
+ parameters[:external_vault][:previous_network_transaction_id] = stored_credential[:network_transaction_id]
662
+ end
663
+ if stored_credential[:initiator] == 'merchant'
664
+ if stored_credential[:reason_type] == 'installment'
665
+ parameters[:transaction_source] = 'recurring'
666
+ else
667
+ parameters[:transaction_source] = stored_credential[:reason_type]
668
+ end
669
+ else
670
+ parameters[:transaction_source] = ''
671
+ end
672
+ end
673
+
653
674
  def add_payment_method(parameters, credit_card_or_vault_id, options)
654
675
  if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
655
676
  if options[:payment_method_token]
@@ -68,7 +68,7 @@ module ActiveMerchant #:nodoc:
68
68
  end
69
69
 
70
70
  def require_valid_domain!(options, param)
71
- if options.key?(param)
71
+ if options[param]
72
72
  raise ArgumentError.new('not a valid cardconnect domain') unless /\Dcardconnect.com:\d{1,}\D/ =~ options[param]
73
73
  end
74
74
  end
@@ -24,7 +24,9 @@ module ActiveMerchant #:nodoc:
24
24
  self.test_url = 'https://ics2wstesta.ic3.com/commerce/1.x/transactionProcessor'
25
25
  self.live_url = 'https://ics2wsa.ic3.com/commerce/1.x/transactionProcessor'
26
26
 
27
- XSD_VERSION = '1.153'
27
+ # Schema files can be found here: https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/
28
+ TEST_XSD_VERSION = '1.156'
29
+ PRODUCTION_XSD_VERSION = '1.155'
28
30
 
29
31
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro, :elo]
30
32
  self.supported_countries = %w(US BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB PK)
@@ -263,6 +265,8 @@ module ActiveMerchant #:nodoc:
263
265
  add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
264
266
  add_business_rules_data(xml, creditcard_or_reference, options)
265
267
  add_stored_credential_options(xml, options)
268
+ add_issuer_additional_data(xml, options)
269
+
266
270
  xml.target!
267
271
  end
268
272
 
@@ -301,6 +305,8 @@ module ActiveMerchant #:nodoc:
301
305
  add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
302
306
  add_business_rules_data(xml, payment_method_or_reference, options) unless options[:pinless_debit_card]
303
307
  end
308
+ add_issuer_additional_data(xml, options)
309
+
304
310
  xml.target!
305
311
  end
306
312
 
@@ -485,6 +491,14 @@ module ActiveMerchant #:nodoc:
485
491
  end
486
492
  end
487
493
 
494
+ def add_issuer_additional_data(xml, options)
495
+ return unless options[:issuer_additional_data]
496
+
497
+ xml.tag! 'issuer' do
498
+ xml.tag! 'additionalData', options[:issuer_additional_data]
499
+ end
500
+ end
501
+
488
502
  def add_mdd_fields(xml, options)
489
503
  return unless options.keys.any? { |key| key.to_s.start_with?('mdd_field') }
490
504
 
@@ -713,6 +727,8 @@ module ActiveMerchant #:nodoc:
713
727
 
714
728
  # Where we actually build the full SOAP request using builder
715
729
  def build_request(body, options)
730
+ xsd_version = test? ? TEST_XSD_VERSION : PRODUCTION_XSD_VERSION
731
+
716
732
  xml = Builder::XmlMarkup.new :indent => 2
717
733
  xml.instruct!
718
734
  xml.tag! 's:Envelope', {'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/'} do
@@ -725,7 +741,7 @@ module ActiveMerchant #:nodoc:
725
741
  end
726
742
  end
727
743
  xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
728
- xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{XSD_VERSION}"} do
744
+ xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}"} do
729
745
  add_merchant_data(xml, options)
730
746
  xml << body
731
747
  end
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
6
6
 
7
7
  self.supported_countries = ['AR', 'BR', 'CL', 'CO', 'MX', 'PE', 'UY', 'TR']
8
8
  self.default_currency = 'USD'
9
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
9
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro, :naranja]
10
10
 
11
11
  self.homepage_url = 'https://dlocal.com/'
12
12
  self.display_name = 'dLocal'
@@ -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]
14
14
 
15
15
  def initialize(options={})
16
16
  requires!(options, :merchant_id, :api_key_id, :secret_api_key)
@@ -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'
@@ -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)
@@ -465,16 +465,62 @@ module ActiveMerchant #:nodoc:
465
465
  end
466
466
  end
467
467
 
468
- def add_cdpt_eci_and_xid(xml, creditcard)
469
- xml.tag! :AuthenticationECIInd, creditcard.eci
470
- xml.tag! :XID, creditcard.transaction_id if creditcard.transaction_id
468
+ def add_eci(xml, creditcard, three_d_secure)
469
+ eci = if three_d_secure
470
+ three_d_secure[:eci]
471
+ elsif creditcard.is_a?(NetworkTokenizationCreditCard)
472
+ creditcard.eci
473
+ end
474
+
475
+ xml.tag!(:AuthenticationECIInd, eci) if eci
476
+ end
477
+
478
+ def add_xid(xml, creditcard, three_d_secure)
479
+ xid = if three_d_secure && creditcard.brand == 'visa'
480
+ three_d_secure[:xid]
481
+ elsif creditcard.is_a?(NetworkTokenizationCreditCard)
482
+ creditcard.transaction_id
483
+ end
484
+
485
+ xml.tag!(:XID, xid) if xid
486
+ end
487
+
488
+ def add_cavv(xml, creditcard, three_d_secure)
489
+ return unless three_d_secure && creditcard.brand == 'visa'
490
+
491
+ xml.tag!(:CAVV, three_d_secure[:cavv])
492
+ end
493
+
494
+ def add_aav(xml, creditcard, three_d_secure)
495
+ return unless three_d_secure && creditcard.brand == 'master'
496
+
497
+ xml.tag!(:AAV, three_d_secure[:cavv])
471
498
  end
472
499
 
473
- def add_cdpt_payment_cryptogram(xml, creditcard)
500
+ def add_dpanind(xml, creditcard)
501
+ return unless creditcard.is_a?(NetworkTokenizationCreditCard)
502
+
474
503
  xml.tag! :DPANInd, 'Y'
504
+ end
505
+
506
+ def add_digital_token_cryptogram(xml, creditcard)
507
+ return unless creditcard.is_a?(NetworkTokenizationCreditCard)
508
+
475
509
  xml.tag! :DigitalTokenCryptogram, creditcard.payment_cryptogram
476
510
  end
477
511
 
512
+ def add_aevv(xml, creditcard, three_d_secure)
513
+ return unless three_d_secure && creditcard.brand == 'american_express'
514
+
515
+ xml.tag!(:AEVV, three_d_secure[:cavv])
516
+ end
517
+
518
+ def add_pymt_brand_program_code(xml, creditcard, three_d_secure)
519
+ return unless three_d_secure && creditcard.brand == 'american_express'
520
+
521
+ xml.tag!(:PymtBrandProgramCode, 'ASK')
522
+ end
523
+
478
524
  def add_refund(xml, currency=nil)
479
525
  xml.tag! :AccountNum, nil
480
526
 
@@ -633,9 +679,11 @@ module ActiveMerchant #:nodoc:
633
679
 
634
680
  yield xml if block_given?
635
681
 
636
- if creditcard.is_a?(NetworkTokenizationCreditCard)
637
- add_cdpt_eci_and_xid(xml, creditcard)
638
- end
682
+ three_d_secure = parameters[:three_d_secure]
683
+
684
+ add_eci(xml, creditcard, three_d_secure)
685
+ add_cavv(xml, creditcard, three_d_secure)
686
+ add_xid(xml, creditcard, three_d_secure)
639
687
 
640
688
  xml.tag! :OrderID, format_order_id(parameters[:order_id])
641
689
  xml.tag! :Amount, amount(money)
@@ -644,11 +692,12 @@ module ActiveMerchant #:nodoc:
644
692
  add_level_2_tax(xml, parameters)
645
693
  add_level_2_advice_addendum(xml, parameters)
646
694
 
695
+ add_aav(xml, creditcard, three_d_secure)
647
696
  # CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
648
697
 
649
- if creditcard.is_a?(NetworkTokenizationCreditCard)
650
- add_cdpt_payment_cryptogram(xml, creditcard)
651
- end
698
+ add_dpanind(xml, creditcard)
699
+ add_aevv(xml, creditcard, three_d_secure)
700
+ add_digital_token_cryptogram(xml, creditcard)
652
701
 
653
702
  if parameters[:soft_descriptors].is_a?(OrbitalSoftDescriptors)
654
703
  add_soft_descriptors(xml, parameters[:soft_descriptors])
@@ -666,6 +715,7 @@ module ActiveMerchant #:nodoc:
666
715
 
667
716
  add_level_2_purchase(xml, parameters)
668
717
  add_stored_credentials(xml, parameters)
718
+ add_pymt_brand_program_code(xml, creditcard, three_d_secure)
669
719
  end
670
720
  end
671
721
  xml.target!
@@ -48,6 +48,11 @@ module ActiveMerchant #:nodoc:
48
48
  end
49
49
 
50
50
  def store(credit_card, options={})
51
+ # The store request requires a currency and amount of at least $1 USD.
52
+ # This is used for an authorization that is handled internally by Paymill.
53
+ options[:currency] = 'USD'
54
+ options[:money] = 100
55
+
51
56
  save_card(credit_card, options)
52
57
  end
53
58
 
@@ -12,13 +12,14 @@ module ActiveMerchant #:nodoc:
12
12
  self.supported_countries = ['AR', 'BR', 'CL', 'CO', 'MX', 'PA', 'PE']
13
13
  self.default_currency = 'USD'
14
14
  self.money_format = :dollars
15
- self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
15
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :naranja]
16
16
 
17
17
  BRAND_MAP = {
18
18
  'visa' => 'VISA',
19
19
  'master' => 'MASTERCARD',
20
20
  'american_express' => 'AMEX',
21
- 'diners_club' => 'DINERS'
21
+ 'diners_club' => 'DINERS',
22
+ 'naranja' => 'NARANJA'
22
23
  }
23
24
 
24
25
  MINIMUMS = {
@@ -42,7 +42,8 @@ module ActiveMerchant
42
42
 
43
43
  def initialize(options = {})
44
44
  requires!(options, :login, :password)
45
- options[:refund_hash] = Digest::SHA1.hexdigest(options[:rebate_secret]) if options.has_key?(:rebate_secret)
45
+ options[:refund_hash] = Digest::SHA1.hexdigest(options[:rebate_secret]) if options[:rebate_secret].present?
46
+ options[:credit_hash] = Digest::SHA1.hexdigest(options[:refund_secret]) if options[:refund_secret].present?
46
47
  super
47
48
  end
48
49
 
@@ -70,9 +71,9 @@ module ActiveMerchant
70
71
  commit(request)
71
72
  end
72
73
 
73
- def credit(money, authorization, options = {})
74
- ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
75
- refund(money, authorization, options)
74
+ def credit(money, creditcard, options = {})
75
+ request = build_credit_request(money, creditcard, options)
76
+ commit(request)
76
77
  end
77
78
 
78
79
  def void(authorization, options = {})
@@ -184,6 +185,22 @@ module ActiveMerchant
184
185
  xml.target!
185
186
  end
186
187
 
188
+ def build_credit_request(money, credit_card, options)
189
+ timestamp = new_timestamp
190
+ xml = Builder::XmlMarkup.new :indent => 2
191
+ xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'credit' do
192
+ add_merchant_details(xml, options)
193
+ xml.tag! 'orderid', sanitize_order_id(options[:order_id])
194
+ add_amount(xml, money, options)
195
+ add_card(xml, credit_card)
196
+ xml.tag! 'refundhash', @options[:credit_hash] if @options[:credit_hash]
197
+ xml.tag! 'autosettle', 'flag' => 1
198
+ add_comments(xml, options)
199
+ add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), credit_card.number)
200
+ end
201
+ xml.target!
202
+ end
203
+
187
204
  def build_void_request(authorization, options)
188
205
  timestamp = new_timestamp
189
206
  xml = Builder::XmlMarkup.new :indent => 2
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
7
7
  self.default_currency = 'GBP'
8
8
  self.money_format = :cents
9
9
  self.supported_countries = %w(HK GB AU AD AR BE BR CA CH CN CO CR CY CZ DE DK ES FI FR GI GR HU IE IN IT JP LI LU MC MT MY MX NL NO NZ PA PE PL PT SE SG SI SM TR UM VA)
10
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :elo]
10
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :elo, :naranja]
11
11
  self.currencies_without_fractions = %w(HUF IDR ISK JPY KRW)
12
12
  self.currencies_with_three_decimal_places = %w(BHD KWD OMR RSD TND)
13
13
  self.homepage_url = 'http://www.worldpay.com/'
@@ -22,6 +22,7 @@ module ActiveMerchant #:nodoc:
22
22
  'maestro' => 'MAESTRO-SSL',
23
23
  'diners_club' => 'DINERS-SSL',
24
24
  'elo' => 'ELO-SSL',
25
+ 'naranja' => 'NARANJA-SSL',
25
26
  'unknown' => 'CARD-SSL'
26
27
  }
27
28
 
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.96.0'
2
+ VERSION = '1.97.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemerchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.96.0
4
+ version: 1.97.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-26 00:00:00.000000000 Z
11
+ date: 2019-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -413,8 +413,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
413
413
  - !ruby/object:Gem::Version
414
414
  version: '0'
415
415
  requirements: []
416
- rubyforge_project: activemerchant
417
- rubygems_version: 2.7.6
416
+ rubygems_version: 3.0.3
418
417
  signing_key:
419
418
  specification_version: 4
420
419
  summary: Framework and tools for dealing with credit card transactions.