activemerchant 1.96.0 → 1.97.0

Sign up to get free protection for your applications and to get access to all the features.
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.