Module: BrazilianUtils::BankAccountUtils

Defined in:
lib/brazilian-utils/bank-account-utils.rb

Overview

Note:

This implementation validates the account's structure (a known COMPE bankCode, agency/account digit-count limits, an allowed digit character) and a generic modulus 10 / modulus 11 fallback check digit. The distinct, published check-digit algorithms some banks use (Banco do Brasil, Santander, Banrisul, Caixa, Bradesco, Nubank/Verhoeff, Itaú, HSBC/Kirton, Citibank) are not implemented: there were no verifiable test vectors available to confirm a from- scratch reproduction of each algorithm, and shipping an unverified guess would be worse than this honestly-partial generic check.

Utilities for validating Brazilian bank accounts (bank code, agency, account and check digit).

Class Method Summary collapse

Class Method Details

.is_valid(params) ⇒ Boolean Also known as: valid?

Validates a Brazilian bank account.

Parameters:

  • params (Hash) —

    :bankCode (3 digits), :agency (1-5 digits), :account (1-13 digits) and :digit (1-2 characters, or the literal X/P used by some banks), all strings.

Returns:

  • (Boolean)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/brazilian-utils/bank-account-utils.rb', line 50

def self.is_valid(params)
  return false unless params.is_a?(Hash)

  bank_code = params[:bankCode] || params['bankCode']
  agency = params[:agency] || params['agency']
   = params[:account] || params['account']
  digit = params[:digit] || params['digit']

  return false unless [bank_code, agency, , digit].all? { |v| v.is_a?(String) }
  return false unless BankUtils.get_by_code(bank_code)
  return false unless agency.match?(/\A\d{1,5}\z/)
  return false unless .match?(/\A\d{1,13}\z/)
  return false unless digit.match?(/\A[0-9A-Za-z]{1,2}\z/)

  digit_upcase = digit.upcase
  return true if %w[X P].include?(digit_upcase) && digit.length == 1

  return false unless digit.match?(/\A\d{1,2}\z/)

  if digit.length == 2
    first_ok = digit[0].to_i == mod10_digit()
    second_ok = digit[1].to_i == mod11_digit( + digit[0])
    first_ok && second_ok
  else
    digit.to_i == mod10_digit() || digit.to_i == mod11_digit()
  end
end