activemerchant 1.118.0 → 1.119.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: 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