activemerchant 1.118.0 → 1.119.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: 506cd11074e8ee661844d74fb2a114665b025952d47517a423f27bd2ca566c49
4
- data.tar.gz: 35cfe858b3bd6c492558dcd47cf17518edc6dbd96176dbb72abe6df2ff607724
3
+ metadata.gz: 93f6306f4daee82e8458586cf10ba23a4b1cfa085c912430821bf583c789aded
4
+ data.tar.gz: a943a31836368d69faf7c731dbc4c81d8b1a302b0fddd5cb4960c6714a88f11a
5
5
  SHA512:
6
- metadata.gz: 8955f8c555ec9049fa06e76176a2a819e2e1bbe54868eab1c88023ece7dcd722201009b39d238acfedc79a5ac50363c73dbfa776b95f61d3db308f0b7dd897e6
7
- data.tar.gz: 77736f76e9483256f71abb8799d8bf4804ba0f56992e226f9f185ecb0fed1cb87dc8956e886473a17c4643d3f799e6b9898565c4ec0420b1b3fcefa7471e1d16
6
+ metadata.gz: cb33c86a0b9f3be8186a69fe170656684a98f74dcd9597df7f70792e23050235a9774c4192f25a1700110315dd6a98afa4ef0c3b74e8ea495814146594c2746a
7
+ data.tar.gz: 68729586be8247575dd96b6351db94f5b726338b92229cb49ddb82d6652ed93300049dd1edc18929a01850ec161cbe7574b0ceda0f1f233941019b7dfbca74f4
data/CHANGELOG CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  == HEAD
4
4
 
5
+ == Version 1.119.0 (February 9th, 2021)
6
+ * Payment Express: support verify/validate [therufs] #3874
7
+ * GlobalCollect: Truncate address fields [meagabeth] #3878
8
+ * Litle: Truncate address fields [meagabeth] #3877
9
+ * Netbanx: Add-customer-information(name,email,IP)-to-a-transaction [rockyhakjoong] #3754
10
+ * Decidir: Improve error mapping [meagabeth] #3875
11
+ * Worldpay: support `skip_capture` [therufs] #3879
12
+ * Redsys: Add new response code text [britth] #3880
13
+ * Orbital: Update ECP details to use payment source [jessiagee] #3881
14
+ * Alelo: Add additional BIN ranges [meagabeth] #3882
15
+ * HPS: Update Add support for general credit [naashton] #3885
16
+ * Elavon: Fix issue with encoding data sent in the request [naashton] #3865
17
+ * Orbital: Update ECP to use EWS verification [jessiagee] #3886
18
+ * Eway: Add 3ds field when do direct payment [GavinSun9527] #3860
19
+ * Support Creditel cardtype [therufs] #3883
20
+
5
21
  == Version 1.118.0 (January 22nd, 2021)
6
22
  * Worldpay: Add support for challengeWindowSize [carrigan] #3823
7
23
  * Adyen: Update capitalization on subMerchantId field [cdmackeyfree] #3824
@@ -102,6 +102,7 @@ module ActiveMerchant #:nodoc:
102
102
  # * +'union_pay'+
103
103
  # * +'alia'+
104
104
  # * +'olimpica'+
105
+ # * +'creditel'+
105
106
  #
106
107
  # Or, if you wish to test your implementation, +'bogus'+.
107
108
  #
@@ -31,7 +31,8 @@ module ActiveMerchant #:nodoc:
31
31
  CARNET_BINS.any? { |bin| num.slice(0, bin.size) == bin }
32
32
  )
33
33
  },
34
- 'olimpica' => ->(num) { num =~ /^636853\d{10}$/ }
34
+ 'olimpica' => ->(num) { num =~ /^636853\d{10}$/ },
35
+ 'creditel' => ->(num) { num =~ /^601933\d{10}$/ }
35
36
  }
36
37
 
37
38
  # http://www.barclaycard.co.uk/business/files/bin_rules.pdf
