UNPKG

boleto.js

Version:

Renderizador de código de barras para boletos bancários

199 lines (179 loc) 5.82 kB
const SVG = require('./svg'); const ITF = require('./itf'); const { modulo11 } = require('./helpers'); class Boleto { /** * Initializes the class * * @constructor * @param {String} bankSlipNumber The bank slip number */ constructor(bankSlipNumber) { this.bankSlipNumber = bankSlipNumber.replace(/[^\d]/g, ''); if (!this.valid()) { throw new Error('Invalid bank slip number'); } } /** * Validates whether the bank slip number is valid or not * * The validation function ensures that the bank slip number is exactly 47 * characters long, then applies the modulo-11 algorithm to the bank slip's * barcode. Finally, it verifies that the result of the algorithm equals the * checksum digit from the bank slip number. * * @return {Boolean} Whether the bank slip number is valid or not */ valid() { if (this.bankSlipNumber.length !== 47) return false; const barcodeDigits = this.barcode().split(''); const checksum = barcodeDigits.splice(4, 1); return (modulo11(barcodeDigits).toString() === checksum.toString()); } /** * Converts the printed bank slip number into the barcode number * * The bank slip's number is a rearrangement of its barcode, plus three * checksum digits. This function executes the inverse process and returns the * original arrangement of the code. Specifications can be found at * https://portal.febraban.org.br/pagina/3166/33/pt-br/layour-arrecadacao * * @return {String} The barcode extracted from the bank slip number */ barcode() { return this.bankSlipNumber.replace( /^(\d{4})(\d{5})\d{1}(\d{10})\d{1}(\d{10})\d{1}(\d{15})$/, '$1$5$2$3$4', ); } /** * Returns the bank slip's raw number * * @return {String} The raw bank slip number */ number() { return this.bankSlipNumber; } /** * Returns the bank slip number with the usual, easy-to-read mask: * 00000.00000 00000.000000 00000.000000 0 00000000000000 * * @return {String} The formatted bank slip number */ prettyNumber() { return this.bankSlipNumber.replace( /^(\d{5})(\d{5})(\d{5})(\d{6})(\d{5})(\d{6})(\d{1})(\d{14})$/, '$1.$2 $3.$4 $5.$6 $7 $8', ); } /** * Returns the name of the bank that issued the bank slip * * This function is able to identify the most popular or commonly used banks * in Brazil, but not all of them are included here. * * A comprehensive list of all Brazilian banks and their codes can be found at * http://www.buscabanco.org.br/AgenciasBancos.asp * * @return {String} The bank name */ bank() { switch (this.barcode().substr(0, 3)) { case '001': return 'Banco do Brasil'; case '007': return 'BNDES'; case '033': return 'Santander'; case '069': return 'Crefisa'; case '077': return 'Banco Inter'; case '102': return 'XP Investimentos'; case '104': return 'Caixa Econômica Federal'; case '140': return 'Easynvest'; case '197': return 'Stone'; case '208': return 'BTG Pactual'; case '212': return 'Banco Original'; case '237': return 'Bradesco'; case '260': return 'Nu Pagamentos'; case '341': return 'Itaú'; case '389': return 'Banco Mercantil do Brasil'; case '422': return 'Banco Safra'; case '505': return 'Credit Suisse'; case '633': return 'Banco Rendimento'; case '652': return 'Itaú Unibanco'; case '735': return 'Banco Neon'; case '739': return 'Banco Cetelem'; case '745': return 'Citibank'; default: return 'Unknown'; } } /** * Returns the currency of the bank slip * * The currency is determined by the currency code, the fourth digit of the * barcode. A list of values other than 9 (Brazilian Real) could not be found. * * @return {String} The currency code, symbol and decimal separator */ currency() { switch (this.barcode()[3]) { case '9': return { code: 'BRL', symbol: 'R$', decimal: ',' }; default: return 'Unknown'; } } /** * Returns the verification digit of the barcode * * The barcode has its own checksum digit, which is the fifth digit of itself. * * @return {String} The checksum of the barcode */ checksum() { return this.barcode()[4]; } /** * Returns the date when the bank slip is due * * The portion of the barcode ranging from its sixth to its nineth digits * represent the number of days since the 7th of October, 1997 up to when the * bank slip is good to be paid. Attempting to pay a bank slip after this date * may incurr in extra fees. * * @return {Date} The expiration date of the bank slip */ expirationDate() { const refDate = new Date(876236400000); // 1997-10-07 12:00:00 GMT-0300 const days = this.barcode().substr(5, 4); return new Date(refDate.getTime() + (days * 86400000)); } /** * Returns the bank slip's nominal amount * * @return {String} The bank slip's raw amount */ amount() { return (this.barcode().substr(9, 10) / 100.0).toFixed(2); } /** * Returns the bank slip's formatted nominal amount * * @return {String} The bank slip's formatted amount */ prettyAmount() { const currency = this.currency(); if (currency === 'Unknown') { return this.amount(); } return `${currency.symbol} ${this.amount().replace('.', currency.decimal)}`; } /** * Renders the bank slip as a child of the provided selector * * @param {String} selector The selector to the object where the SVG must be * appended * * @see {@link SVG#render} */ toSVG(selector) { const stripes = ITF.encode(this.barcode()); return new SVG(stripes).render(selector); } } module.exports = Boleto;