@@ -167,8 +168,9 @@ module ActiveMerchant #:nodoc:
167
168
  402588..402588, 404347..404347, 405876..405876, 405882..405882, 405884..405884,
168
169
  405886..405886, 430471..430471, 438061..438061, 438064..438064, 470063..470066,
169
170
  496067..496067, 506699..506704, 506706..506706, 506713..506714, 506716..506716,
170
- 506749..506750, 506752..506752, 506754..506756, 506758..506762, 506764..506767,
171
- 506770..506771, 509015..509019, 509880..509882, 509884..509885, 509987..509992
171
+ 506749..506750, 506752..506752, 506754..506756, 506758..506767, 506770..506771,
172
+ 506773..506773, 509015..509019, 509880..509882, 509884..509885, 509887..509887,
173
+ 509987..509992
172
174
  ]
173
175
 
174
176
  CABAL_RANGES = [
@@ -345,6 +347,8 @@ module ActiveMerchant #:nodoc:
345
347
  case brand
346
348
  when 'naranja'
347
349
  valid_naranja_algo?(numbers)
350
+ when 'creditel'
351
+ valid_creditel_algo?(numbers)
348
352
  when 'alia'
349
353
  true
350
354
  else
@@ -399,7 +403,7 @@ module ActiveMerchant #:nodoc:
399
403
  sum % 10 == 0
400
404
  end
401
405
 
402
- # Checks the validity of a card number by use of Naranja's specific algorithm.
406
+ # Checks the validity of a card number by use of specific algorithms
403
407
  def valid_naranja_algo?(numbers) #:nodoc:
404
408
  num_array = numbers.to_s.chars.map(&:to_i)
405
409
  multipliers = [4, 3, 2, 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
@@ -408,6 +412,14 @@ module ActiveMerchant #:nodoc:
408
412
  final_num = intermediate > 9 ? 0 : intermediate
409
413
  final_num == num_array[15]
410
414
  end
415
+
416
+ def valid_creditel_algo?(numbers) #:nodoc:
417
+ num_array = numbers.to_s.chars.map(&:to_i)
418
+ multipliers = [5, 4, 3, 2, 1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 9]
419
+ num_sum = num_array[0..14].zip(multipliers).map { |a, b| a * b }.reduce(:+)
420
+ final_num = num_sum % 10
421
+ final_num == num_array[15]
422
+ end
411
423
  end
412
424
  end
413
425
  end
@@ -301,15 +301,21 @@ module ActiveMerchant #:nodoc:
301
301
  error_code = nil
302
302
  if error = response.dig('status_details', 'error')
303
303
  code = error.dig('reason', 'id')
304
- error_code = STANDARD_ERROR_CODE_MAPPING[code]
304
+ standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
305
+ error_code = "#{code}, #{standard_error_code}"
305
306
  error_code ||= error['type']
306
307
  elsif response['error_type']
307
308
  error_code = response['error_type'] if response['validation_errors']
308
- elsif error = response.dig('error')
309
+ elsif response.dig('error', 'validation_errors')
310
+ error = response.dig('error')
309
311
  validation_errors = error.dig('validation_errors', 0)
310
312
  code = validation_errors['code'] if validation_errors && validation_errors['code']
311
313
  param = validation_errors['param'] if validation_errors && validation_errors['param']
312
314
  error_code = "#{error['error_type']} | #{code} | #{param}" if error['error_type']
315
+ elsif error = response.dig('error')
316
+ code = error.dig('reason', 'id')
317
+ standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
318
+ error_code = "#{code}, #{standard_error_code}"
313
319
  end
314
320
 
315
321
  error_code || STANDARD_ERROR_CODE[:processing_error]
@@ -380,6 +380,7 @@ module ActiveMerchant #:nodoc:
380
380
 
381
381
  def commit(request)
382
382
  request = "xmldata=#{request}".delete('&')
383
+
383
384
  response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
384
385
 
385
386
  Response.new(
@@ -416,6 +417,14 @@ module ActiveMerchant #:nodoc:
416
417
  def authorization_from(response)
417
418
  [response[:approval_code], response[:txn_id]].join(';')
418
419
  end
420
+
421
+ def truncate(value, size)
422
+ return nil unless value
423
+
424
+ difference = value.force_encoding('iso-8859-1').length - value.length
425
+
426
+ return value.to_s[0, (size - difference)]
427
+ end
419
428
  end
420
429
  end
421
430
  end
@@ -53,6 +53,7 @@ module ActiveMerchant #:nodoc:
53
53
  add_invoice(params, amount, options)
54
54
  add_customer_data(params, options, payment_method)
55
55
  add_credit_card(params, payment_method, options)
56
+ add_3ds_authenticated_data(params, options) if options[:three_d_secure]
56
57
  params['Method'] = payment_method.respond_to?(:number) ? 'ProcessPayment' : 'TokenPayment'
57
58
  commit(url_for('Transaction'), params)
58
59
  end
@@ -197,6 +198,18 @@ module ActiveMerchant #:nodoc:
197
198
  params
198
199
  end
199
200
 
201
+ def add_3ds_authenticated_data(params, options)
202
+ three_d_secure_options = options[:three_d_secure]
203
+ params['PaymentInstrument'] ||= {} if params['PaymentInstrument'].nil?
204
+ threed_secure_auth = params['PaymentInstrument']['ThreeDSecureAuth'] = {}
205
+ threed_secure_auth['Cryptogram'] = three_d_secure_options[:cavv]
206
+ threed_secure_auth['ECI'] = three_d_secure_options[:eci]
207
+ threed_secure_auth['XID'] = three_d_secure_options[:xid]
208
+ threed_secure_auth['AuthStatus'] = three_d_secure_options[:authentication_response_status]
209
+ threed_secure_auth['dsTransactionId'] = three_d_secure_options[:ds_transaction_id]
210
+ threed_secure_auth['Version'] = three_d_secure_options[:version]
211
+ end
212
+
200
213
  def add_invoice(params, money, options, key = 'Payment')
201
214
  currency_code = options[:currency] || currency(money)
202
215
  params[key] = {
@@ -201,21 +201,21 @@ module ActiveMerchant #:nodoc:
201
201
  shipping_address = options[:shipping_address]
202
202
  if billing_address = options[:billing_address] || options[:address]
203
203
  post['order']['customer']['billingAddress'] = {
204
- 'street' => billing_address[:address1],
205
- 'additionalInfo' => billing_address[:address2],
204
+ 'street' => truncate(billing_address[:address1], 50),
205
+ 'additionalInfo' => truncate(billing_address[:address2], 50),
206
206
  'zip' => billing_address[:zip],
207
207
  'city' => billing_address[:city],
208
- 'state' => billing_address[:state],
208
+ 'state' => truncate(billing_address[:state], 35),
209
209
  'countryCode' => billing_address[:country]
210
210
  }
211
211
  end
212
212
  if shipping_address
213
213
  post['order']['customer']['shippingAddress'] = {
214
- 'street' => shipping_address[:address1],
215
- 'additionalInfo' => shipping_address[:address2],
214
+ 'street' => truncate(shipping_address[:address1], 50),
215
+ 'additionalInfo' => truncate(shipping_address[:address2], 50),
216
216
  'zip' => shipping_address[:zip],
217
217
  'city' => shipping_address[:city],
218
- 'state' => shipping_address[:state],
218
+ 'state' => truncate(shipping_address[:state], 35),
219
219
  'countryCode' => shipping_address[:country]
220
220
  }
221
221
  post['order']['customer']['shippingAddress']['name'] = {
@@ -67,6 +67,15 @@ module ActiveMerchant #:nodoc:
67
67
  end
68
68
  end
69
69
 
70
+ def credit(money, payment_method, options = {})
71
+ commit('CreditReturn') do |xml|
72
+ add_amount(xml, money)
73
+ add_allow_dup(xml)
74
+ add_card_or_token_payment(xml, payment_method, options)
75
+ add_details(xml, options)
76
+ end
77
+ end
78
+
70
79
  def verify(card_or_token, options = {})
71
80
  commit('CreditAccountVerify') do |xml|
72
81
  add_card_or_token_customer_data(xml, card_or_token, options)
@@ -371,9 +371,9 @@ module ActiveMerchant #:nodoc:
371
371
  return unless address
372
372
 
373
373
  doc.companyName(address[:company]) unless address[:company].blank?
374
- doc.addressLine1(address[:address1]) unless address[:address1].blank?
375
- doc.addressLine2(address[:address2]) unless address[:address2].blank?
376
- doc.city(address[:city]) unless address[:city].blank?
374
+ doc.addressLine1(truncate(address[:address1], 35)) unless address[:address1].blank?
375
+ doc.addressLine2(truncate(address[:address2], 35)) unless address[:address2].blank?
376
+ doc.city(truncate(address[:city], 35)) unless address[:city].blank?
377
377
  doc.state(address[:state]) unless address[:state].blank?
378
378
  doc.zip(address[:zip]) unless address[:zip].blank?
379
379
  doc.country(address[:country]) unless address[:country].blank?
@@ -36,6 +36,7 @@ module ActiveMerchant #:nodoc:
36
36
  add_invoice(post, money, options)
37
37
  add_settle_with_auth(post)
38
38
  add_payment(post, payment, options)
39
+ add_customer_detail_data(post, options)
39
40
 
40
41
  commit(:post, 'auths', post)
41
42
  end
@@ -48,6 +49,7 @@ module ActiveMerchant #:nodoc:
48
49
  post = {}
49
50
  add_invoice(post, money, options)
50
51
  add_payment(post, payment, options)
52
+ add_customer_detail_data(post, options)
51
53
 
52
54
  commit(:post, 'auths', post)
53
55
  end
@@ -147,6 +149,15 @@ module ActiveMerchant #:nodoc:
147
149
  post[:locale] = options[:locale]
148
150
  end
149
151
 
152
+ def add_customer_detail_data(post, options)
153
+ post[:profile] ||= {}
154
+ post[:profile][:email] = options[:email] if options[:email]
155
+ post[:customerIp] = options[:ip] if options[:ip]
156
+ if (billing_address = options[:billing_address])
157
+ post[:profile][:firstName], post[:profile][:lastName] = split_names(billing_address[:name])
158
+ end
159
+ end
160
+
150
161
  def add_credit_card(post, credit_card, options = {})
151
162
  post[:card] ||= {}
152
163
  post[:card][:cardNum] = credit_card.number
@@ -60,7 +60,8 @@ module ActiveMerchant #:nodoc:
60
60
  '93', # Approved high fraud
61
61
  '94', # Approved fraud service unavailable
62
62
  'E7', # Stored
63
- 'PA' # Partial approval
63
+ 'PA', # Partial approval
64
+ 'P1' # ECP - AVS - Account Status Verification and/or AOA data is in a positive status.
64
65
  ]
65
66
 
66
67
  class_attribute :secondary_test_url, :secondary_live_url
@@ -341,7 +342,8 @@ module ActiveMerchant #:nodoc:
341
342
  gsub(%r((<CCAccountNum>).+(</CC)), '\1[FILTERED]\2').
342
343
  gsub(%r((<CardSecVal>).+(</CardSecVal>)), '\1[FILTERED]\2').
343
344
  gsub(%r((<MerchantID>).+(</MerchantID>)), '\1[FILTERED]\2').
344
- gsub(%r((<CustomerMerchantID>).+(</CustomerMerchantID>)), '\1[FILTERED]\2')
345
+ gsub(%r((<CustomerMerchantID>).+(</CustomerMerchantID>)), '\1[FILTERED]\2').
346
+ gsub(%r((<CustomerProfileMessage>).+(</CustomerProfileMessage>)), '\1[FILTERED]\2')
345
347
  end
346
348
 
347
349
  private
@@ -511,7 +513,7 @@ module ActiveMerchant #:nodoc:
511
513
 
512
514
  # Payment can be done through either Credit Card or Electronic Check
513
515
  def add_payment_source(xml, payment_source, options = {})
514
- if payment_source.instance_of?(ActiveMerchant::Billing::Check)
516
+ if payment_source.is_a?(Check)
515
517
  add_echeck(xml, payment_source, options)
516
518
  else
517
519
  add_creditcard(xml, payment_source, options[:currency])
@@ -661,16 +663,38 @@ module ActiveMerchant #:nodoc:
661
663
  end
662
664
  end
663
665
 
666
+ def add_ews_details(xml, payment_source, parameters = {})
667
+ xml.tag! :EWSFirstName, payment_source.first_name
668
+ xml.tag! :EWSLastName, payment_source.last_name
669
+ xml.tag! :EWSBusinessName, parameters[:company] if payment_source.first_name.empty? && payment_source.last_name.empty?
670
+
671
+ if (address = (parameters[:billing_address] || parameters[:address]))
672
+ xml.tag! :EWSAddressLine1, byte_limit(format_address_field(address[:address1]), 30)
673
+ xml.tag! :EWSAddressLine2, byte_limit(format_address_field(address[:address2]), 30)
674
+ xml.tag! :EWSCity, byte_limit(format_address_field(address[:city]), 20)
675
+ xml.tag! :EWSState, byte_limit(format_address_field(address[:state]), 2)
676
+ xml.tag! :EWSZip, byte_limit(format_address_field(address[:zip]), 10)
677
+ end
678
+
679
+ xml.tag! :EWSPhoneType, parameters[:phone_type]
680
+ xml.tag! :EWSPhoneNumber, parameters[:phone_number]
681
+ xml.tag! :EWSCheckSerialNumber, payment_source.account_number unless parameters[:auth_method].eql?('I')
682
+ end
683
+
664
684
  # Adds ECP conditional attributes depending on other attribute values
665
- def add_ecp_details(xml, parameters = {})
666
- requires!(parameters, :check_serial_number) if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
685
+ def add_ecp_details(xml, payment_source, parameters = {})
686
+ requires!(payment_source.account_number) if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
667
687
  xml.tag! :ECPActionCode, parameters[:action_code] if parameters[:action_code] && ECP_ACTION_CODES.include?(parameters[:action_code])
668
- xml.tag! :ECPCheckSerialNumber, parameters[:check_serial_number] if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
688
+ xml.tag! :ECPCheckSerialNumber, payment_source.account_number if parameters[:auth_method]&.eql?('A') || parameters[:auth_method]&.eql?('P')
669
689
  if parameters[:auth_method]&.eql?('P')
670
690
  xml.tag! :ECPTerminalCity, parameters[:terminal_city] if parameters[:terminal_city]
671
691
  xml.tag! :ECPTerminalState, parameters[:terminal_state] if parameters[:terminal_state]
672
692
  xml.tag! :ECPImageReferenceNumber, parameters[:image_reference_number] if parameters[:image_reference_number]
673
693
  end
694
+ if parameters[:action_code]&.eql?('W3') || parameters[:action_code]&.eql?('W5') ||
695
+ parameters[:action_code]&.eql?('W7') || parameters[:action_code]&.eql?('W9')
696
+ add_ews_details(xml, payment_source, parameters)
697
+ end
674
698
  end
675
699
 
676
700
  def add_stored_credentials(xml, parameters)
@@ -830,7 +854,7 @@ module ActiveMerchant #:nodoc:
830
854
  add_aevv(xml, payment_source, three_d_secure)
831
855
  add_digital_token_cryptogram(xml, payment_source)
832
856
 
833
- xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && ECP_SAME_DAY.include?(parameters[:same_day]) && payment_source.instance_of?(ActiveMerchant::Billing::Check)
857
+ xml.tag! :ECPSameDayInd, parameters[:same_day] if parameters[:same_day] && ECP_SAME_DAY.include?(parameters[:same_day]) && payment_source.is_a?(Check)
834
858
 
835
859
  set_recurring_ind(xml, parameters)
836
860
 
@@ -844,7 +868,7 @@ module ActiveMerchant #:nodoc:
844
868
  add_level3_purchase(xml, parameters)
845
869
  add_level3_tax(xml, parameters)
846
870
  add_line_items(xml, parameters) if parameters[:line_items]
847
- add_ecp_details(xml, parameters) if payment_source.instance_of?(ActiveMerchant::Billing::Check)
871
+ add_ecp_details(xml, payment_source, parameters) if payment_source.is_a?(Check)
848
872
  add_card_indicators(xml, parameters)
849
873
  add_stored_credentials(xml, parameters)
850
874
  add_pymt_brand_program_code(xml, payment_source, three_d_secure)
@@ -86,6 +86,11 @@ module ActiveMerchant #:nodoc:
86
86
  refund(money, identification, options)
87
87
  end
88
88
 
89
+ def verify(money, payment_source, options = {})
90
+ request = build_purchase_or_authorization_request(money, payment_source, options)
91
+ commit(:validate, request)
92
+ end
93
+
89
94
  # Token Based Billing
90
95
  #
91
96
  # Instead of storing the credit card details locally, you can store them inside the
@@ -334,7 +339,7 @@ module ActiveMerchant #:nodoc:
334
339
  def authorization_from(action, response)
335
340
  case action
336
341
  when :validate
337
- (response[:billing_id] || response[:dps_billing_id])
342
+ (response[:billing_id] || response[:dps_billing_id] || response[:dps_txn_ref])
338
343
  else
339
344
  response[:dps_txn_ref]
340
345
  end
@@ -361,7 +366,7 @@ module ActiveMerchant #:nodoc:
361
366
  # add a method to response so we can easily get the token
362
367
  # for Validate transactions
363
368
  def token
364
- @params['billing_id'] || @params['dps_billing_id']
369
+ @params['billing_id'] || @params['dps_billing_id'] || @params['dps_txn_ref']
365
370
  end
366
371
  end
367
372
  end
@@ -126,6 +126,7 @@ module ActiveMerchant #:nodoc:
126
126
  184 => 'Authentication error',
127
127
  190 => 'Refusal with no specific reason',
128
128
  191 => 'Expiry date incorrect',
129
+ 195 => 'Requires SCA authentication',
129
130
 
130
131
  201 => 'Card expired',
131
132
  202 => 'Card blocked temporarily or under suspicion of fraud',
@@ -622,7 +623,7 @@ module ActiveMerchant #:nodoc:
622
623
  def response_text(code)
623
624
  code = code.to_i
624
625
  code = 0 if code < 100
625
- RESPONSE_TEXTS[code] || 'Unkown code, please check in manual'
626
+ RESPONSE_TEXTS[code] || 'Unknown code, please check in manual'
626
627
  end
627
628
 
628
629
  def response_text_3ds(xml, params)
@@ -58,7 +58,7 @@ module ActiveMerchant #:nodoc:
58
58
  def purchase(money, payment_method, options = {})
59
59
  MultiResponse.run do |r|
60
60
  r.process { authorize(money, payment_method, options) }
61
- r.process { capture(money, r.authorization, options.merge(authorization_validated: true)) }
61
+ r.process { capture(money, r.authorization, options.merge(authorization_validated: true)) } unless options[:skip_capture]
62
62
  end
63
63
  end
64
64
 
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.118.0'
2
+ VERSION = '1.119.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.118.0
4
+ version: 1.119.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: 2021-01-22 00:00:00.000000000 Z
11
+ date: 2021-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport